Repository navigation
fix: type errors in tracing and a2a adapter, check extras in CI - #290
Conversation
mypy reported 18 errors in tracing.py and the a2a adapter when run with all extras installed. CI never saw them because the lint and test jobs install without extras. The same gap let #289 pass CI while breaking the a2a adapter at runtime. tracing.py: type the exporter argument, pass endpoint directly, import the two OTLP exporters under distinct names, drop the dead provider reassignment. a2a: import SecurityScheme unconditionally, remove the executor fallback that enqueued a raw dict. CI: lint and test jobs install all extras. test_tracing.py: skip on opentelemetry.sdk instead of the bare namespace package, which resolves to an empty leftover directory after the extras are uninstalled from a venv.
QualOps Code Quality AnalysisStatus: Summary
🟠 High Issues (2)
🟡 Medium Issues (1)
📊 Full ReportPowered by QualOps |
|
Checked each QualOps finding against the installed libraries and against main. None of them holds. The two low findings were filtered out of the report by QualOps itself (the run log ends with "Low Issues: 0"), so there is nothing to check there. 1.
|
| variant | provider pre-registered | new threads after setup_tracing("console") |
processors on global provider |
|---|---|---|---|
| main | yes | OtelBatchSpanRecordProcessor |
0 |
| branch | yes | OtelBatchSpanRecordProcessor |
0 |
| main | no | OtelBatchSpanRecordProcessor |
1 |
| branch | no | OtelBatchSpanRecordProcessor |
1 |
The orphaned processor when a provider already exists is pre-existing behaviour, not introduced here. Could be tightened in a separate change by building the provider only inside the proxy check.
3. endpoint=None vs omitting the argument (tracing.py:138, medium)
Both exporters declare endpoint: str | None = None, so omitting the argument binds None. Both resolve it as endpoint or environ.get(...). Constructing each exporter both ways and comparing the resolved _endpoint:
| environment | http omitted / endpoint=None |
grpc omitted / endpoint=None |
|---|---|---|
| none | http://localhost:4318/v1/traces both |
localhost:4317 both |
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318 |
http://collector:4318/v1/traces both |
collector:4318 both |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://traces:9999/v1/traces |
http://traces:9999/v1/traces both |
traces:9999 both |
Every pair is equal.
Summary
Running mypy with all extras installed reports 18 errors in
eggai/tracing.py,eggai/adapters/a2a/config.pyandeggai/adapters/a2a/executor.py. CI never sees them because the lint and test jobs runpoetry installwithout extras, so the a2a, mcp and otel modules are neither type checked nor tested. This is the same gap that let #289 pass CI green while breaking the a2a adapter at runtime.Changes
tracing.py
exporteris typed asstr | SpanExporter. A pre-built exporter is detected withisinstanceinstead ofhasattr.OTLPSpanExporterclasses are imported under distinct names and receiveendpointdirectly instead of an unpacked dict.elsebranch that reassignedproviderto the API type is removed. The variable was not used after it.service_name or os.getenv("OTEL_SERVICE_NAME") or "eggai". The previousos.getenv(key, "eggai")form makes mypy inferstr | Nonebecause the left operand oforis used as type context for the generic default.a2a adapter
config.pyimportsSecuritySchemeunconditionally. The executor already requires the a2a SDK, and the plugin is only imported when a2a kwargs are passed to the agent.executor.pybuilds and enqueues theMessagedirectly. The fallback that enqueued a raw dict was the type error and could not work at runtime.CI
--all-extras.tests/test_tracing.py
opentelemetry.sdkinstead ofopentelemetry. The bare name is a namespace package, so it imports from an empty directory left behind after the otel extras are uninstalled from a venv, and collection then fails on the next import.Validation
Also checked at runtime that all four
setup_tracingexporter paths attach the expected exporter, and that_send_agent_responseenqueues aMessageon anEventQueue.