Skip to content

Commit 4ee7599

Browse files
committed
refine meter uploader
1 parent 8fdae92 commit 4ee7599

File tree

4 files changed

+79
-89
lines changed

4 files changed

+79
-89
lines changed

veadk/tracing/telemetry/exporters/apmplus_exporter.py

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414

1515
from typing import Any
1616

17+
from google.adk.models.llm_request import LlmRequest
18+
from google.adk.models.llm_response import LlmResponse
19+
from opentelemetry import metrics
1720
from opentelemetry import metrics as metrics_api
1821
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
1922
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
23+
from opentelemetry.metrics._internal import Meter
2024
from opentelemetry.sdk import metrics as metrics_sdk
2125
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
2226
from opentelemetry.sdk.resources import Resource
@@ -26,12 +30,76 @@
2630

2731
from veadk.config import getenv
2832
from veadk.tracing.telemetry.exporters.base_exporter import BaseExporter
29-
from veadk.tracing.telemetry.metrics.opentelemetry_metrics import MeterUploader
3033
from veadk.utils.logger import get_logger
3134

3235
logger = get_logger(__name__)
3336

3437

38+
class MeterUploader:
39+
def __init__(
40+
self, name: str, endpoint: str, headers: dict, resource_attributes: dict
41+
) -> None:
42+
# global_metrics_provider -> global_tracer_provider
43+
# exporter -> exporter
44+
# metric_reader -> processor
45+
global_metrics_provider = metrics_api.get_meter_provider()
46+
47+
# 1. init resource
48+
if hasattr(global_metrics_provider, "_sdk_config"):
49+
global_resource = global_metrics_provider._sdk_config.resource # type: ignore
50+
else:
51+
global_resource = Resource.create()
52+
53+
resource = global_resource.merge(Resource.create(resource_attributes))
54+
55+
# 2. init exporter and reader
56+
exporter = OTLPMetricExporter(endpoint=endpoint, headers=headers)
57+
metric_reader = PeriodicExportingMetricReader(exporter)
58+
59+
metrics_api.set_meter_provider(
60+
metrics_sdk.MeterProvider(metric_readers=[metric_reader], resource=resource)
61+
)
62+
63+
# 3. init meter
64+
self.meter: Meter = metrics.get_meter(name=name)
65+
66+
# create meter attributes
67+
self.llm_invoke_counter = self.meter.create_counter(
68+
name="gen_ai.chat.count",
69+
description="Number of LLM invocations",
70+
unit="count",
71+
)
72+
self.token_usage = self.meter.create_histogram(
73+
name="gen_ai.client.token.usage",
74+
description="Token consumption of LLM invocations",
75+
unit="count",
76+
)
77+
78+
def record(self, llm_request: LlmRequest, llm_response: LlmResponse) -> None:
79+
attributes = {
80+
"gen_ai_system": "volcengine",
81+
"gen_ai_response_model": llm_request.model,
82+
"gen_ai_operation_name": "chat_completions",
83+
"stream": "false",
84+
"server_address": "api.volcengine.com",
85+
} # required by Volcengine APMPlus
86+
87+
if llm_response.usage_metadata:
88+
# llm invocation number += 1
89+
self.llm_invoke_counter.add(1, attributes)
90+
91+
# upload token usage
92+
input_token = llm_response.usage_metadata.prompt_token_count
93+
output_token = llm_response.usage_metadata.candidates_token_count
94+
95+
if input_token:
96+
token_attributes = {**attributes, "gen_ai_token_type": "input"}
97+
self.token_usage.record(input_token, attributes=token_attributes)
98+
if output_token:
99+
token_attributes = {**attributes, "gen_ai_token_type": "output"}
100+
self.token_usage.record(output_token, attributes=token_attributes)
101+
102+
35103
class APMPlusExporterConfig(BaseModel):
36104
endpoint: str = Field(
37105
default_factory=lambda: getenv(
@@ -69,25 +137,13 @@ def model_post_init(self, context: Any) -> None:
69137
endpoint=self.config.endpoint, insecure=True, headers=self.headers
70138
)
71139
self.processor = BatchSpanProcessor(self._exporter)
72-
self.meter_uploader = self._init_meter_uploader(exporter_id="apmplus")
73-
74-
def _init_meter_uploader(self, exporter_id: str) -> MeterUploader:
75-
global_metrics_provider = metrics_api.get_meter_provider()
76-
if hasattr(global_metrics_provider, "_sdk_config"):
77-
global_resource = global_metrics_provider._sdk_config.resource
78-
else:
79-
global_resource = Resource.create()
80-
resource = global_resource.merge(Resource.create(self.resource_attributes))
81-
82-
exporter = OTLPMetricExporter(
83-
endpoint=self.config.endpoint, headers=self.headers
84-
)
85-
metric_reader = PeriodicExportingMetricReader(exporter)
86140

87-
metrics_api.set_meter_provider(
88-
metrics_sdk.MeterProvider(metric_readers=[metric_reader], resource=resource)
141+
self.meter_uploader = MeterUploader(
142+
name="apmplus_meter",
143+
endpoint=self.config.endpoint,
144+
headers=self.headers,
145+
resource_attributes=self.resource_attributes,
89146
)
90-
return MeterUploader(exporter_id=exporter_id)
91147

92148
@override
93149
def export(self) -> None:

veadk/tracing/telemetry/metrics/__init__.py

Lines changed: 0 additions & 13 deletions
This file was deleted.

veadk/tracing/telemetry/metrics/opentelemetry_metrics.py

Lines changed: 0 additions & 55 deletions
This file was deleted.

veadk/tracing/telemetry/telemetry.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434

3535

3636
def upload_metrics(
37-
invocation_context: InvocationContext, llm_response: LlmResponse
37+
invocation_context: InvocationContext,
38+
llm_request: LlmRequest,
39+
llm_response: LlmResponse,
3840
) -> None:
3941
from veadk.agent import Agent
4042

@@ -43,7 +45,7 @@ def upload_metrics(
4345
for tracer in tracers:
4446
for exporter in getattr(tracer, "exporters", []):
4547
if getattr(exporter, "meter_uploader", None):
46-
exporter.meter_uploader.record(llm_response)
48+
exporter.meter_uploader.record(llm_request, llm_response)
4749

4850

4951
def trace_send_data(): ...
@@ -144,4 +146,4 @@ def trace_call_llm(
144146
response: ExtractorResponse = attr_extractor(params)
145147
ExtractorResponse.update_span(span, attr_name, response)
146148

147-
upload_metrics(invocation_context, llm_response)
149+
upload_metrics(invocation_context, llm_request, llm_response)

0 commit comments

Comments
 (0)