11import logging
22from logging import Logger
33
4+ from azure .monitor .opentelemetry import configure_azure_monitor
5+
46# from azure.identity import ManagedIdentityCredential
5- from azure .monitor .opentelemetry .exporter import AzureMonitorTraceExporter
7+ from azure .monitor .opentelemetry .exporter import (
8+ ApplicationInsightsSampler ,
9+ AzureMonitorLogExporter ,
10+ AzureMonitorMetricExporter ,
11+ AzureMonitorTraceExporter ,
12+ )
613from fastapi import FastAPI
714from fastapp .core .config import settings
15+ from opentelemetry import trace
16+ from opentelemetry ._logs import set_logger_provider
817from opentelemetry .instrumentation .fastapi import FastAPIInstrumentor
18+ from opentelemetry .instrumentation .httpx import HTTPXClientInstrumentor
19+ from opentelemetry .instrumentation .system_metrics import SystemMetricsInstrumentor
20+ from opentelemetry .metrics import set_meter_provider
21+ from opentelemetry .sdk ._logs import LoggerProvider , LoggingHandler
22+ from opentelemetry .sdk ._logs .export import BatchLogRecordProcessor
23+ from opentelemetry .sdk .metrics import MeterProvider
24+ from opentelemetry .sdk .metrics .export import PeriodicExportingMetricReader
925from opentelemetry .sdk .resources import SERVICE_NAME , Resource
1026from opentelemetry .sdk .trace import TracerProvider
1127from opentelemetry .sdk .trace .export import BatchSpanProcessor
28+ from opentelemetry .trace import Tracer , get_tracer_provider , set_tracer_provider
1229
1330
1431def setup_logging (module ) -> Logger :
@@ -21,26 +38,101 @@ def setup_logging(module) -> Logger:
2138 logger .propagate = False
2239
2340 # Create stream handler
24- logger_stream_handler = logging .StreamHandler ()
25- logger_stream_handler .setFormatter (
41+ stream_handler = logging .StreamHandler ()
42+ stream_handler .setFormatter (
2643 logging .Formatter ("[%(asctime)s] [%(levelname)s] [%(module)-8.8s] %(message)s" )
2744 )
28- logger .addHandler (logger_stream_handler )
45+ logger .addHandler (stream_handler )
2946 return logger
3047
3148
32- def setup_tracer (app : FastAPI ):
49+ def setup_tracer (module ) -> Tracer :
50+ """Setup tracer and event handler.
51+
52+ RETURNS (Tracer): The tracer object to create spans.
53+ """
54+ tracer = trace .get_tracer (module )
55+ return tracer
56+
57+
58+ def setup_opentelemetry (app : FastAPI ):
3359 """Setup tracer for Open Telemetry.
3460
3561 app (FastAPI): The app to be instrumented by Open Telemetry.
3662 RETURNS (None): Nothing is being returned.
3763 """
3864 if settings .APPLICATIONINSIGHTS_CONNECTION_STRING :
3965 # credential = ManagedIdentityCredential()
40- exporter = AzureMonitorTraceExporter .from_connection_string (
66+ resource = Resource .create (
67+ {
68+ "service.name" : settings .WEBSITE_NAME ,
69+ "service.namespace" : settings .WEBSITE_NAME ,
70+ "service.instance.id" : settings .WEBSITE_INSTANCE_ID ,
71+ }
72+ )
73+
74+ # Create logger provider
75+ logger_exporter = AzureMonitorLogExporter .from_connection_string (
4176 settings .APPLICATIONINSIGHTS_CONNECTION_STRING ,
4277 # credential=credential
4378 )
44- tracer = TracerProvider (resource = Resource ({SERVICE_NAME : "api" }))
45- tracer .add_span_processor (BatchSpanProcessor (exporter ))
46- FastAPIInstrumentor .instrument_app (app , tracer_provider = tracer )
79+ logger_provider = LoggerProvider (resource = resource )
80+ logger_provider .add_log_record_processor (
81+ BatchLogRecordProcessor (
82+ exporter = logger_exporter ,
83+ schedule_delay_millis = settings .LOGGING_SCHEDULE_DELAY ,
84+ )
85+ )
86+ set_logger_provider (logger_provider )
87+ handler = LoggingHandler (
88+ level = settings .LOGGING_LEVEL , logger_provider = logger_provider
89+ )
90+ logging .getLogger ().addHandler (handler )
91+
92+ # Create tracer provider
93+ tracer_exporter = AzureMonitorTraceExporter .from_connection_string (
94+ settings .APPLICATIONINSIGHTS_CONNECTION_STRING ,
95+ # credential=credential
96+ )
97+ sampler = ApplicationInsightsSampler (
98+ sampling_ratio = settings .LOGGING_SAMPLING_RATIO
99+ )
100+ tracer_provider = TracerProvider (resource = resource , sampler = sampler )
101+ tracer_provider .add_span_processor (
102+ BatchSpanProcessor (
103+ span_exporter = tracer_exporter ,
104+ schedule_delay_millis = settings .LOGGING_SCHEDULE_DELAY ,
105+ )
106+ )
107+ set_tracer_provider (tracer_provider )
108+
109+ # Create meter provider
110+ metrics_exporter = AzureMonitorMetricExporter .from_connection_string (
111+ settings .APPLICATIONINSIGHTS_CONNECTION_STRING ,
112+ # credential=credential
113+ )
114+ reader = PeriodicExportingMetricReader (
115+ exporter = metrics_exporter ,
116+ export_interval_millis = settings .LOGGING_SCHEDULE_DELAY ,
117+ )
118+ meter_provider = MeterProvider (metric_readers = [reader ], resource = resource )
119+ set_meter_provider (meter_provider )
120+
121+ # Configure custom metrics
122+ system_metrics_config = {
123+ "system.memory.usage" : ["used" , "free" , "cached" ],
124+ "system.cpu.time" : ["idle" , "user" , "system" , "irq" ],
125+ "system.network.io" : ["transmit" , "receive" ],
126+ "process.runtime.memory" : ["rss" , "vms" ],
127+ "process.runtime.cpu.time" : ["user" , "system" ],
128+ }
129+
130+ # Create instrumenter
131+ FastAPIInstrumentor .instrument_app (
132+ app ,
133+ excluded_urls = f"{ settings .API_V1_STR } /health/heartbeat" ,
134+ tracer_provider = tracer_provider ,
135+ meter_provider = meter_provider ,
136+ )
137+ HTTPXClientInstrumentor ().instrument ()
138+ SystemMetricsInstrumentor (config = system_metrics_config ).instrument ()
0 commit comments