Skip to content

Commit 82b900c

Browse files
committed
Add otel metrics support as well
1 parent ac0bb11 commit 82b900c

File tree

5 files changed

+95
-14
lines changed

5 files changed

+95
-14
lines changed

requirements/cli.txt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@ dataclasses-json==0.6.7
2020
deprecated==1.2.14
2121
# via
2222
# opentelemetry-api
23+
# opentelemetry-exporter-otlp-proto-grpc
2324
# opentelemetry-semantic-conventions
2425
exceptiongroup==1.2.2
2526
# via anyio
2627
fastapi==0.112.2
2728
# via -r requirements//cli.in
29+
googleapis-common-protos==1.65.0
30+
# via opentelemetry-exporter-otlp-proto-grpc
31+
grpcio==1.66.0
32+
# via opentelemetry-exporter-otlp-proto-grpc
2833
h11==0.14.0
2934
# via uvicorn
3035
idna==3.8
@@ -39,10 +44,16 @@ numpy==2.1.0
3944
# via pandas
4045
opentelemetry-api==1.26.0
4146
# via
47+
# opentelemetry-exporter-otlp-proto-grpc
4248
# opentelemetry-instrumentation
4349
# opentelemetry-instrumentation-asgi
4450
# opentelemetry-instrumentation-fastapi
51+
# opentelemetry-sdk
4552
# opentelemetry-semantic-conventions
53+
opentelemetry-exporter-otlp-proto-common==1.26.0
54+
# via opentelemetry-exporter-otlp-proto-grpc
55+
opentelemetry-exporter-otlp-proto-grpc==1.26.0
56+
# via -r requirements//cli.in
4657
opentelemetry-instrumentation==0.47b0
4758
# via
4859
# opentelemetry-instrumentation-asgi
@@ -51,10 +62,19 @@ opentelemetry-instrumentation-asgi==0.47b0
5162
# via opentelemetry-instrumentation-fastapi
5263
opentelemetry-instrumentation-fastapi==0.47b0
5364
# via -r requirements//cli.in
65+
opentelemetry-proto==1.26.0
66+
# via
67+
# opentelemetry-exporter-otlp-proto-common
68+
# opentelemetry-exporter-otlp-proto-grpc
69+
opentelemetry-sdk==1.26.0
70+
# via
71+
# opentelemetry-exporter-otlp-proto-grpc
72+
# unstructured-ingest
5473
opentelemetry-semantic-conventions==0.47b0
5574
# via
5675
# opentelemetry-instrumentation-asgi
5776
# opentelemetry-instrumentation-fastapi
77+
# opentelemetry-sdk
5878
opentelemetry-util-http==0.47b0
5979
# via
6080
# opentelemetry-instrumentation-asgi
@@ -63,6 +83,10 @@ packaging==24.1
6383
# via marshmallow
6484
pandas==2.2.2
6585
# via unstructured-ingest
86+
protobuf==4.25.4
87+
# via
88+
# googleapis-common-protos
89+
# opentelemetry-proto
6690
pydantic==2.8.2
6791
# via
6892
# fastapi
@@ -88,6 +112,7 @@ typing-extensions==4.12.2
88112
# anyio
89113
# asgiref
90114
# fastapi
115+
# opentelemetry-sdk
91116
# pydantic
92117
# pydantic-core
93118
# typing-inspect
@@ -96,7 +121,7 @@ typing-inspect==0.9.0
96121
# via dataclasses-json
97122
tzdata==2024.1
98123
# via pandas
99-
unstructured-ingest==0.0.6
124+
unstructured-ingest==0.0.8
100125
# via -r requirements//cli.in
101126
uvicorn==0.30.6
102127
# via -r requirements//cli.in

requirements/constraints.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
unstructured-ingest==0.0.0
1+
unstructured-ingest==0.0.8

test/test_schema.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,10 @@ def fn(a: FileData) -> list[FileData]:
554554
],
555555
"default": None,
556556
},
557+
"filesize_bytes": {
558+
"anyOf": [{"type": "integer"}, {"type": "null"}],
559+
"default": None,
560+
},
557561
},
558562
"required": [],
559563
},
@@ -643,6 +647,10 @@ def fn(a: FileData) -> list[FileData]:
643647
],
644648
"default": None,
645649
},
650+
"filesize_bytes": {
651+
"anyOf": [{"type": "integer"}, {"type": "null"}],
652+
"default": None,
653+
},
646654
},
647655
"required": [],
648656
},

unstructured_platform_plugins/etl_uvicorn/api_generator.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from starlette.responses import RedirectResponse
1212
from uvicorn.importer import import_from_string
1313

