1
1
import logging
2
2
from logging import Logger
3
3
4
+ from azure .monitor .opentelemetry import configure_azure_monitor
5
+
4
6
# 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
+ )
6
13
from fastapi import FastAPI
7
14
from fastapp .core .config import settings
15
+ from opentelemetry import trace
16
+ from opentelemetry ._logs import set_logger_provider
8
17
from 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
9
25
from opentelemetry .sdk .resources import SERVICE_NAME , Resource
10
26
from opentelemetry .sdk .trace import TracerProvider
11
27
from opentelemetry .sdk .trace .export import BatchSpanProcessor
28
+ from opentelemetry .trace import Tracer , get_tracer_provider , set_tracer_provider
12
29
13
30
14
31
def setup_logging (module ) -> Logger :
@@ -21,26 +38,101 @@ def setup_logging(module) -> Logger:
21
38
logger .propagate = False
22
39
23
40
# Create stream handler
24
- logger_stream_handler = logging .StreamHandler ()
25
- logger_stream_handler .setFormatter (
41
+ stream_handler = logging .StreamHandler ()
42
+ stream_handler .setFormatter (
26
43
logging .Formatter ("[%(asctime)s] [%(levelname)s] [%(module)-8.8s] %(message)s" )
27
44
)
28
- logger .addHandler (logger_stream_handler )
45
+ logger .addHandler (stream_handler )
29
46
return logger
30
47
31
48
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 ):
33
59
"""Setup tracer for Open Telemetry.
34
60
35
61
app (FastAPI): The app to be instrumented by Open Telemetry.
36
62
RETURNS (None): Nothing is being returned.
37
63
"""
38
64
if settings .APPLICATIONINSIGHTS_CONNECTION_STRING :
39
65
# 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 (
41
76
settings .APPLICATIONINSIGHTS_CONNECTION_STRING ,
42
77
# credential=credential
43
78
)
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