debug(contacts): Add detailed logging to diagnose last_seen matching issue

Add comprehensive debug logging to trace last_seen data flow:

cli.py (get_contacts_with_last_seen):
- Log apply_to command success/failure with error details
- Log number of bytes returned by command
- Log number of contacts parsed from JSON
- Log sample contact with public_key prefix and last_advert value
- Log raw output on JSON parse errors

api.py (get_contacts_detailed_api):
- Log number of detailed contacts retrieved
- Log number of matched contacts after merging
- Fix case sensitivity: normalize both prefix and full_key to lowercase

This will help identify why all contacts show "Last seen: Unknown".

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
MarekWo
2025-12-29 13:11:21 +01:00
parent 7f819b63c7
commit d49cfefca2
2 changed files with 18 additions and 2 deletions

View File

@@ -553,27 +553,37 @@ def get_contacts_with_last_seen() -> Tuple[bool, Dict[str, Dict], str]:
success, stdout, stderr = _run_command(['apply_to', 't=1,t=2,t=3,t=4', 'contact_info'])
if not success:
logger.error(f"apply_to contact_info failed: {stderr}")
return False, {}, stderr or 'Failed to get contact details'
logger.info(f"apply_to contact_info returned {len(stdout)} bytes")
# Parse JSON output
try:
# The output should be a JSON array
contact_list = json.loads(stdout)
if not isinstance(contact_list, list):
logger.error(f"Unexpected response type: {type(contact_list)}")
return False, {}, 'Unexpected response format (expected JSON array)'
logger.info(f"Parsed {len(contact_list)} contacts from JSON")
# Build dictionary indexed by public_key for easy lookup
contacts_dict = {}
for contact in contact_list:
if 'public_key' in contact:
# Use full public key as index
contacts_dict[contact['public_key']] = contact
# Log first contact for debugging
if len(contacts_dict) == 1:
logger.info(f"Sample contact: public_key={contact['public_key'][:12]}..., last_advert={contact.get('last_advert', 'MISSING')}")
return True, contacts_dict, ""
except json.JSONDecodeError as e:
logger.error(f"Failed to parse contact_info JSON: {e}")
logger.error(f"Raw output (first 500 chars): {stdout[:500]}")
return False, {}, f'JSON parse error: {str(e)}'
except Exception as e:

View File

@@ -1245,17 +1245,23 @@ def get_contacts_detailed_api():
success_detailed, contacts_detailed, error_detailed = cli.get_contacts_with_last_seen()
if success_detailed:
logger.info(f"Got {len(contacts_detailed)} detailed contacts")
# Merge last_advert data with contacts
# Match by public_key_prefix (first 12 chars of full public_key)
matched_count = 0
for contact in contacts:
prefix = contact.get('public_key_prefix', '')
prefix = contact.get('public_key_prefix', '').lower()
# Find matching contact in detailed data
for full_key, details in contacts_detailed.items():
if full_key.startswith(prefix):
if full_key.lower().startswith(prefix):
# Add last_seen timestamp
contact['last_seen'] = details.get('last_advert', None)
matched_count += 1
break
logger.info(f"Matched {matched_count} out of {len(contacts)} contacts with last_seen data")
else:
# If detailed fetch failed, log warning but still return contacts without last_seen
logger.warning(f"Failed to get last_seen data: {error_detailed}")