2
2
// Licensed under the MIT License. See License.txt in the project root for license information.
3
3
4
4
using System ;
5
+ using System . Diagnostics ;
5
6
using System . Diagnostics . Tracing ;
7
+ using System . Linq ;
6
8
using Azure . Core ;
7
9
using Azure . Identity ;
8
10
using Azure . Monitor . OpenTelemetry . Exporter ;
9
11
using Azure . Monitor . OpenTelemetry . LiveMetrics ;
12
+ using Microsoft . AspNetCore . Routing ;
13
+ using Microsoft . Azure . WebJobs . Script . Metrics ;
10
14
using Microsoft . Extensions . Configuration ;
11
15
using Microsoft . Extensions . DependencyInjection ;
12
16
using Microsoft . Extensions . Hosting ;
13
17
using Microsoft . Extensions . Logging ;
18
+ using OpenTelemetry ;
14
19
using OpenTelemetry . Logs ;
15
20
using OpenTelemetry . Metrics ;
16
21
using OpenTelemetry . Resources ;
@@ -47,52 +52,94 @@ internal static void ConfigureOpenTelemetry(this ILoggingBuilder loggingBuilder,
47
52
}
48
53
49
54
loggingBuilder
50
- . AddOpenTelemetry ( o =>
51
- {
52
- o . SetResourceBuilder ( ConfigureResource ( ResourceBuilder . CreateDefault ( ) ) ) ;
53
- if ( enableOtlp )
54
- {
55
- o . AddOtlpExporter ( ) ;
56
- }
57
- if ( enableAzureMonitor )
58
- {
59
- o . AddAzureMonitorLogExporter ( options => ConfigureAzureMonitorOptions ( options , azMonConnectionString , credential ) ) ;
60
- }
61
- o . IncludeFormattedMessage = true ;
62
- o . IncludeScopes = false ;
63
- } )
64
- . AddDefaultOpenTelemetryFilters ( ) ;
55
+ . ConfigureLogging ( enableOtlp , enableAzureMonitor , azMonConnectionString , credential ) . Services
56
+ . AddOpenTelemetry ( )
57
+ . ConfigureResource ( r => ConfigureResource ( r ) )
58
+ . ConfigureMetrics ( enableOtlp , enableAzureMonitor , azMonConnectionString , credential )
59
+ . ConfigureTracing ( enableOtlp , enableAzureMonitor , azMonConnectionString , credential )
60
+ . ConfigureEventLogLevel ( context . Configuration ) ;
65
61
66
62
// Azure SDK instrumentation is experimental.
67
63
AppContext . SetSwitch ( "Azure.Experimental.EnableActivitySource" , true ) ;
64
+ }
68
65
69
- ConfigureTracing ( loggingBuilder , enableOtlp , enableAzureMonitor , azMonConnectionString , credential ) ;
66
+ private static IOpenTelemetryBuilder ConfigureMetrics ( this IOpenTelemetryBuilder builder , bool enableOtlp , bool enableAzureMonitor , string azMonConnectionString , TokenCredential credential )
67
+ {
68
+ return builder . WithMetrics ( builder =>
69
+ {
70
+ builder . AddAspNetCoreInstrumentation ( ) ;
71
+ builder . AddMeter ( HostMetrics . FaasMeterName ) ;
72
+ builder . AddView ( HostMetrics . FaasInvokeDuration , new ExplicitBucketHistogramConfiguration
73
+ {
74
+ Boundaries = new double [ ] { 0.005 , 0.01 , 0.025 , 0.05 , 0.075 , 0.1 , 0.25 , 0.5 , 0.75 , 1 , 2.5 , 5 , 7.5 , 10 }
75
+ } ) ;
70
76
71
- ConfigureEventLogLevel ( loggingBuilder , context . Configuration ) ;
77
+ if ( enableOtlp )
78
+ {
79
+ builder . AddOtlpExporter ( ) ;
80
+ }
81
+ if ( enableAzureMonitor )
82
+ {
83
+ builder . AddAzureMonitorMetricExporter ( opt => ConfigureAzureMonitorOptions ( opt , azMonConnectionString , credential ) ) ;
84
+ }
85
+ } ) ;
72
86
}
73
87
74
- private static void ConfigureTracing ( ILoggingBuilder loggingBuilder , bool enableOtlp , bool enableAzureMonitor , string azMonConnectionString , TokenCredential credential )
88
+ private static IOpenTelemetryBuilder ConfigureTracing ( this IOpenTelemetryBuilder builder , bool enableOtlp , bool enableAzureMonitor , string azMonConnectionString , TokenCredential credential )
75
89
{
76
- loggingBuilder . Services . AddOpenTelemetry ( )
77
- . ConfigureResource ( r => ConfigureResource ( r ) )
78
- . WithTracing ( builder =>
90
+ return builder . WithTracing ( builder =>
91
+ {
92
+ builder . AddSource ( "Azure.*" )
93
+ . AddAspNetCoreInstrumentation ( o =>
79
94
{
80
- builder . AddSource ( "Azure.*" )
81
- . AddAspNetCoreInstrumentation ( ) ;
82
-
83
- if ( enableOtlp )
95
+ o . EnrichWithHttpResponse = ( activity , httpResponse ) =>
84
96
{
85
- builder . AddOtlpExporter ( ) ;
86
- }
97
+ if ( Activity . Current != null )
98
+ {
99
+ var routingFeature = httpResponse . HttpContext . Features . Get < AspNetCore . Routing . IRoutingFeature > ( ) ;
100
+ var template = routingFeature . RouteData . Routers . FirstOrDefault ( r => r is Route ) as Route ;
101
+
102
+ Activity . Current . DisplayName = $ "{ Activity . Current . DisplayName } { template ? . RouteTemplate } ";
103
+ Activity . Current . AddTag ( ResourceSemanticConventions . HttpRoute , template ? . RouteTemplate ) ;
104
+ Activity . Current . AddTag ( ResourceSemanticConventions . FaaSTrigger , OpenTelemetryConstants . HttpTriggerType ) ;
105
+ }
106
+ } ;
107
+ } ) ;
87
108
88
- if ( enableAzureMonitor )
89
- {
90
- builder . AddAzureMonitorTraceExporter ( opt => ConfigureAzureMonitorOptions ( opt , azMonConnectionString , credential ) ) ;
91
- builder . AddLiveMetrics ( opt => ConfigureAzureMonitorOptions ( opt , azMonConnectionString , credential ) ) ;
92
- }
109
+ if ( enableOtlp )
110
+ {
111
+ builder . AddOtlpExporter ( ) ;
112
+ }
93
113
94
- builder . AddProcessor ( ActivitySanitizingProcessor . Instance ) ;
95
- } ) ;
114
+ if ( enableAzureMonitor )
115
+ {
116
+ builder . AddAzureMonitorTraceExporter ( opt => ConfigureAzureMonitorOptions ( opt , azMonConnectionString , credential ) ) ;
117
+ builder . AddLiveMetrics ( opt => ConfigureAzureMonitorOptions ( opt , azMonConnectionString , credential ) ) ;
118
+ }
119
+
120
+ builder . AddProcessor ( ActivitySanitizingProcessor . Instance ) ;
121
+ } ) ;
122
+ }
123
+
124
+ private static ILoggingBuilder ConfigureLogging ( this ILoggingBuilder builder , bool enableOtlp , bool enableAzureMonitor , string azMonConnectionString , TokenCredential credential )
125
+ {
126
+ builder . AddOpenTelemetry ( o =>
127
+ {
128
+ o . SetResourceBuilder ( ConfigureResource ( ResourceBuilder . CreateDefault ( ) ) ) ;
129
+ if ( enableOtlp )
130
+ {
131
+ o . AddOtlpExporter ( ) ;
132
+ }
133
+ if ( enableAzureMonitor )
134
+ {
135
+ o . AddAzureMonitorLogExporter ( options => ConfigureAzureMonitorOptions ( options , azMonConnectionString , credential ) ) ;
136
+ }
137
+ o . IncludeFormattedMessage = true ;
138
+ o . IncludeScopes = false ;
139
+ } ) ;
140
+ builder . AddDefaultOpenTelemetryFilters ( ) ;
141
+
142
+ return builder ;
96
143
}
97
144
98
145
private static ILoggingBuilder AddDefaultOpenTelemetryFilters ( this ILoggingBuilder loggingBuilder )
@@ -101,23 +148,27 @@ private static ILoggingBuilder AddDefaultOpenTelemetryFilters(this ILoggingBuild
101
148
// These are messages piped back to the host from the worker - we don't handle these anymore if the worker has OpenTelemetry enabled.
102
149
// Instead, we expect the user's own code to be logging these where they want them to go.
103
150
. AddFilter < OpenTelemetryLoggerProvider > ( "Function.*" , _ => ! ScriptHost . WorkerOpenTelemetryEnabled )
104
- . AddFilter < OpenTelemetryLoggerProvider > ( "Azure.*" , _ => ! ScriptHost . WorkerOpenTelemetryEnabled )
151
+
152
+ // Always filter out these logs
153
+ . AddFilter < OpenTelemetryLoggerProvider > ( "Azure.*" , _ => false )
105
154
// Host.Results and Host.Aggregator are used to emit metrics, ignoring these categories.
106
- . AddFilter < OpenTelemetryLoggerProvider > ( "Host.Results" , _ => ! ScriptHost . WorkerOpenTelemetryEnabled )
107
- . AddFilter < OpenTelemetryLoggerProvider > ( "Host.Aggregator" , _ => ! ScriptHost . WorkerOpenTelemetryEnabled )
155
+ . AddFilter < OpenTelemetryLoggerProvider > ( "Host.Results" , _ => false )
156
+ . AddFilter < OpenTelemetryLoggerProvider > ( "Host.Aggregator" , _ => false )
108
157
// Ignoring all Microsoft.Azure.WebJobs.* logs like /getScriptTag and /lock.
109
- . AddFilter < OpenTelemetryLoggerProvider > ( "Microsoft.Azure.WebJobs.*" , _ => ! ScriptHost . WorkerOpenTelemetryEnabled ) ;
158
+ . AddFilter < OpenTelemetryLoggerProvider > ( "Microsoft.Azure.WebJobs.*" , _ => false ) ;
110
159
}
111
160
112
- private static void ConfigureEventLogLevel ( ILoggingBuilder loggingBuilder , IConfiguration configuration )
161
+ private static IOpenTelemetryBuilder ConfigureEventLogLevel ( this IOpenTelemetryBuilder builder , IConfiguration configuration )
113
162
{
114
163
string eventLogLevel = GetConfigurationValue ( EnvironmentSettingNames . OpenTelemetryEventListenerLogLevel , configuration ) ;
115
164
EventLevel level = ! string . IsNullOrEmpty ( eventLogLevel ) &&
116
165
Enum . TryParse ( eventLogLevel , ignoreCase : true , out EventLevel parsedLevel )
117
166
? parsedLevel
118
167
: EventLevel . Warning ;
119
168
120
- loggingBuilder . Services . AddHostedService ( _ => new OpenTelemetryEventListenerService ( level ) ) ;
169
+ builder . Services . AddHostedService ( _ => new OpenTelemetryEventListenerService ( level ) ) ;
170
+
171
+ return builder ;
121
172
}
122
173
123
174
private static ResourceBuilder ConfigureResource ( ResourceBuilder builder )
0 commit comments