fix(pr specific): passes pre-commit

This commit is contained in:
Emilio Garcia 2025-10-03 12:35:09 -04:00
parent 4aa2dc110d
commit 2b7a765d02
20 changed files with 547 additions and 516 deletions

View file

@ -41,17 +41,17 @@ class TestOTelTelemetryProviderInitialization:
def test_initialization_with_valid_config(self, otel_config, monkeypatch):
"""Test that provider initializes correctly with valid configuration."""
monkeypatch.setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4318")
provider = OTelTelemetryProvider(config=otel_config)
assert provider.config == otel_config
def test_initialization_sets_service_attributes(self, otel_config, monkeypatch):
"""Test that service attributes are properly configured."""
monkeypatch.setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4318")
provider = OTelTelemetryProvider(config=otel_config)
assert provider.config.service_name == "test-service"
assert provider.config.service_version == "1.0.0"
assert provider.config.deployment_environment == "test"
@ -65,9 +65,9 @@ class TestOTelTelemetryProviderInitialization:
deployment_environment="test",
span_processor="batch",
)
provider = OTelTelemetryProvider(config=config)
assert provider.config.span_processor == "batch"
def test_warns_when_endpoints_missing(self, otel_config, monkeypatch, caplog):
@ -76,9 +76,9 @@ class TestOTelTelemetryProviderInitialization:
monkeypatch.delenv("OTEL_EXPORTER_OTLP_ENDPOINT", raising=False)
monkeypatch.delenv("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", raising=False)
monkeypatch.delenv("OTEL_EXPORTER_OTLP_METRICS_ENDPOINT", raising=False)
OTelTelemetryProvider(config=otel_config)
# Check that warnings were logged
assert any("Traces will not be exported" in record.message for record in caplog.records)
assert any("Metrics will not be exported" in record.message for record in caplog.records)
@ -90,44 +90,41 @@ class TestOTelTelemetryProviderTracerAPI:
def test_get_tracer_returns_tracer(self, otel_provider):
"""Test that get_tracer returns a valid Tracer instance."""
tracer = otel_provider.get_tracer("test.module")
assert tracer is not None
assert isinstance(tracer, Tracer)
def test_get_tracer_with_version(self, otel_provider):
"""Test that get_tracer works with version parameter."""
tracer = otel_provider.get_tracer(
instrumenting_module_name="test.module",
instrumenting_library_version="1.0.0"
instrumenting_module_name="test.module", instrumenting_library_version="1.0.0"
)
assert tracer is not None
assert isinstance(tracer, Tracer)
def test_get_tracer_with_attributes(self, otel_provider):
"""Test that get_tracer works with attributes."""
tracer = otel_provider.get_tracer(
instrumenting_module_name="test.module",
attributes={"component": "test", "tier": "backend"}
instrumenting_module_name="test.module", attributes={"component": "test", "tier": "backend"}
)
assert tracer is not None
assert isinstance(tracer, Tracer)
def test_get_tracer_with_schema_url(self, otel_provider):
"""Test that get_tracer works with schema URL."""
tracer = otel_provider.get_tracer(
instrumenting_module_name="test.module",
schema_url="https://example.com/schema"
instrumenting_module_name="test.module", schema_url="https://example.com/schema"
)
assert tracer is not None
assert isinstance(tracer, Tracer)
def test_tracer_can_create_spans(self, otel_provider):
"""Test that tracer can create spans."""
tracer = otel_provider.get_tracer("test.module")
with tracer.start_as_current_span("test.operation") as span:
assert span is not None
assert span.is_recording()
@ -135,11 +132,8 @@ class TestOTelTelemetryProviderTracerAPI:
def test_tracer_can_create_spans_with_attributes(self, otel_provider):
"""Test that tracer can create spans with attributes."""
tracer = otel_provider.get_tracer("test.module")
with tracer.start_as_current_span(
"test.operation",
attributes={"user.id": "123", "request.id": "abc"}
) as span:
with tracer.start_as_current_span("test.operation", attributes={"user.id": "123", "request.id": "abc"}) as span:
assert span is not None
assert span.is_recording()
@ -147,7 +141,7 @@ class TestOTelTelemetryProviderTracerAPI:
"""Test that multiple tracers can be created."""
tracer1 = otel_provider.get_tracer("module.one")
tracer2 = otel_provider.get_tracer("module.two")
assert tracer1 is not None
assert tracer2 is not None
# Tracers with different names might be the same instance or different
@ -164,50 +158,37 @@ class TestOTelTelemetryProviderMeterAPI:
def test_get_meter_returns_meter(self, otel_provider):
"""Test that get_meter returns a valid Meter instance."""
meter = otel_provider.get_meter("test.meter")
assert meter is not None
assert isinstance(meter, Meter)
def test_get_meter_with_version(self, otel_provider):
"""Test that get_meter works with version parameter."""
meter = otel_provider.get_meter(
name="test.meter",
version="1.0.0"
)
meter = otel_provider.get_meter(name="test.meter", version="1.0.0")
assert meter is not None
assert isinstance(meter, Meter)
def test_get_meter_with_attributes(self, otel_provider):
"""Test that get_meter works with attributes."""
meter = otel_provider.get_meter(
name="test.meter",
attributes={"service": "test", "env": "dev"}
)
meter = otel_provider.get_meter(name="test.meter", attributes={"service": "test", "env": "dev"})
assert meter is not None
assert isinstance(meter, Meter)
def test_get_meter_with_schema_url(self, otel_provider):
"""Test that get_meter works with schema URL."""
meter = otel_provider.get_meter(
name="test.meter",
schema_url="https://example.com/schema"
)
meter = otel_provider.get_meter(name="test.meter", schema_url="https://example.com/schema")
assert meter is not None
assert isinstance(meter, Meter)
def test_meter_can_create_counter(self, otel_provider):
"""Test that meter can create counters."""
meter = otel_provider.get_meter("test.meter")
counter = meter.create_counter(
"test.requests.total",
unit="requests",
description="Total requests"
)
counter = meter.create_counter("test.requests.total", unit="requests", description="Total requests")
assert counter is not None
# Test that counter can be used
counter.add(1, {"endpoint": "/test"})
@ -215,13 +196,9 @@ class TestOTelTelemetryProviderMeterAPI:
def test_meter_can_create_histogram(self, otel_provider):
"""Test that meter can create histograms."""
meter = otel_provider.get_meter("test.meter")
histogram = meter.create_histogram(
"test.request.duration",
unit="ms",
description="Request duration"
)
histogram = meter.create_histogram("test.request.duration", unit="ms", description="Request duration")
assert histogram is not None
# Test that histogram can be used
histogram.record(42.5, {"method": "GET"})
@ -229,13 +206,11 @@ class TestOTelTelemetryProviderMeterAPI:
def test_meter_can_create_up_down_counter(self, otel_provider):
"""Test that meter can create up/down counters."""
meter = otel_provider.get_meter("test.meter")
up_down_counter = meter.create_up_down_counter(
"test.active.connections",
unit="connections",
description="Active connections"
"test.active.connections", unit="connections", description="Active connections"
)
assert up_down_counter is not None
# Test that up/down counter can be used
up_down_counter.add(5)
@ -244,31 +219,28 @@ class TestOTelTelemetryProviderMeterAPI:
def test_meter_can_create_observable_gauge(self, otel_provider):
"""Test that meter can create observable gauges."""
meter = otel_provider.get_meter("test.meter")
def gauge_callback(options):
return [{"attributes": {"host": "localhost"}, "value": 42.0}]
gauge = meter.create_observable_gauge(
"test.memory.usage",
callbacks=[gauge_callback],
unit="bytes",
description="Memory usage"
"test.memory.usage", callbacks=[gauge_callback], unit="bytes", description="Memory usage"
)
assert gauge is not None
def test_multiple_instruments_from_same_meter(self, otel_provider):
"""Test that a meter can create multiple instruments."""
meter = otel_provider.get_meter("test.meter")
counter = meter.create_counter("test.counter")
histogram = meter.create_histogram("test.histogram")
up_down_counter = meter.create_up_down_counter("test.gauge")
assert counter is not None
assert histogram is not None
assert up_down_counter is not None
# Verify they all work
counter.add(1)
histogram.record(10.0)
@ -281,107 +253,101 @@ class TestOTelTelemetryProviderNativeUsage:
def test_complete_tracing_workflow(self, otel_provider):
"""Test a complete tracing workflow using native OTel API."""
tracer = otel_provider.get_tracer("llama_stack.inference")
# Create parent span
with tracer.start_as_current_span("inference.request") as parent_span:
parent_span.set_attribute("model", "llama-3.2-1b")
parent_span.set_attribute("user", "test-user")
# Create child span
with tracer.start_as_current_span("model.load") as child_span:
child_span.set_attribute("model.size", "1B")
assert child_span.is_recording()
# Create another child span
with tracer.start_as_current_span("inference.execute") as child_span:
child_span.set_attribute("tokens.input", 25)
child_span.set_attribute("tokens.output", 150)
assert child_span.is_recording()
assert parent_span.is_recording()
def test_complete_metrics_workflow(self, otel_provider):
"""Test a complete metrics workflow using native OTel API."""
meter = otel_provider.get_meter("llama_stack.metrics")
# Create various instruments
request_counter = meter.create_counter(
"llama.requests.total",
unit="requests",
description="Total requests"
)
request_counter = meter.create_counter("llama.requests.total", unit="requests", description="Total requests")
latency_histogram = meter.create_histogram(
"llama.inference.duration",
unit="ms",
description="Inference duration"
"llama.inference.duration", unit="ms", description="Inference duration"
)
active_sessions = meter.create_up_down_counter(
"llama.sessions.active",
unit="sessions",
description="Active sessions"
"llama.sessions.active", unit="sessions", description="Active sessions"
)
# Use the instruments
request_counter.add(1, {"endpoint": "/chat", "status": "success"})
latency_histogram.record(123.45, {"model": "llama-3.2-1b"})
active_sessions.add(1)
active_sessions.add(-1)
# No exceptions means success
def test_concurrent_tracer_usage(self, otel_provider):
"""Test that multiple threads can use tracers concurrently."""
def create_spans(thread_id):
tracer = otel_provider.get_tracer(f"test.module.{thread_id}")
for i in range(10):
with tracer.start_as_current_span(f"operation.{i}") as span:
span.set_attribute("thread.id", thread_id)
span.set_attribute("iteration", i)
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(create_spans, i) for i in range(10)]
concurrent.futures.wait(futures)
# If we get here without exceptions, thread safety is working
def test_concurrent_meter_usage(self, otel_provider):
"""Test that multiple threads can use meters concurrently."""
def record_metrics(thread_id):
meter = otel_provider.get_meter(f"test.meter.{thread_id}")
counter = meter.create_counter(f"test.counter.{thread_id}")
histogram = meter.create_histogram(f"test.histogram.{thread_id}")
for i in range(10):
counter.add(1, {"thread": str(thread_id)})
histogram.record(float(i * 10), {"thread": str(thread_id)})
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(record_metrics, i) for i in range(10)]
concurrent.futures.wait(futures)
# If we get here without exceptions, thread safety is working
def test_mixed_tracing_and_metrics(self, otel_provider):
"""Test using both tracing and metrics together."""
tracer = otel_provider.get_tracer("test.module")
meter = otel_provider.get_meter("test.meter")
counter = meter.create_counter("operations.count")
histogram = meter.create_histogram("operation.duration")
# Trace an operation while recording metrics
with tracer.start_as_current_span("test.operation") as span:
counter.add(1)
span.set_attribute("step", "start")
histogram.record(50.0)
span.set_attribute("step", "processing")
counter.add(1)
span.set_attribute("step", "complete")
# No exceptions means success
@ -391,14 +357,14 @@ class TestOTelTelemetryProviderFastAPIMiddleware:
def test_fastapi_middleware(self, otel_provider):
"""Test that fastapi_middleware can be called."""
mock_app = MagicMock()
# Should not raise an exception
otel_provider.fastapi_middleware(mock_app)
def test_fastapi_middleware_is_idempotent(self, otel_provider):
"""Test that calling fastapi_middleware multiple times is safe."""
mock_app = MagicMock()
# Should be able to call multiple times without error
otel_provider.fastapi_middleware(mock_app)
# Note: Second call might warn but shouldn't fail
@ -411,27 +377,27 @@ class TestOTelTelemetryProviderEdgeCases:
def test_tracer_with_empty_module_name(self, otel_provider):
"""Test that get_tracer works with empty module name."""
tracer = otel_provider.get_tracer("")
assert tracer is not None
assert isinstance(tracer, Tracer)
def test_meter_with_empty_name(self, otel_provider):
"""Test that get_meter works with empty name."""
meter = otel_provider.get_meter("")
assert meter is not None
assert isinstance(meter, Meter)
def test_meter_instruments_with_special_characters(self, otel_provider):
"""Test that metric names with dots, underscores, and hyphens work."""
meter = otel_provider.get_meter("test.meter")
counter = meter.create_counter("test.counter_name-special")
histogram = meter.create_histogram("test.histogram_name-special")
assert counter is not None
assert histogram is not None
# Verify they can be used
counter.add(1)
histogram.record(10.0)
@ -440,7 +406,7 @@ class TestOTelTelemetryProviderEdgeCases:
"""Test that counters work with zero value."""
meter = otel_provider.get_meter("test.meter")
counter = meter.create_counter("test.counter")
# Should not raise an exception
counter.add(0.0)
@ -448,7 +414,7 @@ class TestOTelTelemetryProviderEdgeCases:
"""Test that histograms accept negative values."""
meter = otel_provider.get_meter("test.meter")
histogram = meter.create_histogram("test.histogram")
# Should not raise an exception
histogram.record(-10.0)
@ -456,7 +422,7 @@ class TestOTelTelemetryProviderEdgeCases:
"""Test that up/down counters work with negative values."""
meter = otel_provider.get_meter("test.meter")
up_down_counter = meter.create_up_down_counter("test.updown")
# Should not raise an exception
up_down_counter.add(-5.0)
@ -464,7 +430,7 @@ class TestOTelTelemetryProviderEdgeCases:
"""Test that empty attributes dict is handled correctly."""
meter = otel_provider.get_meter("test.meter")
counter = meter.create_counter("test.counter")
# Should not raise an exception
counter.add(1.0, attributes={})
@ -472,7 +438,7 @@ class TestOTelTelemetryProviderEdgeCases:
"""Test that None attributes are handled correctly."""
meter = otel_provider.get_meter("test.meter")
counter = meter.create_counter("test.counter")
# Should not raise an exception
counter.add(1.0, attributes=None)
@ -484,28 +450,28 @@ class TestOTelTelemetryProviderRealisticScenarios:
"""Simulate telemetry for a complete inference request."""
tracer = otel_provider.get_tracer("llama_stack.inference")
meter = otel_provider.get_meter("llama_stack.metrics")
# Create instruments
request_counter = meter.create_counter("llama.requests.total")
token_counter = meter.create_counter("llama.tokens.total")
latency_histogram = meter.create_histogram("llama.request.duration_ms")
in_flight_gauge = meter.create_up_down_counter("llama.requests.in_flight")
# Simulate request
with tracer.start_as_current_span("inference.request") as request_span:
request_span.set_attribute("model.id", "llama-3.2-1b")
request_span.set_attribute("user.id", "test-user")
request_counter.add(1, {"model": "llama-3.2-1b"})
in_flight_gauge.add(1)
# Simulate token counting
token_counter.add(25, {"type": "input", "model": "llama-3.2-1b"})
token_counter.add(150, {"type": "output", "model": "llama-3.2-1b"})
# Simulate latency
latency_histogram.record(125.5, {"model": "llama-3.2-1b"})
in_flight_gauge.add(-1)
request_span.set_attribute("tokens.input", 25)
request_span.set_attribute("tokens.output", 150)
@ -514,36 +480,36 @@ class TestOTelTelemetryProviderRealisticScenarios:
"""Simulate a multi-step workflow with nested spans."""
tracer = otel_provider.get_tracer("llama_stack.workflow")
meter = otel_provider.get_meter("llama_stack.workflow.metrics")
step_counter = meter.create_counter("workflow.steps.completed")
with tracer.start_as_current_span("workflow.execute") as root_span:
root_span.set_attribute("workflow.id", "wf-123")
# Step 1: Validate
with tracer.start_as_current_span("step.validate") as span:
span.set_attribute("validation.result", "pass")
step_counter.add(1, {"step": "validate", "status": "success"})
# Step 2: Process
with tracer.start_as_current_span("step.process") as span:
span.set_attribute("items.processed", 100)
step_counter.add(1, {"step": "process", "status": "success"})
# Step 3: Finalize
with tracer.start_as_current_span("step.finalize") as span:
span.set_attribute("output.size", 1024)
step_counter.add(1, {"step": "finalize", "status": "success"})
root_span.set_attribute("workflow.status", "completed")
def test_error_handling_with_telemetry(self, otel_provider):
"""Test telemetry when errors occur."""
tracer = otel_provider.get_tracer("llama_stack.errors")
meter = otel_provider.get_meter("llama_stack.errors.metrics")
error_counter = meter.create_counter("llama.errors.total")
with tracer.start_as_current_span("operation.with.error") as span:
try:
span.set_attribute("step", "processing")
@ -553,24 +519,24 @@ class TestOTelTelemetryProviderRealisticScenarios:
span.record_exception(e)
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
error_counter.add(1, {"error.type": "ValueError"})
# Should not raise - error was handled
def test_batch_operations_telemetry(self, otel_provider):
"""Test telemetry for batch operations."""
tracer = otel_provider.get_tracer("llama_stack.batch")
meter = otel_provider.get_meter("llama_stack.batch.metrics")
batch_counter = meter.create_counter("llama.batch.items.processed")
batch_duration = meter.create_histogram("llama.batch.duration_ms")
with tracer.start_as_current_span("batch.process") as batch_span:
batch_span.set_attribute("batch.size", 100)
for i in range(100):
with tracer.start_as_current_span(f"item.{i}") as item_span:
item_span.set_attribute("item.index", i)
batch_counter.add(1, {"status": "success"})
batch_duration.record(5000.0, {"batch.size": "100"})
batch_span.set_attribute("batch.status", "completed")