@azure/monitor-opentelemetry 1.18.0 → 1.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/commonjs/index.d.ts.map +1 -1
  2. package/dist/commonjs/index.js +5 -1
  3. package/dist/commonjs/index.js.map +1 -1
  4. package/dist/commonjs/metrics/handler.d.ts.map +1 -1
  5. package/dist/commonjs/metrics/handler.js +2 -3
  6. package/dist/commonjs/metrics/handler.js.map +1 -1
  7. package/dist/commonjs/metrics/quickpulse/export/sender.d.ts +10 -1
  8. package/dist/commonjs/metrics/quickpulse/export/sender.d.ts.map +1 -1
  9. package/dist/commonjs/metrics/quickpulse/export/sender.js +37 -15
  10. package/dist/commonjs/metrics/quickpulse/export/sender.js.map +1 -1
  11. package/dist/commonjs/metrics/quickpulse/filtering/filter.d.ts.map +1 -1
  12. package/dist/commonjs/metrics/quickpulse/filtering/filter.js +2 -5
  13. package/dist/commonjs/metrics/quickpulse/filtering/filter.js.map +1 -1
  14. package/dist/commonjs/metrics/quickpulse/liveMetrics.d.ts +4 -2
  15. package/dist/commonjs/metrics/quickpulse/liveMetrics.d.ts.map +1 -1
  16. package/dist/commonjs/metrics/quickpulse/liveMetrics.js +71 -16
  17. package/dist/commonjs/metrics/quickpulse/liveMetrics.js.map +1 -1
  18. package/dist/commonjs/metrics/quickpulse/redirectUtils.d.ts +28 -0
  19. package/dist/commonjs/metrics/quickpulse/redirectUtils.d.ts.map +1 -0
  20. package/dist/commonjs/metrics/quickpulse/redirectUtils.js +80 -0
  21. package/dist/commonjs/metrics/quickpulse/redirectUtils.js.map +1 -0
  22. package/dist/commonjs/metrics/quickpulse/utils.d.ts.map +1 -1
  23. package/dist/commonjs/metrics/quickpulse/utils.js.map +1 -1
  24. package/dist/commonjs/metrics/standardMetrics.js.map +1 -1
  25. package/dist/commonjs/traces/handler.d.ts +12 -0
  26. package/dist/commonjs/traces/handler.d.ts.map +1 -1
  27. package/dist/commonjs/traces/handler.js +30 -1
  28. package/dist/commonjs/traces/handler.js.map +1 -1
  29. package/dist/commonjs/tsdoc-metadata.json +1 -1
  30. package/dist/commonjs/types.d.ts +1 -1
  31. package/dist/commonjs/types.js +1 -1
  32. package/dist/commonjs/types.js.map +1 -1
  33. package/dist/commonjs/utils/azureSdkTracingBridge.d.ts +18 -0
  34. package/dist/commonjs/utils/azureSdkTracingBridge.d.ts.map +1 -0
  35. package/dist/commonjs/utils/azureSdkTracingBridge.js +35 -0
  36. package/dist/commonjs/utils/azureSdkTracingBridge.js.map +1 -0
  37. package/dist/esm/index.d.ts.map +1 -1
  38. package/dist/esm/index.js +5 -1
  39. package/dist/esm/index.js.map +1 -1
  40. package/dist/esm/metrics/handler.d.ts.map +1 -1
  41. package/dist/esm/metrics/handler.js +2 -3
  42. package/dist/esm/metrics/handler.js.map +1 -1
  43. package/dist/esm/metrics/quickpulse/export/sender.d.ts +10 -1
  44. package/dist/esm/metrics/quickpulse/export/sender.d.ts.map +1 -1
  45. package/dist/esm/metrics/quickpulse/export/sender.js +37 -15
  46. package/dist/esm/metrics/quickpulse/export/sender.js.map +1 -1
  47. package/dist/esm/metrics/quickpulse/filtering/filter.d.ts.map +1 -1
  48. package/dist/esm/metrics/quickpulse/filtering/filter.js +2 -5
  49. package/dist/esm/metrics/quickpulse/filtering/filter.js.map +1 -1
  50. package/dist/esm/metrics/quickpulse/liveMetrics.d.ts +4 -2
  51. package/dist/esm/metrics/quickpulse/liveMetrics.d.ts.map +1 -1
  52. package/dist/esm/metrics/quickpulse/liveMetrics.js +71 -16
  53. package/dist/esm/metrics/quickpulse/liveMetrics.js.map +1 -1
  54. package/dist/esm/metrics/quickpulse/redirectUtils.d.ts +28 -0
  55. package/dist/esm/metrics/quickpulse/redirectUtils.d.ts.map +1 -0
  56. package/dist/esm/metrics/quickpulse/redirectUtils.js +76 -0
  57. package/dist/esm/metrics/quickpulse/redirectUtils.js.map +1 -0
  58. package/dist/esm/metrics/quickpulse/utils.d.ts.map +1 -1
  59. package/dist/esm/metrics/quickpulse/utils.js.map +1 -1
  60. package/dist/esm/metrics/standardMetrics.js.map +1 -1
  61. package/dist/esm/traces/handler.d.ts +12 -0
  62. package/dist/esm/traces/handler.d.ts.map +1 -1
  63. package/dist/esm/traces/handler.js +29 -1
  64. package/dist/esm/traces/handler.js.map +1 -1
  65. package/dist/esm/types.d.ts +1 -1
  66. package/dist/esm/types.js +1 -1
  67. package/dist/esm/types.js.map +1 -1
  68. package/dist/esm/utils/azureSdkTracingBridge.d.ts +18 -0
  69. package/dist/esm/utils/azureSdkTracingBridge.d.ts.map +1 -0
  70. package/dist/esm/utils/azureSdkTracingBridge.js +34 -0
  71. package/dist/esm/utils/azureSdkTracingBridge.js.map +1 -0
  72. package/package.json +29 -20
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAMlD,OAAO,KAAK,EAGV,gCAAgC,EAChC,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAsBpB,YAAY,EAAE,gCAAgC,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,CAAC;AA0BlG;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,gCAAgC,GAAG,IAAI,CA+FhF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGpD;AAED;;;GAGG;AAEH,wBAAgB,eAAe,IAAI,OAAO,GAAG,SAAS,CAErD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAMlD,OAAO,KAAK,EAGV,gCAAgC,EAChC,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAuBpB,YAAY,EAAE,gCAAgC,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,CAAC;AA0BlG;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,gCAAgC,GAAG,IAAI,CAmGhF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGpD;AAED;;;GAGG;AAEH,wBAAgB,eAAe,IAAI,OAAO,GAAG,SAAS,CAErD"}
@@ -17,6 +17,7 @@ const browserSdkLoader_js_1 = require("./browserSdkLoader/browserSdkLoader.js");
17
17
  const utils_js_1 = require("./metrics/quickpulse/utils.js");
18
18
  const statsbeat_js_1 = require("./utils/statsbeat.js");
19
19
  const opentelemetryInstrumentationPatcher_js_1 = require("./utils/opentelemetryInstrumentationPatcher.js");
20
+ const azureSdkTracingBridge_js_1 = require("./utils/azureSdkTracingBridge.js");
20
21
  const common_js_1 = require("./utils/common.js");
21
22
  const index_js_3 = require("./shared/logging/index.js");
22
23
  const types_js_2 = require("./types.js");
