Add telemetry: per-request latency metrics#43
Conversation
Instrument do_get and _get_with_optional_cache to record latency, status codes, retry attempts, cache hits, and errors. Metrics are stored in-memory with a configurable max buffer size and can be queried, summarized, or drained via public API functions. Also adds x-client-build-version header for server-side telemetry, fixes missing @responses.activate decorator in audio download test, and adds CLAUDE.md with project coding conventions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Unnecessary
getattrfor typed module attributes- Replaced getattr calls with direct access to earningscall.enable_telemetry and earningscall.telemetry_max_entries to fail fast and align with project rules.
Or push these changes by commenting:
@cursor push a3a1cdf947
Preview (a3a1cdf947)
diff --git a/earningscall/api.py b/earningscall/api.py
--- a/earningscall/api.py
+++ b/earningscall/api.py
@@ -67,7 +67,7 @@
def _get_telemetry_max_entries() -> int:
- return max(getattr(earningscall, "telemetry_max_entries", DEFAULT_TELEMETRY_MAX_ENTRIES), 0)
+ return max(earningscall.telemetry_max_entries, 0)
def _record_latency_metric(
@@ -80,7 +80,7 @@
from_cache: bool = False,
error_type: Optional[str] = None,
) -> None:
- if not getattr(earningscall, "enable_telemetry", True):
+ if not earningscall.enable_telemetry:
return
max_entries = _get_telemetry_max_entries()Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Addresses Bugbot review: these are typed module attributes defined in __init__.py, so getattr() with defaults is unnecessary defensive coding. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| "base_delay": 1, | ||
| "max_attempts": 10, | ||
| } | ||
| DEFAULT_TELEMETRY_MAX_ENTRIES = 1000 |
There was a problem hiding this comment.
Unused constant DEFAULT_TELEMETRY_MAX_ENTRIES is dead code
Low Severity
DEFAULT_TELEMETRY_MAX_ENTRIES is defined but never referenced anywhere in the codebase. The actual default value is set via earningscall.telemetry_max_entries = 1000 in earningscall/__init__.py, and _get_telemetry_max_entries() reads directly from that module attribute. This constant is dead code.
| return response | ||
| except Exception as exc: | ||
| error_type = type(exc).__name__ | ||
| raise |
There was a problem hiding this comment.
Broad except Exception contradicts project conventions in CLAUDE.md
Low Severity
Both _get_with_optional_cache and do_get use except Exception as exc: solely to capture error_type for telemetry. The CLAUDE.md file introduced in this same PR states "Never catch Exception unless top-level handler" and "Catch the most specific exception possible." The finally block could use sys.exc_info() to retrieve the exception type without needing a broad catch, keeping the code consistent with the project's own conventions.



Summary
do_getand_get_with_optional_cacheto record per-request latency metrics (duration, status code, retry attempts, cache hits, errors)enable_telemetryandtelemetry_max_entriesconfig options (renamed fromenable_latency_metricsper review feedback)get_latency_metrics(),pop_latency_metrics(),get_latency_metrics_summary(), andclear_latency_metrics()for user-side observabilityx-client-build-versionheader on all API requests for server-side telemetry@responses.activatedecorator ontest_download_audio_file_missing_params_raises_value_errorCLAUDE.mdwith project coding conventionsSupersedes #41 — rebased on current master (includes Python 3.10+ from #42).
Test plan
🤖 Generated with Claude Code
Note
Medium Risk
Touches core HTTP request paths and wraps them with new metric-recording logic, which could subtly affect request behavior/performance and error handling despite being intended as observational.
Overview
Adds in-memory request telemetry to the SDK by instrumenting
do_getand_get_with_optional_cacheto record duration, status code, retry attempts, cache hits, and raised error types, with new user configuration viaenable_telemetryandtelemetry_max_entries.Exposes telemetry helpers (
get_latency_metrics,pop_latency_metrics,clear_latency_metrics,get_latency_metrics_summary) throughearningscall.__init__, documents usage inREADME.md, and addsx-client-build-versionto request headers.Adds a new
tests/test_latency_metrics.pysuite covering collection/disable/limits/summarization, fixes a missing@responses.activatein an existing audio download test, and introducesCLAUDE.mdcontributor guidelines.Written by Cursor Bugbot for commit 63088fd. This will update automatically on new commits. Configure here.