14-
from unstructured_platform_plugins.etl_uvicorn.otel import get_provider
14+
from unstructured_platform_plugins.etl_uvicorn.otel import get_metric_provider, get_trace_provider
1515
from unstructured_platform_plugins.etl_uvicorn.utils import (
1616
get_func,
1717
get_input_schema,
@@ -172,6 +172,8 @@ async def get_id() -> str:
172172
except TypeError as e:
173173
raise TypeError(f"failed to validate function schema: {e}") from e
174174

175-
FastAPIInstrumentor.instrument_app(fastapi_app, tracer_provider=get_provider())
175+
FastAPIInstrumentor.instrument_app(
176+
fastapi_app, tracer_provider=get_trace_provider(), meter_provider=get_metric_provider()
177+
)
176178

177179
return fastapi_app
Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,67 @@
11
import os
22
from typing import Literal, TypedDict
33

4-
from opentelemetry.environment_variables import OTEL_TRACES_EXPORTER
4+
from opentelemetry.environment_variables import OTEL_METRICS_EXPORTER, OTEL_TRACES_EXPORTER
55
from opentelemetry.sdk.environment_variables import OTEL_SERVICE_NAME
6+
from opentelemetry.sdk.metrics import MeterProvider
7+
from opentelemetry.sdk.metrics.export import (
8+
ConsoleMetricExporter,
9+
MetricReader,
10+
PeriodicExportingMetricReader,
11+
)
612
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
713
from opentelemetry.sdk.trace import TracerProvider
814
from opentelemetry.sdk.trace.export import (
915
ConsoleSpanExporter,
1016
SimpleSpanProcessor,
1117
)
1218

13-
ExporterType = Literal["otlp", "jaeger", "zipkin", "console"]
19+
TraceExporterType = Literal["otlp", "jaeger", "zipkin", "console"]
20+
MetricExporterType = Literal["otlp", "prometheus", "none"]
1421

1522

1623
class OtelSettings(TypedDict):
1724
service_name: str
18-
exporters: list[ExporterType]
25+
trace_exporters: list[TraceExporterType]
26+
metric_exporters: list[MetricExporterType]
1927

2028

2129
def get_settings() -> OtelSettings:
2230
service_name = os.environ.get(OTEL_SERVICE_NAME, "unknown_service")
23-
exporters = os.environ.get(OTEL_TRACES_EXPORTER)
24-
exporters = exporters.split(",") if exporters else []
25-
return OtelSettings(service_name=service_name, exporters=exporters)
31+
trace_exporters = os.environ.get(OTEL_TRACES_EXPORTER)
32+
trace_exporters = trace_exporters.split(",") if trace_exporters else []
33+
34+
metric_exporters = os.environ.get(OTEL_METRICS_EXPORTER)
35+
metric_exporters = metric_exporters.split(",") if metric_exporters else []
36+
return OtelSettings(
37+
service_name=service_name,
38+
trace_exporters=trace_exporters,
39+
metric_exporters=metric_exporters,
40+
)
2641

2742

28-
def get_provider() -> TracerProvider:
43+
def get_trace_provider() -> TracerProvider:
2944
settings = get_settings()
45+
print(settings)
3046
provider = TracerProvider(resource=Resource({SERVICE_NAME: settings["service_name"]}))
3147

32-
for exporter_type in settings["exporters"]:
33-
_add_exporter(exporter_type=exporter_type, provider=provider)
48+
for trace_exporter_type in settings["trace_exporters"]:
49+
_add_trace_exporter(exporter_type=trace_exporter_type, provider=provider)
3450

3551
return provider
3652

3753

38-
def _add_exporter(exporter_type: ExporterType, provider: TracerProvider):
54+
def get_metric_provider() -> MeterProvider:
55+
settings = get_settings()
56+
readers = []
57+
for metric_exporter_type in settings["metric_exporters"]:
58+
readers.append(_get_metrics_reader(exporter_type=metric_exporter_type))
59+
return MeterProvider(
60+
resource=Resource({SERVICE_NAME: settings["service_name"]}), metric_readers=readers
61+
)
62+
63+
64+
def _add_trace_exporter(exporter_type: TraceExporterType, provider: TracerProvider):
3965
if exporter_type == "otlp":
4066
_add_traces_otlp_exporter(
4167
provider,
@@ -47,6 +73,14 @@ def _add_exporter(exporter_type: ExporterType, provider: TracerProvider):
4773
raise NotImplementedError(f"{exporter_type} implementation not supported yet")
4874

4975

76+
def _get_metrics_reader(exporter_type: MetricExporterType) -> MetricReader:
77+
if exporter_type == "otlp":
78+
return _get_metric_otlp_reader()
79+
if exporter_type == "console":
80+
return _get_metric_console_reader()
81+
raise NotImplementedError(f"{exporter_type} implementation not supported yet")
82+
83+
5084
def _add_traces_console_exporter(provider: TracerProvider) -> None:
5185
exporter = ConsoleSpanExporter()
5286
processor = SimpleSpanProcessor(exporter)
@@ -59,3 +93,15 @@ def _add_traces_otlp_exporter(provider: TracerProvider) -> None:
5993
exporter = OTLPSpanExporter()
6094
processor = SimpleSpanProcessor(exporter)
6195
provider.add_span_processor(processor)
96+
97+
98+
def _get_metric_otlp_reader() -> MetricReader:
99+
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
100+
101+
exporter = OTLPMetricExporter()
102+
return PeriodicExportingMetricReader(exporter)
103+
104+
105+
def _get_metric_console_reader() -> MetricReader:
106+
exporter = ConsoleMetricExporter()
107+
return PeriodicExportingMetricReader(exporter)

0 commit comments

Comments
 (0)