Skip to content

Commit 376170b

Browse files
committed
fix: rename metric to gen_ai.client.operation.time_to_first_chunk
Align metric name with semantic conventions specification: - Rename gen_ai.client.time_to_first_token to gen_ai.client.operation.time_to_first_chunk per semconv registry - Update bucket boundaries to match spec-defined values - Rename helper functions from ttft to ttfc throughout - Update all test assertions to use correct metric name Addresses reviewer feedback from @lmolkova (client, not server) and @xrmx (return all data points for assertions).
1 parent 69ab567 commit 376170b

5 files changed

Lines changed: 36 additions & 36 deletions

File tree

instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/instruments.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
from opentelemetry.util.genai.instruments import (
33
create_duration_histogram,
44
create_token_histogram,
5-
create_ttft_histogram,
5+
create_ttfc_histogram,
66
)
77

88

99
class Instruments:
1010
def __init__(self, meter: Meter):
1111
self.operation_duration_histogram: Histogram = create_duration_histogram(meter)
1212
self.token_usage_histogram: Histogram = create_token_histogram(meter)
13-
self.ttft_histogram: Histogram = create_ttft_histogram(meter)
13+
self.ttfc_histogram: Histogram = create_ttfc_histogram(meter)

instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ def _record_ttft(self):
926926
common_attributes[ServerAttributes.SERVER_PORT] = (
927927
self._request_attributes[ServerAttributes.SERVER_PORT]
928928
)
929-
self._instruments.ttft_histogram.record(
929+
self._instruments.ttfc_histogram.record(
930930
ttft,
931931
attributes=common_attributes,
932932
)

instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_ttft_metrics.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
server_attributes as ServerAttributes,
99
)
1010
from opentelemetry.util.genai.instruments import (
11-
GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN,
12-
GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN_BUCKETS,
11+
GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK,
12+
_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK_BUCKETS,
1313
get_metric_data_points,
1414
)
1515
from opentelemetry.util.genai.utils import is_experimental_mode
@@ -29,15 +29,15 @@ def test_streaming_chat_records_ttft_metric(
2929
for _ in response:
3030
pass
3131

32-
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN)
32+
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK)
3333
assert len(data_points) == 1, (
34-
"expected exactly one TTFT data point for streaming"
34+
"expected exactly one TTFC data point for streaming"
3535
)
3636

3737
data_point = data_points[0]
3838
assert data_point.sum >= 0
3939
assert data_point.count == 1
40-
assert data_point.explicit_bounds == tuple(GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN_BUCKETS)
40+
assert data_point.explicit_bounds == tuple(_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK_BUCKETS)
4141

4242
latest_experimental_enabled = is_experimental_mode()
4343
assert GenAIAttributes.GEN_AI_OPERATION_NAME in data_point.attributes
@@ -68,15 +68,15 @@ async def test_async_streaming_chat_records_ttft_metric(
6868
async for _ in response:
6969
pass
7070

71-
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN)
71+
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK)
7272
assert len(data_points) == 1, (
73-
"expected exactly one TTFT data point for async streaming"
73+
"expected exactly one TTFC data point for async streaming"
7474
)
7575

7676
data_point = data_points[0]
7777
assert data_point.sum >= 0
7878
assert data_point.count == 1
79-
assert data_point.explicit_bounds == tuple(GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN_BUCKETS)
79+
assert data_point.explicit_bounds == tuple(_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK_BUCKETS)
8080

8181

8282
def test_non_streaming_chat_does_not_record_ttft_metric(
@@ -88,9 +88,9 @@ def test_non_streaming_chat_does_not_record_ttft_metric(
8888
messages=USER_ONLY_PROMPT, model=DEFAULT_MODEL, stream=False
8989
)
9090

91-
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN)
91+
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK)
9292
assert len(data_points) == 0, (
93-
"gen_ai.client.time_to_first_token metric should not be recorded for non-streaming"
93+
"gen_ai.client.operation.time_to_first_chunk metric should not be recorded for non-streaming"
9494
)
9595

9696

@@ -124,9 +124,9 @@ def test_streaming_tool_calls_records_ttft_metric(
124124
for _ in response:
125125
pass
126126

127-
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN)
127+
data_points = get_metric_data_points(metric_reader, GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK)
128128
assert len(data_points) == 1, (
129-
"expected exactly one TTFT data point for streaming tool calls"
129+
"expected exactly one TTFC data point for streaming tool calls"
130130
)
131131

132132
data_point = data_points[0]

util/opentelemetry-util-genai/src/opentelemetry/util/genai/instruments.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,25 @@
3535
67108864,
3636
]
3737

38-
GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN = "gen_ai.client.time_to_first_token"
38+
GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK = (
39+
"gen_ai.client.operation.time_to_first_chunk"
40+
)
3941

40-
GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN_BUCKETS = [
41-
0.001,
42-
0.005,
42+
_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK_BUCKETS = [
4343
0.01,
4444
0.02,
4545
0.04,
46-
0.06,
4746
0.08,
48-
0.1,
49-
0.25,
50-
0.5,
51-
0.75,
52-
1.0,
53-
2.5,
54-
5.0,
55-
7.5,
56-
10.0,
47+
0.16,
48+
0.32,
49+
0.64,
50+
1.28,
51+
2.56,
52+
5.12,
53+
10.24,
54+
20.48,
55+
40.96,
56+
81.92,
5757
]
5858

5959

@@ -75,12 +75,12 @@ def create_token_histogram(meter: Meter) -> Histogram:
7575
)
7676

7777

78-
def create_ttft_histogram(meter: Meter) -> Histogram:
78+
def create_ttfc_histogram(meter: Meter) -> Histogram:
7979
return meter.create_histogram(
80-
name=GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN,
81-
description="Time to generate first token for successful responses",
80+
name=GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK,
81+
description="Time to receive the first chunk in a streaming response",
8282
unit="s",
83-
explicit_bucket_boundaries_advisory=GEN_AI_CLIENT_TIME_TO_FIRST_TOKEN_BUCKETS,
83+
explicit_bucket_boundaries_advisory=_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK_BUCKETS,
8484
)
8585

8686

util/opentelemetry-util-genai/src/opentelemetry/util/genai/metrics.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from opentelemetry.util.genai.instruments import (
1818
create_duration_histogram,
1919
create_token_histogram,
20-
create_ttft_histogram,
20+
create_ttfc_histogram,
2121
)
2222
from opentelemetry.util.genai.types import LLMInvocation
2323
from opentelemetry.util.types import AttributeValue
@@ -29,7 +29,7 @@ class InvocationMetricsRecorder:
2929
def __init__(self, meter: Meter):
3030
self._duration_histogram: Histogram = create_duration_histogram(meter)
3131
self._token_histogram: Histogram = create_token_histogram(meter)
32-
self._ttft_histogram: Histogram = create_ttft_histogram(meter)
32+
self._ttfc_histogram: Histogram = create_ttfc_histogram(meter)
3333

3434
def record(
3535
self,
@@ -108,7 +108,7 @@ def record(
108108
)
109109

110110
if invocation.time_to_first_token_s is not None and not error_type:
111-
self._ttft_histogram.record(
111+
self._ttfc_histogram.record(
112112
invocation.time_to_first_token_s,
113113
attributes=attributes,
114114
context=span_context,

0 commit comments

Comments
 (0)