@@ -92,7 +93,7 @@ function useAzureMonitor(options) {
92
93
  // must match", resulting in Noop providers. Deleting the global object forces
93
94
  // registerGlobal() to create a fresh one with the correct version.
94
95
  const globalOpentelemetryApiKey = Symbol.for("opentelemetry.js.api.1");
95
- delete globalThis[globalOpentelemetryApiKey];
96
+ Reflect.deleteProperty(globalThis, globalOpentelemetryApiKey);
96
97
  // Create internal handlers
97
98
  const metricHandler = new index_js_1.MetricHandler(config);
98
99
  const traceHandler = new handler_js_1.TraceHandler(config, metricHandler);
@@ -135,6 +136,9 @@ function useAzureMonitor(options) {
135
136
  (0, utils_js_1.setSdkPrefix)();
136
137
  sendAttachWarning();
137
138
  sdk.start();
139
+ // Eagerly install the Azure SDK tracing bridge in case @azure/core-tracing
140
+ // was loaded before useAzureMonitor() (the RITM hook misses it otherwise).
141
+ (0, azureSdkTracingBridge_js_1.ensureAzureSdkTracingBridge)();
138
142
  }
139
143
  /**
140
144
  * Shutdown Azure Monitor Open Telemetry Distro
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { metrics, trace } from \"@opentelemetry/api\";\nimport { logs } from \"@opentelemetry/api-logs\";\nimport type { NodeSDKConfiguration } from \"@opentelemetry/sdk-node\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport type { MetricReader, ViewOptions } from \"@opentelemetry/sdk-metrics\";\nimport { InternalConfig } from \"./shared/config.js\";\nimport { MetricHandler } from \"./metrics/index.js\";\nimport { TraceHandler } from \"./traces/handler.js\";\nimport { LogHandler } from \"./logs/index.js\";\nimport type {\n StatsbeatFeatures,\n StatsbeatInstrumentations,\n AzureMonitorOpenTelemetryOptions,\n InstrumentationOptions,\n BrowserSdkLoaderOptions,\n} from \"./types.js\";\nimport {\n AZURE_MONITOR_OPENTELEMETRY_VERSION,\n APPLICATIONINSIGHTS_SDKSTATS_DISABLED,\n} from \"./types.js\";\nimport { BrowserSdkLoader } from \"./browserSdkLoader/browserSdkLoader.js\";\nimport { setSdkPrefix } from \"./metrics/quickpulse/utils.js\";\nimport type { SpanProcessor } from \"@opentelemetry/sdk-trace-base\";\nimport type { LogRecordProcessor } from \"@opentelemetry/sdk-logs\";\nimport { getInstance } from \"./utils/statsbeat.js\";\nimport { patchOpenTelemetryInstrumentationEnable } from \"./utils/opentelemetryInstrumentationPatcher.js\";\nimport { isFunctionApp, parseResourceDetectorsFromEnvVar } from \"./utils/common.js\";\nimport { Logger } from \"./shared/logging/index.js\";\nimport { AZURE_MONITOR_AUTO_ATTACH } from \"./types.js\";\nimport { SEMRESATTRS_K8S_CLUSTER_NAME } from \"@opentelemetry/semantic-conventions\";\n\n/**\n * Semantic attribute for cloud resource ID, defined by \\@opentelemetry/resource-detector-azure\n * @internal\n */\nconst CLOUD_RESOURCE_ID_ATTRIBUTE = \"cloud.resource_id\";\n\nexport type { AzureMonitorOpenTelemetryOptions, InstrumentationOptions, BrowserSdkLoaderOptions };\n\nprocess.env[\"AZURE_MONITOR_DISTRO_VERSION\"] = AZURE_MONITOR_OPENTELEMETRY_VERSION;\n\nlet sdk: NodeSDK;\nlet browserSdkLoader: BrowserSdkLoader | undefined;\n\n/**\n * Check if auto-attach (autoinstrumentation) is enabled and warn about double instrumentation.\n */\nfunction sendAttachWarning(): void {\n if (process.env[AZURE_MONITOR_AUTO_ATTACH] === \"true\" && !isFunctionApp()) {\n // TODO: When AKS attach is public, update this message with disablement instructions for AKS\n const message =\n \"Distro detected that automatic instrumentation may have occurred. Only use autoinstrumentation if you \" +\n \"are not using manual instrumentation of OpenTelemetry in your code, such as with \" +\n \"@azure/monitor-opentelemetry or @azure/monitor-opentelemetry-exporter. For App Service resources, disable \" +\n \"autoinstrumentation in the Application Insights experience on your App Service resource or by setting \" +\n \"the ApplicationInsightsAgent_EXTENSION_VERSION app setting to 'disabled'.\";\n // Surface in the log stream\n console.warn(message);\n // Also log via diagnostic logging\n Logger.getInstance().warn(message);\n }\n}\n\n/**\n * Initialize Azure Monitor Distro\n * @param options - Azure Monitor OpenTelemetry Options\n */\nexport function useAzureMonitor(options?: AzureMonitorOpenTelemetryOptions): void {\n const config = new InternalConfig(options);\n patchOpenTelemetryInstrumentationEnable();\n const statsbeatInstrumentations: StatsbeatInstrumentations = {\n // Instrumentations\n azureSdk: config.instrumentationOptions?.azureSdk?.enabled,\n mongoDb: config.instrumentationOptions?.mongoDb?.enabled,\n mySql: config.instrumentationOptions?.mySql?.enabled,\n postgreSql: config.instrumentationOptions?.postgreSql?.enabled,\n redis: config.instrumentationOptions?.redis?.enabled,\n bunyan: config.instrumentationOptions?.bunyan?.enabled,\n winston: config.instrumentationOptions?.winston?.enabled,\n };\n // Check if the AKS resource detector successfully populated specific resource attributes\n // (k8s.cluster.name or cloud.resource_id) beyond the basic cloud.platform/cloud.provider\n // Derive from config.resource.attributes which already includes the AKS detector results\n const resourceAttributes = config.resource.attributes;\n const aksResourceDetected =\n SEMRESATTRS_K8S_CLUSTER_NAME in resourceAttributes ||\n CLOUD_RESOURCE_ID_ATTRIBUTE in resourceAttributes;\n const statsbeatFeatures: StatsbeatFeatures = {\n browserSdkLoader: config.browserSdkLoaderOptions.enabled,\n aadHandling: !!config.azureMonitorExporterOptions?.credential,\n diskRetry: !config.azureMonitorExporterOptions?.disableOfflineStorage,\n customerSdkStats: process.env[APPLICATIONINSIGHTS_SDKSTATS_DISABLED]?.toLowerCase() === \"true\",\n aksResourceDetectorPopulation: aksResourceDetected,\n };\n getInstance().setStatsbeatFeatures(statsbeatInstrumentations, statsbeatFeatures);\n\n if (config.browserSdkLoaderOptions.enabled) {\n browserSdkLoader = new BrowserSdkLoader(config);\n }\n // Remove global providers in OpenTelemetry, these would be overridden if present\n metrics.disable();\n trace.disable();\n logs.disable();\n\n // Clear the entire OpenTelemetry API global state to avoid version conflicts.\n // The disable() calls above remove individual providers but leave the `version` field\n // on the global object intact. If a different version of @opentelemetry/api was loaded\n // first (e.g. by a VS Code extension host or another extension), the stale version\n // causes registerGlobal() in sdk.start() to fail with \"All API registration versions\n // must match\", resulting in Noop providers. Deleting the global object forces\n // registerGlobal() to create a fresh one with the correct version.\n const globalOpentelemetryApiKey = Symbol.for(\"opentelemetry.js.api.1\");\n delete (globalThis as Record<symbol, unknown>)[globalOpentelemetryApiKey];\n\n // Create internal handlers\n const metricHandler = new MetricHandler(config);\n const traceHandler = new TraceHandler(config, metricHandler);\n const logHandler = new LogHandler(config, metricHandler);\n\n const instrumentations = traceHandler\n .getInstrumentations()\n .concat(logHandler.getInstrumentations());\n\n const resourceDetectorsList = parseResourceDetectorsFromEnvVar();\n\n // Add extra SpanProcessors, and logRecordProcessors from user configuration\n const spanProcessors: SpanProcessor[] = options?.spanProcessors || [];\n const logRecordProcessors: LogRecordProcessor[] = options?.logRecordProcessors || [];\n const customViews: ViewOptions[] = options?.views || [];\n\n // Prepare metric readers - always include Azure Monitor\n const metricReaders: MetricReader[] = [\n metricHandler.getMetricReader(),\n ...(options?.metricReaders || []),\n ];\n\n const views: ViewOptions[] = metricHandler.getViews().concat(customViews);\n\n // Initialize OpenTelemetry SDK\n const sdkConfig: Partial<NodeSDKConfiguration> = {\n autoDetectResources: true,\n metricReaders: metricReaders,\n views,\n instrumentations: instrumentations,\n logRecordProcessors: [\n logHandler.getAzureLogRecordProcessor(),\n ...logRecordProcessors,\n logHandler.getBatchLogRecordProcessor(),\n ],\n resource: config.resource,\n sampler: traceHandler.getSampler(),\n spanProcessors: [\n traceHandler.getAzureMonitorSpanProcessor(),\n ...spanProcessors,\n traceHandler.getBatchSpanProcessor(),\n ],\n resourceDetectors: resourceDetectorsList,\n };\n sdk = new NodeSDK(sdkConfig);\n setSdkPrefix();\n sendAttachWarning();\n sdk.start();\n}\n\n/**\n * Shutdown Azure Monitor Open Telemetry Distro\n * @see https://github.com/open-telemetry/opentelemetry-js/blob/0229434cb5a3179f63c021105f36270ae7897929/experimental/packages/opentelemetry-sdk-node/src/sdk.ts#L398\n */\nexport function shutdownAzureMonitor(): Promise<void> {\n browserSdkLoader?.dispose();\n return sdk?.shutdown();\n}\n\n/**\n * Get the internal SDK instance for testing purposes\n * @internal\n */\n// eslint-disable-next-line no-underscore-dangle\nexport function _getSdkInstance(): NodeSDK | undefined {\n return sdk;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { metrics, trace } from \"@opentelemetry/api\";\nimport { logs } from \"@opentelemetry/api-logs\";\nimport type { NodeSDKConfiguration } from \"@opentelemetry/sdk-node\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport type { MetricReader, ViewOptions } from \"@opentelemetry/sdk-metrics\";\nimport { InternalConfig } from \"./shared/config.js\";\nimport { MetricHandler } from \"./metrics/index.js\";\nimport { TraceHandler } from \"./traces/handler.js\";\nimport { LogHandler } from \"./logs/index.js\";\nimport type {\n StatsbeatFeatures,\n StatsbeatInstrumentations,\n AzureMonitorOpenTelemetryOptions,\n InstrumentationOptions,\n BrowserSdkLoaderOptions,\n} from \"./types.js\";\nimport {\n AZURE_MONITOR_OPENTELEMETRY_VERSION,\n APPLICATIONINSIGHTS_SDKSTATS_DISABLED,\n} from \"./types.js\";\nimport { BrowserSdkLoader } from \"./browserSdkLoader/browserSdkLoader.js\";\nimport { setSdkPrefix } from \"./metrics/quickpulse/utils.js\";\nimport type { SpanProcessor } from \"@opentelemetry/sdk-trace-base\";\nimport type { LogRecordProcessor } from \"@opentelemetry/sdk-logs\";\nimport { getInstance } from \"./utils/statsbeat.js\";\nimport { patchOpenTelemetryInstrumentationEnable } from \"./utils/opentelemetryInstrumentationPatcher.js\";\nimport { ensureAzureSdkTracingBridge } from \"./utils/azureSdkTracingBridge.js\";\nimport { isFunctionApp, parseResourceDetectorsFromEnvVar } from \"./utils/common.js\";\nimport { Logger } from \"./shared/logging/index.js\";\nimport { AZURE_MONITOR_AUTO_ATTACH } from \"./types.js\";\nimport { SEMRESATTRS_K8S_CLUSTER_NAME } from \"@opentelemetry/semantic-conventions\";\n\n/**\n * Semantic attribute for cloud resource ID, defined by \\@opentelemetry/resource-detector-azure\n * @internal\n */\nconst CLOUD_RESOURCE_ID_ATTRIBUTE = \"cloud.resource_id\";\n\nexport type { AzureMonitorOpenTelemetryOptions, InstrumentationOptions, BrowserSdkLoaderOptions };\n\nprocess.env[\"AZURE_MONITOR_DISTRO_VERSION\"] = AZURE_MONITOR_OPENTELEMETRY_VERSION;\n\nlet sdk: NodeSDK;\nlet browserSdkLoader: BrowserSdkLoader | undefined;\n\n/**\n * Check if auto-attach (autoinstrumentation) is enabled and warn about double instrumentation.\n */\nfunction sendAttachWarning(): void {\n if (process.env[AZURE_MONITOR_AUTO_ATTACH] === \"true\" && !isFunctionApp()) {\n // TODO: When AKS attach is public, update this message with disablement instructions for AKS\n const message =\n \"Distro detected that automatic instrumentation may have occurred. Only use autoinstrumentation if you \" +\n \"are not using manual instrumentation of OpenTelemetry in your code, such as with \" +\n \"@azure/monitor-opentelemetry or @azure/monitor-opentelemetry-exporter. For App Service resources, disable \" +\n \"autoinstrumentation in the Application Insights experience on your App Service resource or by setting \" +\n \"the ApplicationInsightsAgent_EXTENSION_VERSION app setting to 'disabled'.\";\n // Surface in the log stream\n console.warn(message);\n // Also log via diagnostic logging\n Logger.getInstance().warn(message);\n }\n}\n\n/**\n * Initialize Azure Monitor Distro\n * @param options - Azure Monitor OpenTelemetry Options\n */\nexport function useAzureMonitor(options?: AzureMonitorOpenTelemetryOptions): void {\n const config = new InternalConfig(options);\n patchOpenTelemetryInstrumentationEnable();\n const statsbeatInstrumentations: StatsbeatInstrumentations = {\n // Instrumentations\n azureSdk: config.instrumentationOptions?.azureSdk?.enabled,\n mongoDb: config.instrumentationOptions?.mongoDb?.enabled,\n mySql: config.instrumentationOptions?.mySql?.enabled,\n postgreSql: config.instrumentationOptions?.postgreSql?.enabled,\n redis: config.instrumentationOptions?.redis?.enabled,\n bunyan: config.instrumentationOptions?.bunyan?.enabled,\n winston: config.instrumentationOptions?.winston?.enabled,\n };\n // Check if the AKS resource detector successfully populated specific resource attributes\n // (k8s.cluster.name or cloud.resource_id) beyond the basic cloud.platform/cloud.provider\n // Derive from config.resource.attributes which already includes the AKS detector results\n const resourceAttributes = config.resource.attributes;\n const aksResourceDetected =\n SEMRESATTRS_K8S_CLUSTER_NAME in resourceAttributes ||\n CLOUD_RESOURCE_ID_ATTRIBUTE in resourceAttributes;\n const statsbeatFeatures: StatsbeatFeatures = {\n browserSdkLoader: config.browserSdkLoaderOptions.enabled,\n aadHandling: !!config.azureMonitorExporterOptions?.credential,\n diskRetry: !config.azureMonitorExporterOptions?.disableOfflineStorage,\n customerSdkStats: process.env[APPLICATIONINSIGHTS_SDKSTATS_DISABLED]?.toLowerCase() === \"true\",\n aksResourceDetectorPopulation: aksResourceDetected,\n };\n getInstance().setStatsbeatFeatures(statsbeatInstrumentations, statsbeatFeatures);\n\n if (config.browserSdkLoaderOptions.enabled) {\n browserSdkLoader = new BrowserSdkLoader(config);\n }\n // Remove global providers in OpenTelemetry, these would be overridden if present\n metrics.disable();\n trace.disable();\n logs.disable();\n\n // Clear the entire OpenTelemetry API global state to avoid version conflicts.\n // The disable() calls above remove individual providers but leave the `version` field\n // on the global object intact. If a different version of @opentelemetry/api was loaded\n // first (e.g. by a VS Code extension host or another extension), the stale version\n // causes registerGlobal() in sdk.start() to fail with \"All API registration versions\n // must match\", resulting in Noop providers. Deleting the global object forces\n // registerGlobal() to create a fresh one with the correct version.\n const globalOpentelemetryApiKey = Symbol.for(\"opentelemetry.js.api.1\");\n Reflect.deleteProperty(globalThis, globalOpentelemetryApiKey);\n\n // Create internal handlers\n const metricHandler = new MetricHandler(config);\n const traceHandler = new TraceHandler(config, metricHandler);\n const logHandler = new LogHandler(config, metricHandler);\n\n const instrumentations = traceHandler\n .getInstrumentations()\n .concat(logHandler.getInstrumentations());\n\n const resourceDetectorsList = parseResourceDetectorsFromEnvVar();\n\n // Add extra SpanProcessors, and logRecordProcessors from user configuration\n const spanProcessors: SpanProcessor[] = options?.spanProcessors || [];\n const logRecordProcessors: LogRecordProcessor[] = options?.logRecordProcessors || [];\n const customViews: ViewOptions[] = options?.views || [];\n\n // Prepare metric readers - always include Azure Monitor\n const metricReaders: MetricReader[] = [\n metricHandler.getMetricReader(),\n ...(options?.metricReaders || []),\n ];\n\n const views: ViewOptions[] = metricHandler.getViews().concat(customViews);\n\n // Initialize OpenTelemetry SDK\n const sdkConfig: Partial<NodeSDKConfiguration> = {\n autoDetectResources: true,\n metricReaders: metricReaders,\n views,\n instrumentations: instrumentations,\n logRecordProcessors: [\n logHandler.getAzureLogRecordProcessor(),\n ...logRecordProcessors,\n logHandler.getBatchLogRecordProcessor(),\n ],\n resource: config.resource,\n sampler: traceHandler.getSampler(),\n spanProcessors: [\n traceHandler.getAzureMonitorSpanProcessor(),\n ...spanProcessors,\n traceHandler.getBatchSpanProcessor(),\n ],\n resourceDetectors: resourceDetectorsList,\n };\n sdk = new NodeSDK(sdkConfig);\n setSdkPrefix();\n sendAttachWarning();\n sdk.start();\n\n // Eagerly install the Azure SDK tracing bridge in case @azure/core-tracing\n // was loaded before useAzureMonitor() (the RITM hook misses it otherwise).\n ensureAzureSdkTracingBridge();\n}\n\n/**\n * Shutdown Azure Monitor Open Telemetry Distro\n * @see https://github.com/open-telemetry/opentelemetry-js/blob/0229434cb5a3179f63c021105f36270ae7897929/experimental/packages/opentelemetry-sdk-node/src/sdk.ts#L398\n */\nexport function shutdownAzureMonitor(): Promise<void> {\n browserSdkLoader?.dispose();\n return sdk?.shutdown();\n}\n\n/**\n * Get the internal SDK instance for testing purposes\n * @internal\n */\n// eslint-disable-next-line no-underscore-dangle\nexport function _getSdkInstance(): NodeSDK | undefined {\n return sdk;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/metrics/handler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,WAAW,EACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,6BAA6B,EAC9B,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAiDxE;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,oBAAoB,CAAC,CAA4B;IACzD,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAgB;IAE9B;;;;OAIG;gBACS,MAAM,EAAE,cAAc;IAmD3B,eAAe,IAAI,6BAA6B;IAIhD,QAAQ,IAAI,WAAW,EAAE;IAIzB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIrC,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAMpC,SAAS,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI;IAM/C;;OAEG;IAEU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKvC"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/metrics/handler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,WAAW,EACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,6BAA6B,EAC9B,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAiDxE;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,oBAAoB,CAAC,CAA4B;IACzD,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAgB;IAE9B;;;;OAIG;gBACS,MAAM,EAAE,cAAc;IAmD3B,eAAe,IAAI,6BAA6B;IAIhD,QAAQ,IAAI,WAAW,EAAE;IAIzB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIrC,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAMpC,SAAS,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI;IAM/C;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKvC"}
@@ -120,11 +120,10 @@ class MetricHandler {
120
120
  /**
121
121
  * Shutdown handler
122
122
  */
123
- // eslint-disable-next-line @typescript-eslint/require-await
124
123
  async shutdown() {
125
124
  this._standardMetrics?.shutdown();
126
- this._liveMetrics?.shutdown();
127
- this._performanceCounters?.shutdown();
125
+ await this._liveMetrics?.shutdown();
126
+ await this._performanceCounters?.shutdown();
128
127
  }
129
128
  }
130
129
  exports.MetricHandler = MetricHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/metrics/handler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { AzureMonitorMetricExporter } from \"@azure/monitor-opentelemetry-exporter\";\nimport type {\n AggregationOption,\n PeriodicExportingMetricReaderOptions,\n ViewOptions,\n} from \"@opentelemetry/sdk-metrics\";\nimport {\n AggregationType,\n InstrumentType,\n PeriodicExportingMetricReader,\n} from \"@opentelemetry/sdk-metrics\";\nimport type { SdkLogRecord } from \"@opentelemetry/sdk-logs\";\nimport type { InternalConfig } from \"../shared/config.js\";\nimport { StandardMetrics } from \"./standardMetrics.js\";\nimport type { ReadableSpan, Span } from \"@opentelemetry/sdk-trace-base\";\nimport { APPLICATION_INSIGHTS_NO_STANDARD_METRICS, HISTOGRAM_AGGREGATION_MAP } from \"./types.js\";\nimport { LiveMetrics } from \"./quickpulse/liveMetrics.js\";\nimport { PerformanceCounterMetrics } from \"./performanceCounters.js\";\nimport { Logger } from \"../shared/logging/index.js\";\n\ntype MetricExporterOptions = ConstructorParameters<typeof AzureMonitorMetricExporter>[0];\n\nconst DEFAULT_HISTOGRAM_AGGREGATION_ENV_VAR =\n \"OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION\";\n\nfunction resolveHistogramAggregationFromEnv(): AggregationOption | undefined {\n const envValue = process.env[DEFAULT_HISTOGRAM_AGGREGATION_ENV_VAR];\n if (!envValue) {\n return undefined;\n }\n\n const normalized = envValue.trim().toLowerCase();\n const aggregation = HISTOGRAM_AGGREGATION_MAP[normalized];\n if (aggregation) {\n return aggregation;\n }\n\n const validValues = Object.keys(HISTOGRAM_AGGREGATION_MAP)\n .map((v) => `'${v}'`)\n .join(\" and \");\n Logger.getInstance().warn(\n `${DEFAULT_HISTOGRAM_AGGREGATION_ENV_VAR} has unsupported value '${envValue}'. Supported values are ${validValues}.`,\n );\n return undefined;\n}\n\nclass AzureMonitorMetricExporterWithAggregation extends AzureMonitorMetricExporter {\n private _histogramAggregation?: AggregationOption;\n\n constructor(options: MetricExporterOptions, histogramAggregation?: AggregationOption) {\n super(options);\n this._histogramAggregation = histogramAggregation;\n }\n\n public selectAggregation(instrumentType: InstrumentType): AggregationOption {\n if (instrumentType === InstrumentType.HISTOGRAM && this._histogramAggregation) {\n return this._histogramAggregation;\n }\n\n return { type: AggregationType.DEFAULT };\n }\n}\n\n/**\n * Azure Monitor OpenTelemetry Metric Handler\n */\nexport class MetricHandler {\n private _azureExporter: AzureMonitorMetricExporter;\n private _metricReader: PeriodicExportingMetricReader;\n private _standardMetrics?: StandardMetrics;\n private _performanceCounters?: PerformanceCounterMetrics;\n private _liveMetrics?: LiveMetrics;\n private _config: InternalConfig;\n private _views: ViewOptions[];\n\n /**\n * Initializes a new instance of the MetricHandler class.\n * @param config - Distro configuration.\n * @param options - Metric Handler options.\n */\n constructor(config: InternalConfig) {\n const defaultInterval = 60000;\n this._config = config;\n // Adding Views of instrumentations will allow customer to add Metric Readers after, and get access to previously created metrics using the views shared state\n this._views = [];\n if (config.instrumentationOptions.azureSdk?.enabled) {\n this._views.push({ meterName: \"@azure/opentelemetry-instrumentation-azure-sdk\" });\n }\n if (config.instrumentationOptions.http?.enabled) {\n this._views.push({ meterName: \"@azure/opentelemetry-instrumentation-http\" });\n }\n if (config.instrumentationOptions.mongoDb?.enabled) {\n this._views.push({ meterName: \"@azure/opentelemetry-instrumentation-mongodb\" });\n }\n if (config.instrumentationOptions.mySql?.enabled) {\n this._views.push({ meterName: \"@opentelemetry/instrumentation-mysql\" });\n }\n if (config.instrumentationOptions.postgreSql?.enabled) {\n this._views.push({ meterName: \"@opentelemetry/instrumentation-pg\" });\n }\n if (\n config.instrumentationOptions.redis?.enabled ||\n config.instrumentationOptions.redis4?.enabled\n ) {\n this._views.push({ meterName: \"@opentelemetry/instrumentation-redis\" });\n }\n const histogramAggregation = resolveHistogramAggregationFromEnv();\n this._azureExporter = new AzureMonitorMetricExporterWithAggregation(\n this._config.azureMonitorExporterOptions,\n histogramAggregation,\n );\n const metricReaderOptions: PeriodicExportingMetricReaderOptions = {\n exporter: this._azureExporter as any,\n exportIntervalMillis: this._config.metricExportIntervalMillis || defaultInterval,\n };\n this._metricReader = new PeriodicExportingMetricReader(metricReaderOptions);\n\n if (\n this._config.enableStandardMetrics &&\n !process.env[APPLICATION_INSIGHTS_NO_STANDARD_METRICS]\n ) {\n this._standardMetrics = new StandardMetrics(this._config);\n }\n if (this._config.enableLiveMetrics) {\n this._liveMetrics = new LiveMetrics(this._config);\n }\n if (this._config.enablePerformanceCounters) {\n this._performanceCounters = new PerformanceCounterMetrics(this._config);\n }\n }\n\n public getMetricReader(): PeriodicExportingMetricReader {\n return this._metricReader;\n }\n\n public getViews(): ViewOptions[] {\n return this._views;\n }\n\n public markSpanAsProcessed(span: Span): void {\n this._standardMetrics?.markSpanAsProcessed(span);\n }\n\n public recordSpan(span: ReadableSpan): void {\n this._standardMetrics?.recordSpan(span);\n this._liveMetrics?.recordSpan(span);\n this._performanceCounters?.recordSpan(span);\n }\n\n public recordLog(logRecord: SdkLogRecord): void {\n this._standardMetrics?.recordLog(logRecord);\n this._liveMetrics?.recordLog(logRecord);\n this._performanceCounters?.recordLog(logRecord);\n }\n\n /**\n * Shutdown handler\n */\n // eslint-disable-next-line @typescript-eslint/require-await\n public async shutdown(): Promise<void> {\n this._standardMetrics?.shutdown();\n this._liveMetrics?.shutdown();\n this._performanceCounters?.shutdown();\n }\n}\n"]}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/metrics/handler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { AzureMonitorMetricExporter } from \"@azure/monitor-opentelemetry-exporter\";\nimport type {\n AggregationOption,\n PeriodicExportingMetricReaderOptions,\n ViewOptions,\n} from \"@opentelemetry/sdk-metrics\";\nimport {\n AggregationType,\n InstrumentType,\n PeriodicExportingMetricReader,\n} from \"@opentelemetry/sdk-metrics\";\nimport type { SdkLogRecord } from \"@opentelemetry/sdk-logs\";\nimport type { InternalConfig } from \"../shared/config.js\";\nimport { StandardMetrics } from \"./standardMetrics.js\";\nimport type { ReadableSpan, Span } from \"@opentelemetry/sdk-trace-base\";\nimport { APPLICATION_INSIGHTS_NO_STANDARD_METRICS, HISTOGRAM_AGGREGATION_MAP } from \"./types.js\";\nimport { LiveMetrics } from \"./quickpulse/liveMetrics.js\";\nimport { PerformanceCounterMetrics } from \"./performanceCounters.js\";\nimport { Logger } from \"../shared/logging/index.js\";\n\ntype MetricExporterOptions = ConstructorParameters<typeof AzureMonitorMetricExporter>[0];\n\nconst DEFAULT_HISTOGRAM_AGGREGATION_ENV_VAR =\n \"OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION\";\n\nfunction resolveHistogramAggregationFromEnv(): AggregationOption | undefined {\n const envValue = process.env[DEFAULT_HISTOGRAM_AGGREGATION_ENV_VAR];\n if (!envValue) {\n return undefined;\n }\n\n const normalized = envValue.trim().toLowerCase();\n const aggregation = HISTOGRAM_AGGREGATION_MAP[normalized];\n if (aggregation) {\n return aggregation;\n }\n\n const validValues = Object.keys(HISTOGRAM_AGGREGATION_MAP)\n .map((v) => `'${v}'`)\n .join(\" and \");\n Logger.getInstance().warn(\n `${DEFAULT_HISTOGRAM_AGGREGATION_ENV_VAR} has unsupported value '${envValue}'. Supported values are ${validValues}.`,\n );\n return undefined;\n}\n\nclass AzureMonitorMetricExporterWithAggregation extends AzureMonitorMetricExporter {\n private _histogramAggregation?: AggregationOption;\n\n constructor(options: MetricExporterOptions, histogramAggregation?: AggregationOption) {\n super(options);\n this._histogramAggregation = histogramAggregation;\n }\n\n public selectAggregation(instrumentType: InstrumentType): AggregationOption {\n if (instrumentType === InstrumentType.HISTOGRAM && this._histogramAggregation) {\n return this._histogramAggregation;\n }\n\n return { type: AggregationType.DEFAULT };\n }\n}\n\n/**\n * Azure Monitor OpenTelemetry Metric Handler\n */\nexport class MetricHandler {\n private _azureExporter: AzureMonitorMetricExporter;\n private _metricReader: PeriodicExportingMetricReader;\n private _standardMetrics?: StandardMetrics;\n private _performanceCounters?: PerformanceCounterMetrics;\n private _liveMetrics?: LiveMetrics;\n private _config: InternalConfig;\n private _views: ViewOptions[];\n\n /**\n * Initializes a new instance of the MetricHandler class.\n * @param config - Distro configuration.\n * @param options - Metric Handler options.\n */\n constructor(config: InternalConfig) {\n const defaultInterval = 60000;\n this._config = config;\n // Adding Views of instrumentations will allow customer to add Metric Readers after, and get access to previously created metrics using the views shared state\n this._views = [];\n if (config.instrumentationOptions.azureSdk?.enabled) {\n this._views.push({ meterName: \"@azure/opentelemetry-instrumentation-azure-sdk\" });\n }\n if (config.instrumentationOptions.http?.enabled) {\n this._views.push({ meterName: \"@azure/opentelemetry-instrumentation-http\" });\n }\n if (config.instrumentationOptions.mongoDb?.enabled) {\n this._views.push({ meterName: \"@azure/opentelemetry-instrumentation-mongodb\" });\n }\n if (config.instrumentationOptions.mySql?.enabled) {\n this._views.push({ meterName: \"@opentelemetry/instrumentation-mysql\" });\n }\n if (config.instrumentationOptions.postgreSql?.enabled) {\n this._views.push({ meterName: \"@opentelemetry/instrumentation-pg\" });\n }\n if (\n config.instrumentationOptions.redis?.enabled ||\n config.instrumentationOptions.redis4?.enabled\n ) {\n this._views.push({ meterName: \"@opentelemetry/instrumentation-redis\" });\n }\n const histogramAggregation = resolveHistogramAggregationFromEnv();\n this._azureExporter = new AzureMonitorMetricExporterWithAggregation(\n this._config.azureMonitorExporterOptions,\n histogramAggregation,\n );\n const metricReaderOptions: PeriodicExportingMetricReaderOptions = {\n exporter: this._azureExporter,\n exportIntervalMillis: this._config.metricExportIntervalMillis || defaultInterval,\n };\n this._metricReader = new PeriodicExportingMetricReader(metricReaderOptions);\n\n if (\n this._config.enableStandardMetrics &&\n !process.env[APPLICATION_INSIGHTS_NO_STANDARD_METRICS]\n ) {\n this._standardMetrics = new StandardMetrics(this._config);\n }\n if (this._config.enableLiveMetrics) {\n this._liveMetrics = new LiveMetrics(this._config);\n }\n if (this._config.enablePerformanceCounters) {\n this._performanceCounters = new PerformanceCounterMetrics(this._config);\n }\n }\n\n public getMetricReader(): PeriodicExportingMetricReader {\n return this._metricReader;\n }\n\n public getViews(): ViewOptions[] {\n return this._views;\n }\n\n public markSpanAsProcessed(span: Span): void {\n this._standardMetrics?.markSpanAsProcessed(span);\n }\n\n public recordSpan(span: ReadableSpan): void {\n this._standardMetrics?.recordSpan(span);\n this._liveMetrics?.recordSpan(span);\n this._performanceCounters?.recordSpan(span);\n }\n\n public recordLog(logRecord: SdkLogRecord): void {\n this._standardMetrics?.recordLog(logRecord);\n this._liveMetrics?.recordLog(logRecord);\n this._performanceCounters?.recordLog(logRecord);\n }\n\n /**\n * Shutdown handler\n */\n public async shutdown(): Promise<void> {\n this._standardMetrics?.shutdown();\n await this._liveMetrics?.shutdown();\n await this._performanceCounters?.shutdown();\n }\n}\n"]}
@@ -24,7 +24,6 @@ export declare class QuickpulseSender {
24
24
  private endpointUrl;
25
25
  private credential;
26
26
  private credentialScopes;
27
- private quickpulseClientOptions;
28
27
  constructor(options: {
29
28
  endpointUrl: string;
30
29
  instrumentationKey: string;
@@ -42,6 +41,16 @@ export declare class QuickpulseSender {
42
41
  * @internal
43
42
  */
44
43
  publish(optionalParams: PublishOptionalParams): Promise<QuickpulseResponse | undefined>;
44
+ /**
45
+ * Apply a server-issued Live Metrics redirect (`x-ms-qps-service-endpoint-redirect-v2`) by
46
+ * re-pointing the underlying client at the new host.
47
+ *
48
+ * Cross-origin redirects are refused (no state mutated) when the target is neither the configured
49
+ * Live Metrics host nor under a known Azure Monitor ingestion domain suffix. Refusing them is
50
+ * required to prevent an attacker-controlled redirect from causing the bearer auth policy to
51
+ * attach a freshly-signed AAD token (scope `https://monitor.azure.com/.default`) — and the
52
+ * telemetry body — to a foreign host on the next ping/publish call.
53
+ */
45
54
  handlePermanentRedirect(location: string | undefined): void;
46
55
  }
47
56
  //# sourceMappingURL=sender.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/export/sender.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EACV,0BAA0B,EAC1B,qBAAqB,EAErB,2BAA2B,EAC5B,MAAM,6BAA6B,CAAC;AAKrC;;;GAGG;AACH,MAAM,WAAW,kBAAmB,SAAQ,2BAA2B;IACrE,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,6CAA6C;IAC7C,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,yCAAyC;IACzC,+BAA+B,CAAC,EAAE,MAAM,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,gBAAgB,CAAW;IAEnC,OAAO,CAAC,uBAAuB,CAG7B;gBAEU,OAAO,EAAE;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,UAAU,CAAC,EAAE,eAAe,CAAC;QAC7B,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KACtC;IA+BD,OAAO,CAAC,sBAAsB;IAO9B;;;OAGG;IACG,YAAY,CAChB,cAAc,EAAE,0BAA0B,GACzC,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAuB1C;;;OAGG;IACG,OAAO,CAAC,cAAc,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAqB7F,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;CAa5D"}
1
+ {"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/export/sender.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EACV,0BAA0B,EAC1B,qBAAqB,EAErB,2BAA2B,EAC5B,MAAM,6BAA6B,CAAC;AAMrC;;;GAGG;AACH,MAAM,WAAW,kBAAmB,SAAQ,2BAA2B;IACrE,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,6CAA6C;IAC7C,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,yCAAyC;IACzC,+BAA+B,CAAC,EAAE,MAAM,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,gBAAgB,CAAW;gBAEvB,OAAO,EAAE;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,UAAU,CAAC,EAAE,eAAe,CAAC;QAC7B,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KACtC;IAyBD,OAAO,CAAC,sBAAsB;IAO9B;;;OAGG;IACG,YAAY,CAChB,cAAc,EAAE,0BAA0B,GACzC,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAuB1C;;;OAGG;IACG,OAAO,CAAC,cAAc,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAqB7F;;;;;;;;;OASG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;CAkC5D"}
@@ -8,6 +8,7 @@ const url_1 = tslib_1.__importDefault(require("url"));
8
8
  const core_rest_pipeline_1 = require("@azure/core-rest-pipeline");
9
9
  const api_1 = require("@opentelemetry/api");
10
10
  const index_js_1 = require("../../../generated/index.js");
11
+ const redirectUtils_js_1 = require("../redirectUtils.js");
11
12
  const applicationInsightsResource = "https://monitor.azure.com/.default";
12
13
  /**
13
14
  * Quickpulse sender class
@@ -19,8 +20,6 @@ class QuickpulseSender {
19
20
  endpointUrl;
20
21
  credential;
21
22
  credentialScopes;
22
- // @ts-expect-error - assigned in constructor, accessed by tests via bracket notation
23
- quickpulseClientOptions;
24
23
  constructor(options) {
25
24
  // Build endpoint using provided configuration or default values
26
25
  this.endpointUrl = options.endpointUrl;
@@ -41,11 +40,6 @@ class QuickpulseSender {
41
40
  if (options.credential) {
42
41
  clientOptions.credentials = { scopes: this.credentialScopes };
43
42
  }
44
- // Store credential info for testability
45
- this.quickpulseClientOptions = {
46
- credential: options.credential,
47
- credentialScopes: this.credentialScopes,
48
- };
49
43
  this.quickpulseClient = this.createQuickpulseClient(clientOptions);
50
44
  }
51
45
  createQuickpulseClient(clientOptions) {
@@ -106,17 +100,45 @@ class QuickpulseSender {
106
100
  }
107
101
  return;
108
102
  }
103
+ /**
104
+ * Apply a server-issued Live Metrics redirect (`x-ms-qps-service-endpoint-redirect-v2`) by
105
+ * re-pointing the underlying client at the new host.
106
+ *
107
+ * Cross-origin redirects are refused (no state mutated) when the target is neither the configured
108
+ * Live Metrics host nor under a known Azure Monitor ingestion domain suffix. Refusing them is
109
+ * required to prevent an attacker-controlled redirect from causing the bearer auth policy to
110
+ * attach a freshly-signed AAD token (scope `https://monitor.azure.com/.default`) — and the
111
+ * telemetry body — to a foreign host on the next ping/publish call.
112
+ */
109
113
  handlePermanentRedirect(location) {
110
114
  if (location) {
111
- const locUrl = new url_1.default.URL(location);
112
- if (locUrl && locUrl.host) {
113
- this.endpointUrl = "https://" + locUrl.host;
114
- // Recreate the client so subsequent requests use the new endpoint
115
- this.quickpulseClient = this.createQuickpulseClient({
116
- endpoint: this.endpointUrl,
117
- credentials: { scopes: this.credentialScopes },
118
- });
115
+ let locUrl;
116
+ try {
117
+ locUrl = new url_1.default.URL(location);
118
+ }
119
+ catch {
120
+ return;
121
+ }
122
+ if (!locUrl.host) {
123
+ return;
119
124
  }
125
+ let currentHost = "";
126
+ try {
127
+ currentHost = new url_1.default.URL(this.endpointUrl).host;
128
+ }
129
+ catch {
130
+ currentHost = "";
131
+ }
132
+ if (!(0, redirectUtils_js_1.isSameRegisteredDomain)(currentHost, locUrl.host)) {
133
+ api_1.diag.error(`Refusing cross-origin Live Metrics redirect to https://${locUrl.host}: target is neither the configured endpoint host nor under a known Azure Monitor ingestion domain.`);
134
+ return;
135
+ }
136
+ this.endpointUrl = "https://" + locUrl.host;
137
+ // Recreate the client so subsequent requests use the new endpoint
138
+ this.quickpulseClient = this.createQuickpulseClient({
139
+ endpoint: this.endpointUrl,
140
+ credentials: { scopes: this.credentialScopes },
141
+ });
120
142
  }
121
143
  }
122
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sender.js","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/export/sender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport url from \"url\";\nimport type { RestError } from \"@azure/core-rest-pipeline\";\nimport { redirectPolicyName } from \"@azure/core-rest-pipeline\";\nimport type { TokenCredential } from \"@azure/core-auth\";\nimport { diag } from \"@opentelemetry/api\";\nimport type {\n IsSubscribedOptionalParams,\n PublishOptionalParams,\n QuickpulseClientOptionalParams,\n CollectionConfigurationInfo,\n} from \"../../../generated/index.js\";\nimport { QuickpulseClient } from \"../../../generated/index.js\";\n\nconst applicationInsightsResource = \"https://monitor.azure.com/.default\";\n\n/**\n * Response type that includes the body and response headers from the Live Metrics service.\n * @internal\n */\nexport interface QuickpulseResponse extends CollectionConfigurationInfo {\n /** Whether the instrumentation key is subscribed. */\n xMsQpsSubscribed?: string;\n /** Configuration ETag. */\n xMsQpsConfigurationEtag?: string;\n /** Polling interval hint (only for ping). */\n xMsQpsServicePollingIntervalHint?: string;\n /** Endpoint redirect (only for ping). */\n xMsQpsServiceEndpointRedirectV2?: string;\n}\n\n/**\n * Quickpulse sender class\n * @internal\n */\nexport class QuickpulseSender {\n private quickpulseClient: QuickpulseClient;\n private instrumentationKey: string;\n private endpointUrl: string;\n private credential: TokenCredential;\n private credentialScopes: string[];\n // @ts-expect-error - assigned in constructor, accessed by tests via bracket notation\n private quickpulseClientOptions: {\n credential?: TokenCredential;\n credentialScopes?: string[];\n };\n\n constructor(options: {\n endpointUrl: string;\n instrumentationKey: string;\n credential?: TokenCredential;\n credentialScopes?: string | string[];\n }) {\n // Build endpoint using provided configuration or default values\n this.endpointUrl = options.endpointUrl;\n const clientOptions: QuickpulseClientOptionalParams = {\n endpoint: this.endpointUrl,\n };\n\n this.instrumentationKey = options.instrumentationKey;\n this.credential = options.credential as TokenCredential;\n\n // Configure credential scopes\n if (options.credentialScopes) {\n this.credentialScopes = Array.isArray(options.credentialScopes)\n ? options.credentialScopes\n : [options.credentialScopes];\n } else {\n this.credentialScopes = [applicationInsightsResource];\n }\n if (options.credential) {\n clientOptions.credentials = { scopes: this.credentialScopes };\n }\n\n // Store credential info for testability\n this.quickpulseClientOptions = {\n credential: options.credential,\n credentialScopes: this.credentialScopes,\n };\n\n this.quickpulseClient = this.createQuickpulseClient(clientOptions);\n }\n\n private createQuickpulseClient(clientOptions: QuickpulseClientOptionalParams): QuickpulseClient {\n const client = new QuickpulseClient(this.credential, clientOptions);\n // Handle redirects in HTTP Sender\n client.pipeline.removePolicy({ name: redirectPolicyName });\n return client;\n }\n\n /**\n * isSubscribed Quickpulse service\n * @internal\n */\n async isSubscribed(\n optionalParams: IsSubscribedOptionalParams,\n ): Promise<QuickpulseResponse | undefined> {\n try {\n let responseHeaders: Record<string, string> = {};\n const body = await this.quickpulseClient.isSubscribed(this.instrumentationKey, {\n ...optionalParams,\n onResponse: (rawResponse) => {\n responseHeaders = rawResponse.headers.toJSON();\n },\n });\n return {\n ...body,\n xMsQpsSubscribed: responseHeaders[\"x-ms-qps-subscribed\"],\n xMsQpsConfigurationEtag: responseHeaders[\"x-ms-qps-configuration-etag\"],\n xMsQpsServicePollingIntervalHint: responseHeaders[\"x-ms-qps-service-polling-interval-hint\"],\n xMsQpsServiceEndpointRedirectV2: responseHeaders[\"x-ms-qps-service-endpoint-redirect-v2\"],\n };\n } catch (error: any) {\n const restError = error as RestError;\n diag.info(\"Failed to ping Quickpulse service\", restError.message);\n }\n return;\n }\n\n /**\n * publish Quickpulse service\n * @internal\n */\n async publish(optionalParams: PublishOptionalParams): Promise<QuickpulseResponse | undefined> {\n try {\n let responseHeaders: Record<string, string> = {};\n const body = await this.quickpulseClient.publish(this.instrumentationKey, {\n ...optionalParams,\n onResponse: (rawResponse) => {\n responseHeaders = rawResponse.headers.toJSON();\n },\n });\n return {\n ...body,\n xMsQpsSubscribed: responseHeaders[\"x-ms-qps-subscribed\"],\n xMsQpsConfigurationEtag: responseHeaders[\"x-ms-qps-configuration-etag\"],\n };\n } catch (error: any) {\n const restError = error as RestError;\n diag.warn(\"Failed to post Quickpulse service\", restError.message);\n }\n return;\n }\n\n handlePermanentRedirect(location: string | undefined): void {\n if (location) {\n const locUrl = new url.URL(location);\n if (locUrl && locUrl.host) {\n this.endpointUrl = \"https://\" + locUrl.host;\n // Recreate the client so subsequent requests use the new endpoint\n this.quickpulseClient = this.createQuickpulseClient({\n endpoint: this.endpointUrl,\n credentials: { scopes: this.credentialScopes },\n });\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"sender.js","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/export/sender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport url from \"url\";\nimport type { RestError } from \"@azure/core-rest-pipeline\";\nimport { redirectPolicyName } from \"@azure/core-rest-pipeline\";\nimport type { TokenCredential } from \"@azure/core-auth\";\nimport { diag } from \"@opentelemetry/api\";\nimport type {\n IsSubscribedOptionalParams,\n PublishOptionalParams,\n QuickpulseClientOptionalParams,\n CollectionConfigurationInfo,\n} from \"../../../generated/index.js\";\nimport { QuickpulseClient } from \"../../../generated/index.js\";\nimport { isSameRegisteredDomain } from \"../redirectUtils.js\";\n\nconst applicationInsightsResource = \"https://monitor.azure.com/.default\";\n\n/**\n * Response type that includes the body and response headers from the Live Metrics service.\n * @internal\n */\nexport interface QuickpulseResponse extends CollectionConfigurationInfo {\n /** Whether the instrumentation key is subscribed. */\n xMsQpsSubscribed?: string;\n /** Configuration ETag. */\n xMsQpsConfigurationEtag?: string;\n /** Polling interval hint (only for ping). */\n xMsQpsServicePollingIntervalHint?: string;\n /** Endpoint redirect (only for ping). */\n xMsQpsServiceEndpointRedirectV2?: string;\n}\n\n/**\n * Quickpulse sender class\n * @internal\n */\nexport class QuickpulseSender {\n private quickpulseClient: QuickpulseClient;\n private instrumentationKey: string;\n private endpointUrl: string;\n private credential: TokenCredential;\n private credentialScopes: string[];\n\n constructor(options: {\n endpointUrl: string;\n instrumentationKey: string;\n credential?: TokenCredential;\n credentialScopes?: string | string[];\n }) {\n // Build endpoint using provided configuration or default values\n this.endpointUrl = options.endpointUrl;\n const clientOptions: QuickpulseClientOptionalParams = {\n endpoint: this.endpointUrl,\n };\n\n this.instrumentationKey = options.instrumentationKey;\n this.credential = options.credential as TokenCredential;\n\n // Configure credential scopes\n if (options.credentialScopes) {\n this.credentialScopes = Array.isArray(options.credentialScopes)\n ? options.credentialScopes\n : [options.credentialScopes];\n } else {\n this.credentialScopes = [applicationInsightsResource];\n }\n if (options.credential) {\n clientOptions.credentials = { scopes: this.credentialScopes };\n }\n\n this.quickpulseClient = this.createQuickpulseClient(clientOptions);\n }\n\n private createQuickpulseClient(clientOptions: QuickpulseClientOptionalParams): QuickpulseClient {\n const client = new QuickpulseClient(this.credential, clientOptions);\n // Handle redirects in HTTP Sender\n client.pipeline.removePolicy({ name: redirectPolicyName });\n return client;\n }\n\n /**\n * isSubscribed Quickpulse service\n * @internal\n */\n async isSubscribed(\n optionalParams: IsSubscribedOptionalParams,\n ): Promise<QuickpulseResponse | undefined> {\n try {\n let responseHeaders: Record<string, string> = {};\n const body = await this.quickpulseClient.isSubscribed(this.instrumentationKey, {\n ...optionalParams,\n onResponse: (rawResponse) => {\n responseHeaders = rawResponse.headers.toJSON();\n },\n });\n return {\n ...body,\n xMsQpsSubscribed: responseHeaders[\"x-ms-qps-subscribed\"],\n xMsQpsConfigurationEtag: responseHeaders[\"x-ms-qps-configuration-etag\"],\n xMsQpsServicePollingIntervalHint: responseHeaders[\"x-ms-qps-service-polling-interval-hint\"],\n xMsQpsServiceEndpointRedirectV2: responseHeaders[\"x-ms-qps-service-endpoint-redirect-v2\"],\n };\n } catch (error: any) {\n const restError = error as RestError;\n diag.info(\"Failed to ping Quickpulse service\", restError.message);\n }\n return;\n }\n\n /**\n * publish Quickpulse service\n * @internal\n */\n async publish(optionalParams: PublishOptionalParams): Promise<QuickpulseResponse | undefined> {\n try {\n let responseHeaders: Record<string, string> = {};\n const body = await this.quickpulseClient.publish(this.instrumentationKey, {\n ...optionalParams,\n onResponse: (rawResponse) => {\n responseHeaders = rawResponse.headers.toJSON();\n },\n });\n return {\n ...body,\n xMsQpsSubscribed: responseHeaders[\"x-ms-qps-subscribed\"],\n xMsQpsConfigurationEtag: responseHeaders[\"x-ms-qps-configuration-etag\"],\n };\n } catch (error: any) {\n const restError = error as RestError;\n diag.warn(\"Failed to post Quickpulse service\", restError.message);\n }\n return;\n }\n\n /**\n * Apply a server-issued Live Metrics redirect (`x-ms-qps-service-endpoint-redirect-v2`) by\n * re-pointing the underlying client at the new host.\n *\n * Cross-origin redirects are refused (no state mutated) when the target is neither the configured\n * Live Metrics host nor under a known Azure Monitor ingestion domain suffix. Refusing them is\n * required to prevent an attacker-controlled redirect from causing the bearer auth policy to\n * attach a freshly-signed AAD token (scope `https://monitor.azure.com/.default`) — and the\n * telemetry body — to a foreign host on the next ping/publish call.\n */\n handlePermanentRedirect(location: string | undefined): void {\n if (location) {\n let locUrl: url.URL;\n try {\n locUrl = new url.URL(location);\n } catch {\n return;\n }\n if (!locUrl.host) {\n return;\n }\n\n let currentHost = \"\";\n try {\n currentHost = new url.URL(this.endpointUrl).host;\n } catch {\n currentHost = \"\";\n }\n\n if (!isSameRegisteredDomain(currentHost, locUrl.host)) {\n diag.error(\n `Refusing cross-origin Live Metrics redirect to https://${locUrl.host}: target is neither the configured endpoint host nor under a known Azure Monitor ingestion domain.`,\n );\n return;\n }\n\n this.endpointUrl = \"https://\" + locUrl.host;\n // Recreate the client so subsequent requests use the new endpoint\n this.quickpulseClient = this.createQuickpulseClient({\n endpoint: this.endpointUrl,\n credentials: { scopes: this.credentialScopes },\n });\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/filtering/filter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EAEjB,0BAA0B,EAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAEV,aAAa,EAId,MAAM,aAAa,CAAC;AAUrB,qBAAa,MAAM;IACV,qCAAqC,CAC1C,0BAA0B,EAAE,0BAA0B,GACrD,IAAI;IAQA,kBAAkB,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO;IAetF,2BAA2B,CAChC,0BAA0B,EAAE,0BAA0B,EACtD,IAAI,EAAE,aAAa,GAClB,OAAO;IAUV,OAAO,CAAC,WAAW;IA4DnB,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,aAAa;CAoBtB"}
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/filtering/filter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EAEjB,0BAA0B,EAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAEV,aAAa,EAId,MAAM,aAAa,CAAC;AAUrB,qBAAa,MAAM;IACV,qCAAqC,CAC1C,0BAA0B,EAAE,0BAA0B,GACrD,IAAI;IAQA,kBAAkB,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO;IAetF,2BAA2B,CAChC,0BAA0B,EAAE,0BAA0B,EACtD,IAAI,EAAE,aAAa,GAClB,OAAO;IAUV,OAAO,CAAC,WAAW;IA4DnB,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,aAAa;CAoBtB"}
@@ -124,11 +124,8 @@ class Filter {
124
124
  }
125
125
  checkCustomDimFilter(filter, data) {
126
126
  const fieldName = filter.fieldName.replace("CustomDimensions.", "");
127
- let value;
128
- if (data.CustomDimensions.has(fieldName)) {
129
- value = data.CustomDimensions.get(fieldName);
130
- }
131
- else {
127
+ const value = data.CustomDimensions.get(fieldName);
128
+ if (value === undefined) {
132
129
  return false; // the asked for field is not present in the custom dimensions
133
130
  }
134
131
  return this.stringCompare(value, filter.comparand, filter.predicate);
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/filtering/filter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type {\n DerivedMetricInfo,\n FilterInfo,\n FilterConjunctionGroupInfo,\n} from \"../../../generated/index.js\";\nimport type {\n RequestData,\n TelemetryData,\n DependencyData,\n ExceptionData,\n TraceData,\n} from \"../types.js\";\nimport { KnownDependencyColumns, KnownRequestColumns } from \"../types.js\";\nimport {\n isRequestData,\n isDependencyData,\n isExceptionData,\n isTraceData,\n getMsFromFilterTimestampString,\n} from \"../utils.js\";\n\nexport class Filter {\n public renameExceptionFieldNamesForFiltering(\n filterConjunctionGroupInfo: FilterConjunctionGroupInfo,\n ): void {\n filterConjunctionGroupInfo.filters.forEach((filter) => {\n if (filter.fieldName.startsWith(\"Exception.\")) {\n filter.fieldName = filter.fieldName.replace(\"Exception.\", \"\");\n }\n });\n }\n\n public checkMetricFilters(derivedMetricInfo: DerivedMetricInfo, data: TelemetryData): boolean {\n if (derivedMetricInfo.filterGroups.length === 0) {\n // This should never happen - even when a user does not add filter pills to the derived metric,\n // the filterGroups array should have one filter group with an empty array of filters.\n return true;\n }\n // Haven't yet seen any case where there is more than one filter group in a derived metric info.\n // Just to be safe, handling the multiple filter conjunction group case as an or operation.\n let matched = false;\n derivedMetricInfo.filterGroups.forEach((filterConjunctionGroup) => {\n matched = matched || this.checkFilterConjunctionGroup(filterConjunctionGroup, data);\n });\n return matched;\n }\n\n public checkFilterConjunctionGroup(\n filterConjunctionGroupInfo: FilterConjunctionGroupInfo,\n data: TelemetryData,\n ): boolean {\n // All of the filters need to match for this to return true (and operation).\n for (const filter of filterConjunctionGroupInfo.filters) {\n if (!this.checkFilter(filter, data)) {\n return false;\n }\n }\n return true;\n }\n\n private checkFilter(filter: FilterInfo, data: TelemetryData): boolean {\n if (filter.fieldName === \"*\") {\n // Any field\n return this.checkAnyFieldFilter(filter, data);\n } else if (filter.fieldName.startsWith(\"CustomDimensions.\")) {\n return this.checkCustomDimFilter(filter, data);\n } else {\n let dataValue: string | number | boolean | Map<string, string>;\n // use filter.fieldname to get the property of data to query\n if (isRequestData(data)) {\n dataValue = data[filter.fieldName as keyof RequestData];\n } else if (isDependencyData(data)) {\n dataValue = data[filter.fieldName as keyof DependencyData];\n } else if (isExceptionData(data)) {\n dataValue = data[filter.fieldName as keyof ExceptionData];\n } else if (isTraceData(data)) {\n dataValue = data[filter.fieldName as keyof TraceData];\n } else {\n return false; // should not reach here\n }\n\n if (filter.fieldName === KnownRequestColumns.Success.toString()) {\n if (filter.predicate === \"Equal\") {\n return dataValue === (filter.comparand.toLowerCase() === \"true\");\n } else if (filter.predicate === \"NotEqual\") {\n return dataValue !== (filter.comparand.toLowerCase() === \"true\");\n }\n } else if (\n filter.fieldName === KnownDependencyColumns.ResultCode.toString() ||\n filter.fieldName === KnownRequestColumns.ResponseCode.toString() ||\n filter.fieldName === KnownDependencyColumns.Duration.toString()\n ) {\n const comparand: number =\n filter.fieldName === KnownDependencyColumns.Duration.toString()\n ? getMsFromFilterTimestampString(filter.comparand)\n : parseFloat(filter.comparand);\n switch (filter.predicate) {\n case \"Equal\":\n return dataValue === comparand;\n case \"NotEqual\":\n return dataValue !== comparand;\n case \"GreaterThan\":\n return (dataValue as number) > comparand;\n case \"GreaterThanOrEqual\":\n return (dataValue as number) >= comparand;\n case \"LessThan\":\n return (dataValue as number) < comparand;\n case \"LessThanOrEqual\":\n return (dataValue as number) <= comparand;\n default:\n return false;\n }\n } else {\n // string fields\n return this.stringCompare(dataValue as string, filter.comparand, filter.predicate);\n }\n }\n return false;\n }\n\n private checkAnyFieldFilter(filter: FilterInfo, data: TelemetryData): boolean {\n const properties: string[] = Object.keys(data);\n // At this point, the only predicates possible to pass in are Contains and DoesNotContain\n // At config validation time the predicate is checked to be one of these two.\n for (const property of properties) {\n if (property === \"CustomDimensions\") {\n for (const value of data.CustomDimensions.values()) {\n if (this.stringCompare(value, filter.comparand, filter.predicate)) {\n return true;\n }\n }\n } else {\n // @ts-expect-error - data can be any type of telemetry data and we know property is a valid key\n const value: string = String(data[property]);\n if (this.stringCompare(value, filter.comparand, filter.predicate)) {\n return true;\n }\n }\n }\n return false;\n }\n\n private checkCustomDimFilter(filter: FilterInfo, data: TelemetryData): boolean {\n const fieldName: string = filter.fieldName.replace(\"CustomDimensions.\", \"\");\n let value: string | undefined;\n if (data.CustomDimensions.has(fieldName)) {\n value = data.CustomDimensions.get(fieldName) as string;\n } else {\n return false; // the asked for field is not present in the custom dimensions\n }\n return this.stringCompare(value, filter.comparand, filter.predicate);\n }\n\n private stringCompare(dataValue: string, comparand: string, predicate: string): boolean {\n switch (predicate) {\n case \"Equal\":\n return dataValue === comparand;\n case \"NotEqual\":\n return dataValue !== comparand;\n case \"Contains\": {\n const lowerDataValue = dataValue.toLowerCase();\n const lowerComparand = comparand.toLowerCase();\n return lowerDataValue.includes(lowerComparand);\n }\n case \"DoesNotContain\": {\n const lowerDataValue = dataValue.toLowerCase();\n const lowerComparand = comparand.toLowerCase();\n return !lowerDataValue.includes(lowerComparand);\n }\n default:\n return false;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../../../src/metrics/quickpulse/filtering/filter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type {\n DerivedMetricInfo,\n FilterInfo,\n FilterConjunctionGroupInfo,\n} from \"../../../generated/index.js\";\nimport type {\n RequestData,\n TelemetryData,\n DependencyData,\n ExceptionData,\n TraceData,\n} from \"../types.js\";\nimport { KnownDependencyColumns, KnownRequestColumns } from \"../types.js\";\nimport {\n isRequestData,\n isDependencyData,\n isExceptionData,\n isTraceData,\n getMsFromFilterTimestampString,\n} from \"../utils.js\";\n\nexport class Filter {\n public renameExceptionFieldNamesForFiltering(\n filterConjunctionGroupInfo: FilterConjunctionGroupInfo,\n ): void {\n filterConjunctionGroupInfo.filters.forEach((filter) => {\n if (filter.fieldName.startsWith(\"Exception.\")) {\n filter.fieldName = filter.fieldName.replace(\"Exception.\", \"\");\n }\n });\n }\n\n public checkMetricFilters(derivedMetricInfo: DerivedMetricInfo, data: TelemetryData): boolean {\n if (derivedMetricInfo.filterGroups.length === 0) {\n // This should never happen - even when a user does not add filter pills to the derived metric,\n // the filterGroups array should have one filter group with an empty array of filters.\n return true;\n }\n // Haven't yet seen any case where there is more than one filter group in a derived metric info.\n // Just to be safe, handling the multiple filter conjunction group case as an or operation.\n let matched = false;\n derivedMetricInfo.filterGroups.forEach((filterConjunctionGroup) => {\n matched = matched || this.checkFilterConjunctionGroup(filterConjunctionGroup, data);\n });\n return matched;\n }\n\n public checkFilterConjunctionGroup(\n filterConjunctionGroupInfo: FilterConjunctionGroupInfo,\n data: TelemetryData,\n ): boolean {\n // All of the filters need to match for this to return true (and operation).\n for (const filter of filterConjunctionGroupInfo.filters) {\n if (!this.checkFilter(filter, data)) {\n return false;\n }\n }\n return true;\n }\n\n private checkFilter(filter: FilterInfo, data: TelemetryData): boolean {\n if (filter.fieldName === \"*\") {\n // Any field\n return this.checkAnyFieldFilter(filter, data);\n } else if (filter.fieldName.startsWith(\"CustomDimensions.\")) {\n return this.checkCustomDimFilter(filter, data);\n } else {\n let dataValue: string | number | boolean | Map<string, string>;\n // use filter.fieldname to get the property of data to query\n if (isRequestData(data)) {\n dataValue = data[filter.fieldName as keyof RequestData];\n } else if (isDependencyData(data)) {\n dataValue = data[filter.fieldName as keyof DependencyData];\n } else if (isExceptionData(data)) {\n dataValue = data[filter.fieldName as keyof ExceptionData];\n } else if (isTraceData(data)) {\n dataValue = data[filter.fieldName as keyof TraceData];\n } else {\n return false; // should not reach here\n }\n\n if (filter.fieldName === KnownRequestColumns.Success.toString()) {\n if (filter.predicate === \"Equal\") {\n return dataValue === (filter.comparand.toLowerCase() === \"true\");\n } else if (filter.predicate === \"NotEqual\") {\n return dataValue !== (filter.comparand.toLowerCase() === \"true\");\n }\n } else if (\n filter.fieldName === KnownDependencyColumns.ResultCode.toString() ||\n filter.fieldName === KnownRequestColumns.ResponseCode.toString() ||\n filter.fieldName === KnownDependencyColumns.Duration.toString()\n ) {\n const comparand: number =\n filter.fieldName === KnownDependencyColumns.Duration.toString()\n ? getMsFromFilterTimestampString(filter.comparand)\n : parseFloat(filter.comparand);\n switch (filter.predicate) {\n case \"Equal\":\n return dataValue === comparand;\n case \"NotEqual\":\n return dataValue !== comparand;\n case \"GreaterThan\":\n return (dataValue as number) > comparand;\n case \"GreaterThanOrEqual\":\n return (dataValue as number) >= comparand;\n case \"LessThan\":\n return (dataValue as number) < comparand;\n case \"LessThanOrEqual\":\n return (dataValue as number) <= comparand;\n default:\n return false;\n }\n } else {\n // string fields\n return this.stringCompare(dataValue as string, filter.comparand, filter.predicate);\n }\n }\n return false;\n }\n\n private checkAnyFieldFilter(filter: FilterInfo, data: TelemetryData): boolean {\n const properties: string[] = Object.keys(data);\n // At this point, the only predicates possible to pass in are Contains and DoesNotContain\n // At config validation time the predicate is checked to be one of these two.\n for (const property of properties) {\n if (property === \"CustomDimensions\") {\n for (const value of data.CustomDimensions.values()) {\n if (this.stringCompare(value, filter.comparand, filter.predicate)) {\n return true;\n }\n }\n } else {\n // @ts-expect-error - data can be any type of telemetry data and we know property is a valid key\n const value: string = String(data[property]);\n if (this.stringCompare(value, filter.comparand, filter.predicate)) {\n return true;\n }\n }\n }\n return false;\n }\n\n private checkCustomDimFilter(filter: FilterInfo, data: TelemetryData): boolean {\n const fieldName: string = filter.fieldName.replace(\"CustomDimensions.\", \"\");\n const value = data.CustomDimensions.get(fieldName);\n if (value === undefined) {\n return false; // the asked for field is not present in the custom dimensions\n }\n return this.stringCompare(value, filter.comparand, filter.predicate);\n }\n\n private stringCompare(dataValue: string, comparand: string, predicate: string): boolean {\n switch (predicate) {\n case \"Equal\":\n return dataValue === comparand;\n case \"NotEqual\":\n return dataValue !== comparand;\n case \"Contains\": {\n const lowerDataValue = dataValue.toLowerCase();\n const lowerComparand = comparand.toLowerCase();\n return lowerDataValue.includes(lowerComparand);\n }\n case \"DoesNotContain\": {\n const lowerDataValue = dataValue.toLowerCase();\n const lowerComparand = comparand.toLowerCase();\n return !lowerDataValue.includes(lowerComparand);\n }\n default:\n return false;\n }\n }\n}\n"]}
@@ -28,6 +28,8 @@ export declare class LiveMetrics {
28
28
  private quickpulseExporter;
29
29
  private pingSender;
30
30
  private isCollectingData;
31
+ private isDeactivating;
32
+ private deactivatingPromise;
31
33
  private lastSuccessTime;
32
34
  private handle;
33
35
  private baseMonitoringDataPoint;
@@ -62,7 +64,7 @@ export declare class LiveMetrics {
62
64
  * @param options - Standard Metrics options.
63
65
  */
64
66
  constructor(config: InternalConfig);
65
- shutdown(): void;
67
+ shutdown(): Promise<void>;
66
68
  private goQuickpulse;
67
69
  private quickPulseDone;
68
70
  activateMetrics(options?: {
@@ -71,7 +73,7 @@ export declare class LiveMetrics {
71
73
  /**
72
74
  * Deactivate metric collection
73
75
  */
74
- deactivateMetrics(): void;
76
+ deactivateMetrics(): Promise<void>;
75
77
  /**
76
78
  * Force flush Meter Provider.
77
79
  */
@@ -1 +1 @@
1
- {"version":3,"file":"liveMetrics.d.ts","sourceRoot":"","sources":["../../../../src/metrics/quickpulse/liveMetrics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"liveMetrics.d.ts","sourceRoot":"","sources":["../../../../src/metrics/quickpulse/liveMetrics.ts"],"names":[],"mappings":"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"}
@@ -54,6 +54,8 @@ class LiveMetrics {
54
54
  quickpulseExporter;
55
55
  pingSender;
56
56
  isCollectingData;
57
+ isDeactivating = false;
58
+ deactivatingPromise;
57
59
  lastSuccessTime = Date.now();
58
60
  handle;
59
61
  // Monitoring data point with common properties
@@ -148,8 +150,15 @@ class LiveMetrics {
148
150
  this.lastCpuUsage = process.cpuUsage();
149
151
  this.lastHrTime = process.hrtime.bigint();
150
152
  }
151
- shutdown() {
152
- this.meterProvider?.shutdown();
153
+ async shutdown() {
154
+ // Force collecting=false before tearing down so the shutdown's final
155
+ // force-flush export, if it fails, cannot trigger the deactivate/
156
+ // reactivate fallback in quickPulseDone(). Delegate to deactivateMetrics()
157
+ // which manages the in-flight deactivation promise so callers (including
158
+ // a concurrent failure-fallback in quickPulseDone) all observe the same
159
+ // completion and shutdown waits for any in-flight deactivation to finish.
160
+ this.isCollectingData = false;
161
+ await this.deactivateMetrics();
153
162
  }
154
163
  async goQuickpulse() {
155
164
  if (!this.isCollectingData) {
@@ -176,7 +185,6 @@ class LiveMetrics {
176
185
  this.activateMetrics({ collectionInterval: this.postInterval });
177
186
  }
178
187
  }
179
- // eslint-disable-next-line @typescript-eslint/require-await
180
188
  async quickPulseDone(response) {
181
189
  if (!response) {
182
190
  if (!this.isCollectingData) {
@@ -186,9 +194,34 @@ class LiveMetrics {
186
194
  }
187
195
  else {
188
196
  if (Date.now() - this.lastSuccessTime >= MAX_POST_WAIT_TIME) {
197
+ // Re-entrancy guard: MeterProvider.shutdown() triggers a final
198
+ // force-flush export which, on failure, re-invokes this callback
199
+ // synchronously from inside the shutdown's export call. If a
200
+ // deactivation is already in flight, bail out — awaiting the
201
+ // in-flight promise here would deadlock the exporter's callback.
202
+ if (this.isDeactivating) {
203
+ return;
204
+ }
189
205
  this.postInterval = FALLBACK_INTERVAL;
190
- this.deactivateMetrics();
191
- this.activateMetrics({ collectionInterval: this.postInterval });
206
+ try {
207
+ await this.deactivateMetrics();
208
+ }
209
+ catch (error) {
210
+ // The exporter invokes postCallback without awaiting it, so a
211
+ // rejection here would surface as an unhandled rejection. Swallow
212
+ // and log so the failure path stays contained.
213
+ logger_js_1.Logger.getInstance().warn("Failed to deactivate Live Metrics during failure fallback", error);
214
+ }
215
+ // Reset the success-time baseline so the FALLBACK_INTERVAL backoff
216
+ // can take effect before we consider deactivating again.
217
+ this.lastSuccessTime = Date.now();
218
+ // Re-check after the await: shutdown() may have run concurrently and
219
+ // flipped isCollectingData to false. Don't restart collection in
220
+ // that case — doing so would re-create the meterProvider after
221
+ // shutdown has begun.
222
+ if (this.isCollectingData) {
223
+ this.activateMetrics({ collectionInterval: this.postInterval });
224
+ }
192
225
  }
193
226
  }
194
227
  }
@@ -204,7 +237,7 @@ class LiveMetrics {
204
237
  // If collecting was stoped
205
238
  if (!this.isCollectingData && this.meterProvider) {
206
239
  this.etag = "";
207
- this.deactivateMetrics();
240
+ await this.deactivateMetrics();
208
241
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
209
242
  this.handle = setTimeout(this.goQuickpulse.bind(this), this.pingInterval);
210
243
  this.handle.unref();
@@ -298,16 +331,38 @@ class LiveMetrics {
298
331
  /**
299
332
  * Deactivate metric collection
300
333
  */
301
- deactivateMetrics() {
302
- this.documents = [];
303
- this.validDocumentFilterConjuctionGroupInfos.clear();
304
- this.errorTracker.clearRunTimeErrors();
305
- this.errorTracker.clearValidationTimeErrors();
306
- this.validDerivedMetrics.clear();
307
- this.derivedMetricProjection.clearProjectionMaps();
308
- this.seenMetricIds.clear();
309
- this.meterProvider?.shutdown();
310
- this.meterProvider = undefined;
334
+ async deactivateMetrics() {
335
+ // Coalesce concurrent deactivations: callers (shutdown(), the
336
+ // failure-fallback in quickPulseDone(), and the "unsubscribed" branch in
337
+ // goQuickpulse()) can all race. Return the in-flight promise so every
338
+ // caller awaits the same completion and the underlying meterProvider
339
+ // shutdown only runs once.
340
+ if (this.deactivatingPromise) {
341
+ return this.deactivatingPromise;
342
+ }
343
+ this.isDeactivating = true;
344
+ this.deactivatingPromise = (async () => {
345
+ try {
346
+ this.documents = [];
347
+ this.validDocumentFilterConjuctionGroupInfos.clear();
348
+ this.errorTracker.clearRunTimeErrors();
349
+ this.errorTracker.clearValidationTimeErrors();
350
+ this.validDerivedMetrics.clear();
351
+ this.derivedMetricProjection.clearProjectionMaps();
352
+ this.seenMetricIds.clear();
353
+ // Capture and clear the reference before awaiting shutdown so any
354
+ // re-entrant calls triggered by the shutdown's final force-flush
355
+ // export observe meterProvider as undefined and exit early.
356
+ const provider = this.meterProvider;
357
+ this.meterProvider = undefined;
358
+ await provider?.shutdown();
359
+ }
360
+ finally {
361
+ this.isDeactivating = false;
362
+ this.deactivatingPromise = undefined;
363
+ }
364
+ })();
365
+ return this.deactivatingPromise;
311
366
  }
312
367
  /**
313
368
  * Force flush Meter Provider.