-
Notifications
You must be signed in to change notification settings - Fork 144
Add functionality for TelemetryClient to not use global providers #1482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
hectorhdzg
merged 5 commits into
microsoft:main
from
hectorhdzg:hectorhdzg/telemetryclientupd
Dec 12, 2025
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
85a2c5e
Add funcitonality for TelemetryClient to not use global providers
hectorhdzg c34719b
Merge branch 'main' into hectorhdzg/telemetryclientupd
hectorhdzg 7524309
Updating to latest Otel
hectorhdzg 0185d98
Use actual latest OTel
hectorhdzg 8161dd8
Change default to avoid breaking changes
hectorhdzg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT license. | ||
|
|
||
| import { Attributes, context, metrics, SpanKind, SpanOptions, SpanStatusCode, diag, trace } from "@opentelemetry/api"; | ||
| import { Attributes, Meter, Tracer, context, metrics, SpanKind, SpanOptions, SpanStatusCode, diag, trace } from "@opentelemetry/api"; | ||
| import { logs } from "@opentelemetry/api-logs"; | ||
| import { | ||
| SEMATTRS_DB_STATEMENT, | ||
|
|
@@ -24,7 +24,8 @@ import { AttributeLogProcessor } from "../shared/util/attributeLogRecordProcesso | |
| import { LogApi } from "./logsApi"; | ||
| import { flushAzureMonitor, shutdownAzureMonitor, useAzureMonitor } from "../main"; | ||
| import { AzureMonitorOpenTelemetryOptions } from "../types"; | ||
| import { UNSUPPORTED_MSG, StatsbeatFeature } from "./types"; | ||
| import { TelemetryClientProvider } from "./telemetryClientProvider"; | ||
| import { TelemetryClientOptions, UNSUPPORTED_MSG, StatsbeatFeature } from "./types"; | ||
| import { StatsbeatFeaturesManager } from "../shared/util/statsbeatFeaturesManager"; | ||
|
|
||
| /** | ||
|
|
@@ -41,13 +42,17 @@ export class TelemetryClient { | |
| private _logApi: LogApi; | ||
| private _isInitialized: boolean; | ||
| private _options: AzureMonitorOpenTelemetryOptions; | ||
| private _telemetryClientProvider?: TelemetryClientProvider; | ||
| private _useGlobalProviders: boolean; | ||
| private _manualTracer?: Tracer; | ||
| private _manualMeter?: Meter; | ||
| private _configWarnings: string[] = []; | ||
|
|
||
| /** | ||
| * Constructs a new instance of TelemetryClient | ||
| * @param setupString the Connection String or Instrumentation Key to use (read from environment variable if not specified) | ||
| */ | ||
| constructor(input?: string) { | ||
| constructor(input?: string, options?: TelemetryClientOptions) { | ||
| TelemetryClient._instanceCount++; | ||
|
|
||
| // Set statsbeat feature if this is the second or subsequent TelemetryClient instance | ||
|
|
@@ -60,41 +65,38 @@ export class TelemetryClient { | |
| this.commonProperties = {}; | ||
| this.context = new Context(); | ||
| this._isInitialized = false; | ||
| this._useGlobalProviders = options?.useGlobalProviders ?? true; | ||
| } | ||
|
|
||
| public initialize() { | ||
| if (this._isInitialized) { | ||
| return; | ||
| } | ||
| this._isInitialized = true; | ||
| // Parse shim config to Azure Monitor options | ||
| this._options = this.config.parseConfig(); | ||
|
|
||
| try { | ||
| // Create attribute processors with context tags and common properties | ||
| this._attributeSpanProcessor = new AttributeSpanProcessor({ ...this.context.tags, ...this.commonProperties }); | ||
| this._attributeLogProcessor = new AttributeLogProcessor({ ...this.context.tags, ...this.commonProperties }); | ||
| this._options.spanProcessors = [...(this._options.spanProcessors || []), this._attributeSpanProcessor]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice addition, thanks for noticing this omission! |
||
| this._options.logRecordProcessors = [...(this._options.logRecordProcessors || []), this._attributeLogProcessor]; | ||
|
|
||
| // Add processors to Azure Monitor options before initialization | ||
| if (!this._options.spanProcessors) { | ||
| this._options.spanProcessors = []; | ||
| } | ||
| this._options.spanProcessors.push(this._attributeSpanProcessor); | ||
|
|
||
| if (!this._options.logRecordProcessors) { | ||
| this._options.logRecordProcessors = []; | ||
| if (this._useGlobalProviders) { | ||
| useAzureMonitor(this._options); | ||
| } else { | ||
| this._telemetryClientProvider = new TelemetryClientProvider(this._options); | ||
| } | ||
| this._options.logRecordProcessors.push(this._attributeLogProcessor); | ||
|
|
||
| // Initialize Azure Monitor with processors included | ||
| useAzureMonitor(this._options); | ||
|
|
||
| // LoggerProvider would be initialized when client is instantiated | ||
| // Get Logger from global provider | ||
| this._logApi = new LogApi(logs.getLogger("ApplicationInsightsLogger")); | ||
| const logger = this._useGlobalProviders | ||
| ? logs.getLogger("ApplicationInsightsLogger") | ||
| : this._telemetryClientProvider.getLogger("ApplicationInsightsLogger"); | ||
| this._logApi = new LogApi(logger); | ||
|
|
||
| // Warn if any config warnings were generated during parsing | ||
| for (let i = 0; i < this._configWarnings.length; i++) { | ||
| diag.warn(this._configWarnings[i]); | ||
| } | ||
| } | ||
| } | ||
| catch (error) { | ||
| diag.error(`Failed to initialize TelemetryClient ${error}`); | ||
| } | ||
|
|
@@ -167,14 +169,34 @@ export class TelemetryClient { | |
| } | ||
| // Create custom metric | ||
| try { | ||
| const meter = metrics.getMeterProvider().getMeter("ApplicationInsightsMetrics"); | ||
| const meter = this._getMeterInstance(); | ||
| const histogram = meter.createHistogram(telemetry.name); | ||
| histogram.record(telemetry.value, { ...telemetry.properties, ...this.commonProperties, ...this.context.tags }); | ||
| } catch (error) { | ||
| diag.error(`Failed to record metric: ${error}`); | ||
| } | ||
| } | ||
|
|
||
| private _getTracerInstance(): Tracer { | ||
| if (this._telemetryClientProvider) { | ||
| if (!this._manualTracer) { | ||
| this._manualTracer = this._telemetryClientProvider.getTracer("ApplicationInsightsTracer"); | ||
| } | ||
| return this._manualTracer; | ||
| } | ||
| return trace.getTracer("ApplicationInsightsTracer"); | ||
| } | ||
|
|
||
| private _getMeterInstance(): Meter { | ||
| if (this._telemetryClientProvider) { | ||
| if (!this._manualMeter) { | ||
| this._manualMeter = this._telemetryClientProvider.getMeter("ApplicationInsightsMetrics"); | ||
| } | ||
| return this._manualMeter; | ||
| } | ||
| return metrics.getMeterProvider().getMeter("ApplicationInsightsMetrics"); | ||
| } | ||
|
|
||
| /** | ||
| * Log a request. Note that the default client will attempt to collect HTTP requests automatically so only use this for requests | ||
| * that aren't automatically captured or if you've disabled automatic request collection. | ||
|
|
@@ -209,7 +231,7 @@ export class TelemetryClient { | |
| attributes: attributes, | ||
| startTime: startTime, | ||
| }; | ||
| const span: any = trace.getTracer("ApplicationInsightsTracer") | ||
| const span: any = this._getTracerInstance() | ||
| .startSpan(telemetry.name, options, ctx); | ||
|
|
||
| if (telemetry.id) { | ||
|
|
@@ -285,7 +307,7 @@ export class TelemetryClient { | |
| attributes: attributes, | ||
| startTime: startTime, | ||
| }; | ||
| const span: any = trace.getTracer("ApplicationInsightsTracer") | ||
| const span: any = this._getTracerInstance() | ||
| .startSpan(telemetry.name, options, ctx); | ||
|
|
||
| if (telemetry.id) { | ||
|
|
@@ -381,13 +403,19 @@ export class TelemetryClient { | |
| * Immediately send all queued telemetry. | ||
| */ | ||
| public async flush(): Promise<void> { | ||
| if (this._telemetryClientProvider) { | ||
| return this._telemetryClientProvider.flush(); | ||
| } | ||
| return flushAzureMonitor(); | ||
| } | ||
|
|
||
| /** | ||
| * Shutdown client | ||
| */ | ||
| public async shutdown(): Promise<void> { | ||
| if (this._telemetryClientProvider) { | ||
| return this._telemetryClientProvider.shutdown(); | ||
| } | ||
| return shutdownAzureMonitor(); | ||
| } | ||
|
|
||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit confused here, I though the title meant not to use the global providers for telemetry client, but here we are setting it to True.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only scenario where we want to enable it, the default client when the SDK is initialized using