Skip to content
This repository was archived by the owner on Mar 18, 2026. It is now read-only.

Commit 030e6f8

Browse files
Merge pull request #436 from aibtcdev/improve-logging
improve logging
2 parents f15e5a2 + b631f81 commit 030e6f8

25 files changed

Lines changed: 2585 additions & 683 deletions

app/api/agents.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ async def get_agent_account_contract(
3535
HTTPException: If the profile or agent is not found.
3636
"""
3737
try:
38-
logger.info(
39-
f"Agent account contract lookup request received from {request.client.host if request.client else 'unknown'} for address: {stacks_address}"
38+
logger.debug(
39+
"Agent account contract lookup",
40+
extra={"stacks_address": stacks_address, "event_type": "agent_lookup"},
4041
)
4142

4243
# Look up profile by mainnet_address or testnet_address
@@ -46,18 +47,26 @@ async def get_agent_account_contract(
4647
profiles = backend.list_profiles(ProfileFilter(mainnet_address=stacks_address))
4748
if profiles:
4849
profile = profiles[0]
49-
logger.info(f"Found profile {profile.id} by mainnet address")
50+
logger.debug(
51+
"Found profile by mainnet address",
52+
extra={"profile_id": str(profile.id)},
53+
)
5054
else:
5155
# Try testnet address
5256
profiles = backend.list_profiles(
5357
ProfileFilter(testnet_address=stacks_address)
5458
)
5559
if profiles:
5660
profile = profiles[0]
57-
logger.info(f"Found profile {profile.id} by testnet address")
61+
logger.debug(
62+
"Found profile by testnet address",
63+
extra={"profile_id": str(profile.id)},
64+
)
5865

5966
if not profile:
60-
logger.error(f"No profile found for Stacks address: {stacks_address}")
67+
logger.warning(
68+
"Profile not found", extra={"stacks_address": stacks_address}
69+
)
6170
raise HTTPException(
6271
status_code=404,
6372
detail=f"No profile found for Stacks address: {stacks_address}",
@@ -66,7 +75,7 @@ async def get_agent_account_contract(
6675
# Look up agent by profile_id
6776
agents = backend.list_agents(AgentFilter(profile_id=profile.id))
6877
if not agents:
69-
logger.error(f"No agent found for profile ID: {profile.id}")
78+
logger.warning("Agent not found", extra={"profile_id": str(profile.id)})
7079
raise HTTPException(
7180
status_code=404,
7281
detail=f"No agent found for profile ID: {profile.id}",
@@ -76,14 +85,20 @@ async def get_agent_account_contract(
7685
account_contract = agent.account_contract
7786

7887
if not account_contract:
79-
logger.error(f"No account contract found for agent ID: {agent.id}")
88+
logger.warning(
89+
"Account contract missing", extra={"agent_id": str(agent.id)}
90+
)
8091
raise HTTPException(
8192
status_code=404,
8293
detail=f"No account contract found for agent ID: {agent.id}",
8394
)
8495

8596
logger.info(
86-
f"Successfully retrieved account contract for address {stacks_address}: {account_contract}"
97+
"Agent account contract retrieved",
98+
extra={
99+
"stacks_address": stacks_address,
100+
"account_contract": account_contract,
101+
},
87102
)
88103

89104
return JSONResponse(content={"account_contract": account_contract})
@@ -92,7 +107,8 @@ async def get_agent_account_contract(
92107
raise he
93108
except Exception as e:
94109
logger.error(
95-
f"Failed to lookup agent account contract for address {stacks_address}",
110+
"Agent account contract lookup failed",
111+
extra={"stacks_address": stacks_address, "error": str(e)},
96112
exc_info=e,
97113
)
98114
raise HTTPException(

app/api/daos.py

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,19 @@ def _agent_voted_in_last_proposals(
5656
VoteFilter(agent_id=agent_id, proposal_id=proposal.id)
5757
)
5858
if votes:
59-
logger.debug(f"Agent {agent_id} voted in proposal {proposal.id}")
59+
logger.debug(
60+
"Agent voted in proposal",
61+
extra={"agent_id": agent_id, "proposal_id": str(proposal.id)},
62+
)
6063
return True
6164

6265
return False
6366

6467
except Exception as e:
65-
logger.warning(f"Error checking voting history for agent {agent_id}: {str(e)}")
68+
logger.warning(
69+
"Error checking voting history",
70+
extra={"agent_id": agent_id, "error": str(e)},
71+
)
6672
return False
6773

6874

@@ -106,14 +112,20 @@ def _agent_submitted_proposal(agent_id: str, dao_id: str) -> bool:
106112
result = len(proposals) > 0
107113
if result:
108114
logger.debug(
109-
f"Agent {agent_id} (address: {agent_address}) has submitted {len(proposals)} proposals"
115+
"Agent has submitted proposals",
116+
extra={
117+
"agent_id": agent_id,
118+
"agent_address": agent_address,
119+
"proposal_count": len(proposals),
120+
},
110121
)
111122

112123
return result
113124

114125
except Exception as e:
115126
logger.warning(
116-
f"Error checking proposal submission history for agent {agent_id}: {str(e)}"
127+
"Error checking proposal submission history",
128+
extra={"agent_id": agent_id, "error": str(e)},
117129
)
118130
return False
119131

@@ -167,12 +179,15 @@ async def get_dao_token_holders(
167179
if has_submitted_proposal is not None:
168180
filters_applied.append(f"has_submitted_proposal={has_submitted_proposal}")
169181

170-
filter_str = (
171-
f" with filters: {', '.join(filters_applied)}" if filters_applied else ""
172-
)
182+
# Build filter info for logging
173183

174-
logger.info(
175-
f"DAO token holders request received from {request.client.host if request.client else 'unknown'} for token: {token_contract_principal}{filter_str}"
184+
logger.debug(
185+
"DAO token holders request",
186+
extra={
187+
"token_contract": token_contract_principal,
188+
"filters": filters_applied,
189+
"event_type": "dao_holders",
190+
},
176191
)
177192

178193
# Step 1: Find the token by contract principal
@@ -182,7 +197,7 @@ async def get_dao_token_holders(
182197

183198
if not tokens:
184199
logger.warning(
185-
f"No token found with contract principal: {token_contract_principal}"
200+
"Token not found", extra={"token_contract": token_contract_principal}
186201
)
187202
raise HTTPException(
188203
status_code=404,
@@ -191,18 +206,26 @@ async def get_dao_token_holders(
191206

192207
token = tokens[0] # Take the first matching token
193208
logger.debug(
194-
f"Found token {token.id} for contract principal: {token_contract_principal}"
209+
"Token found",
210+
extra={
211+
"token_id": str(token.id),
212+
"token_contract": token_contract_principal,
213+
},
195214
)
196215

197216
# Step 2: Find all holders of this token
198217
holders = backend.list_holders(HolderFilter(token_id=token.id))
199218

200219
if not holders:
201-
logger.info(f"No holders found for token: {token_contract_principal}")
220+
logger.info(
221+
"No token holders found",
222+
extra={"token_contract": token_contract_principal},
223+
)
202224
return JSONResponse(content={"holders": []})
203225

204226
logger.debug(
205-
f"Found {len(holders)} holders for token: {token_contract_principal}"
227+
"Token holders found",
228+
extra={"count": len(holders), "token_contract": token_contract_principal},
206229
)
207230

208231
# Step 3: Get agent account contracts for holders that have agents
@@ -212,20 +235,29 @@ async def get_dao_token_holders(
212235
try:
213236
# Skip holders without agent_id
214237
if not holder.agent_id:
215-
logger.debug(f"Holder {holder.id} has no agent_id, skipping")
238+
logger.debug(
239+
"Holder has no agent", extra={"holder_id": str(holder.id)}
240+
)
216241
continue
217242

218243
# Get the agent
219244
agent = backend.get_agent(holder.agent_id)
220245
if not agent:
221246
logger.warning(
222-
f"Agent {holder.agent_id} not found for holder {holder.id}"
247+
"Agent not found for holder",
248+
extra={
249+
"agent_id": str(holder.agent_id),
250+
"holder_id": str(holder.id),
251+
},
223252
)
224253
continue
225254

226255
# Skip agents without account contracts
227256
if not agent.account_contract:
228-
logger.debug(f"Agent {agent.id} has no account_contract")
257+
logger.debug(
258+
"Agent missing account contract",
259+
extra={"agent_id": str(agent.id)},
260+
)
229261
continue
230262

231263
# Apply filters if specified
@@ -234,7 +266,11 @@ async def get_dao_token_holders(
234266
str(agent.id), str(token.dao_id), voted_in_last_proposals
235267
):
236268
logger.debug(
237-
f"Agent {agent.id} did not vote in last {voted_in_last_proposals} proposals, skipping"
269+
"Agent filtered by voting history",
270+
extra={
271+
"agent_id": str(agent.id),
272+
"proposals_checked": voted_in_last_proposals,
273+
},
238274
)
239275
continue
240276

@@ -244,29 +280,42 @@ async def get_dao_token_holders(
244280
)
245281
if has_submitted_proposal and not agent_has_submitted:
246282
logger.debug(
247-
f"Agent {agent.id} has not submitted proposals, skipping"
283+
"Agent filtered - no proposals submitted",
284+
extra={"agent_id": str(agent.id)},
248285
)
249286
continue
250287
elif not has_submitted_proposal and agent_has_submitted:
251288
logger.debug(
252-
f"Agent {agent.id} has submitted proposals but filter excludes them, skipping"
289+
"Agent filtered - has submitted proposals",
290+
extra={"agent_id": str(agent.id)},
253291
)
254292
continue
255293

256294
# Add account contract if it passes all filters
257295
account_contracts.append(agent.account_contract)
258-
logger.debug(f"Added account contract: {agent.account_contract}")
296+
logger.debug(
297+
"Account contract added",
298+
extra={"account_contract": agent.account_contract},
299+
)
259300

260301
except Exception as e:
261-
logger.warning(f"Error processing holder {holder.id}: {str(e)}")
302+
logger.warning(
303+
"Error processing holder",
304+
extra={"holder_id": str(holder.id), "error": str(e)},
305+
)
262306
# Continue processing other holders even if one fails
263307
continue
264308

265309
# Remove duplicates and sort
266310
unique_contracts = sorted(list(set(account_contracts)))
267311

268312
logger.info(
269-
f"Successfully found {len(unique_contracts)} unique agent account contracts for token: {token_contract_principal}{filter_str}"
313+
"DAO token holders retrieved",
314+
extra={
315+
"token_contract": token_contract_principal,
316+
"unique_contracts": len(unique_contracts),
317+
"filters": filters_applied,
318+
},
270319
)
271320

272321
return JSONResponse(content={"holders": unique_contracts})
@@ -275,7 +324,8 @@ async def get_dao_token_holders(
275324
raise he
276325
except Exception as e:
277326
logger.error(
278-
f"Failed to retrieve DAO token holders for token {token_contract_principal}: {str(e)}",
327+
"DAO token holders retrieval failed",
328+
extra={"token_contract": token_contract_principal, "error": str(e)},
279329
exc_info=e,
280330
)
281331
raise HTTPException(

0 commit comments

Comments
 (0)