Skip to content

Add telemetry: per-request latency metrics#43

Open
EarningsCall wants to merge 3 commits intomasterfrom
telemetry
Open

Add telemetry: per-request latency metrics#43
EarningsCall wants to merge 3 commits intomasterfrom
telemetry

Conversation

@EarningsCall
Copy link
Owner

@EarningsCall EarningsCall commented Mar 5, 2026

Summary

  • Instruments do_get and _get_with_optional_cache to record per-request latency metrics (duration, status code, retry attempts, cache hits, errors)
  • Adds enable_telemetry and telemetry_max_entries config options (renamed from enable_latency_metrics per review feedback)
  • Exports get_latency_metrics(), pop_latency_metrics(), get_latency_metrics_summary(), and clear_latency_metrics() for user-side observability
  • Sends x-client-build-version header on all API requests for server-side telemetry
  • Fixes missing @responses.activate decorator on test_download_audio_file_missing_params_raises_value_error
  • Adds CLAUDE.md with project coding conventions

Supersedes #41 — rebased on current master (includes Python 3.10+ from #42).

Test plan

  • 87 tests pass locally
  • Coverage improved from 96.4% to 97%
  • CI checks pass on all Python versions (3.10–3.14)
  • Coveralls check passes (coverage should not decrease)

🤖 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_get and _get_with_optional_cache to record duration, status code, retry attempts, cache hits, and raised error types, with new user configuration via enable_telemetry and telemetry_max_entries.

Exposes telemetry helpers (get_latency_metrics, pop_latency_metrics, clear_latency_metrics, get_latency_metrics_summary) through earningscall.__init__, documents usage in README.md, and adds x-client-build-version to request headers.

Adds a new tests/test_latency_metrics.py suite covering collection/disable/limits/summarization, fixes a missing @responses.activate in an existing audio download test, and introduces CLAUDE.md contributor guidelines.

Written by Cursor Bugbot for commit 63088fd. This will update automatically on new commits. Configure here.

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>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 getattr for 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.

Create PR

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()
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

EarningsCall and others added 2 commits March 5, 2026 07:35
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>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

return response
except Exception as exc:
error_type = type(exc).__name__
raise
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant