@azure/monitor-opentelemetry-exporter 1.0.0-beta.7 → 1.0.0-beta.9

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 (42) hide show
  1. package/README.md +47 -9
  2. package/dist/index.js +656 -261
  3. package/dist-esm/src/config.js +1 -14
  4. package/dist-esm/src/config.js.map +1 -1
  5. package/dist-esm/src/export/base.js +174 -0
  6. package/dist-esm/src/export/base.js.map +1 -0
  7. package/dist-esm/src/export/metric.js +64 -0
  8. package/dist-esm/src/export/metric.js.map +1 -0
  9. package/dist-esm/src/export/trace.js +25 -146
  10. package/dist-esm/src/export/trace.js.map +1 -1
  11. package/dist-esm/src/generated/applicationInsightsClient.js +36 -3
  12. package/dist-esm/src/generated/applicationInsightsClient.js.map +1 -1
  13. package/dist-esm/src/generated/index.js +0 -1
  14. package/dist-esm/src/generated/index.js.map +1 -1
  15. package/dist-esm/src/generated/models/index.js +35 -0
  16. package/dist-esm/src/generated/models/index.js.map +1 -1
  17. package/dist-esm/src/index.js +3 -0
  18. package/dist-esm/src/index.js.map +1 -1
  19. package/dist-esm/src/platform/nodejs/httpSender.js +5 -8
  20. package/dist-esm/src/platform/nodejs/httpSender.js.map +1 -1
  21. package/dist-esm/src/platform/nodejs/persist/fileAccessControl.js.map +1 -1
  22. package/dist-esm/src/platform/nodejs/persist/fileSystemHelpers.js +2 -1
  23. package/dist-esm/src/platform/nodejs/persist/fileSystemHelpers.js.map +1 -1
  24. package/dist-esm/src/platform/nodejs/persist/fileSystemPersist.js +10 -5
  25. package/dist-esm/src/platform/nodejs/persist/fileSystemPersist.js.map +1 -1
  26. package/dist-esm/src/sampling.js +81 -0
  27. package/dist-esm/src/sampling.js.map +1 -0
  28. package/dist-esm/src/utils/breezeUtils.js +3 -1
  29. package/dist-esm/src/utils/breezeUtils.js.map +1 -1
  30. package/dist-esm/src/utils/constants/applicationinsights.js +2 -1
  31. package/dist-esm/src/utils/constants/applicationinsights.js.map +1 -1
  32. package/dist-esm/src/utils/metricUtils.js +67 -0
  33. package/dist-esm/src/utils/metricUtils.js.map +1 -0
  34. package/dist-esm/src/utils/resourceUtils.js +35 -0
  35. package/dist-esm/src/utils/resourceUtils.js.map +1 -0
  36. package/dist-esm/src/utils/spanUtils.js +123 -44
  37. package/dist-esm/src/utils/spanUtils.js.map +1 -1
  38. package/package.json +20 -19
  39. package/types/monitor-opentelemetry-exporter.d.ts +181 -13
  40. package/CHANGELOG.md +0 -51
  41. package/dist-esm/src/generated/applicationInsightsClientContext.js +0 -34
  42. package/dist-esm/src/generated/applicationInsightsClientContext.js.map +0 -1
package/dist/index.js CHANGED
@@ -2,17 +2,19 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
5
6
  var api = require('@opentelemetry/api');
6
7
  var core = require('@opentelemetry/core');
7
- var os = require('os');
8
8
  var url = require('url');
9
- var semanticConventions = require('@opentelemetry/semantic-conventions');
10
9
  var coreRestPipeline = require('@azure/core-rest-pipeline');
11
10
  var coreClient = require('@azure/core-client');
12
11
  var fs = require('fs');
12
+ var os = require('os');
13
13
  var path = require('path');
14
14
  var child_process = require('child_process');
15
15
  var util = require('util');
16
+ var semanticConventions = require('@opentelemetry/semantic-conventions');
17
+ var sdkMetrics = require('@opentelemetry/sdk-metrics');
16
18
 
17
19
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
18
20
 
@@ -34,14 +36,126 @@ function _interopNamespace(e) {
34
36
  return Object.freeze(n);
35
37
  }
36
38
 
37
- var os__namespace = /*#__PURE__*/_interopNamespace(os);
38
- var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
39
39
  var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
40
+ var coreRestPipeline__namespace = /*#__PURE__*/_interopNamespace(coreRestPipeline);
40
41
  var coreClient__namespace = /*#__PURE__*/_interopNamespace(coreClient);
41
42
  var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
43
+ var os__namespace = /*#__PURE__*/_interopNamespace(os);
44
+ var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
42
45
  var path__namespace = /*#__PURE__*/_interopNamespace(path);
43
46
  var child_process__namespace = /*#__PURE__*/_interopNamespace(child_process);
44
47
 
48
+ // Copyright (c) Microsoft Corporation.
49
+ // Licensed under the MIT license.
50
+ /**
51
+ * AI MS Links.
52
+ * @internal
53
+ */
54
+ const MS_LINKS = "_MS.links";
55
+ /**
56
+ * AI enqueued time attribute.
57
+ * @internal
58
+ */
59
+ const ENQUEUED_TIME = "enqueuedTime";
60
+ /**
61
+ * AI time since enqueued attribute.
62
+ * @internal
63
+ */
64
+ const TIME_SINCE_ENQUEUED = "timeSinceEnqueued";
65
+ /**
66
+ * AzureMonitorTraceExporter version.
67
+ * @internal
68
+ */
69
+ const packageVersion = "1.0.0-beta.9";
70
+ var DependencyTypes;
71
+ (function (DependencyTypes) {
72
+ DependencyTypes["InProc"] = "InProc";
73
+ DependencyTypes["QueueMessage"] = "Queue Message";
74
+ DependencyTypes["Sql"] = "SQL";
75
+ DependencyTypes["Http"] = "Http";
76
+ DependencyTypes["Grpc"] = "GRPC";
77
+ })(DependencyTypes || (DependencyTypes = {}));
78
+ const AzureMonitorSampleRate = "_MS.sampleRate";
79
+
80
+ /**
81
+ * ApplicationInsightsSampler is responsible for the following:
82
+ * Implements same trace id hashing algorithm so that traces are sampled the same across multiple nodes
83
+ * Adds item count to span attribute if span is sampled (needed for ingestion service)
84
+ * @param samplingRatio - 0 to 1 value.
85
+ */
86
+ class ApplicationInsightsSampler {
87
+ constructor(samplingRatio = 1) {
88
+ this._samplingRatio = samplingRatio;
89
+ if (this._samplingRatio > 1) {
90
+ throw new Error("Wrong sampling rate, data will not be sampled out");
91
+ }
92
+ this._sampleRate = Math.round(this._samplingRatio * 100);
93
+ }
94
+ /**
95
+ * Checks whether span needs to be created and tracked.
96
+ *
97
+ * @param context Parent Context which may contain a span.
98
+ * @param traceId of the span to be created. It can be different from the
99
+ * traceId in the {@link SpanContext}. Typically in situations when the
100
+ * span to be created starts a new trace.
101
+ * @param spanName of the span to be created.
102
+ * @param spanKind of the span to be created.
103
+ * @param attributes Initial set of SpanAttributes for the Span being constructed.
104
+ * @param links Collection of links that will be associated with the Span to
105
+ * be created. Typically useful for batch operations.
106
+ * @returns a {@link SamplingResult}.
107
+ */
108
+ shouldSample(
109
+ // @ts-ignore
110
+ context, traceId,
111
+ // @ts-ignore
112
+ spanName,
113
+ // @ts-ignore
114
+ spanKind, attributes,
115
+ // @ts-ignore
116
+ links) {
117
+ let isSampledIn = false;
118
+ if (this._sampleRate == 100) {
119
+ isSampledIn = true;
120
+ }
121
+ else if (this._sampleRate == 0) {
122
+ isSampledIn = false;
123
+ }
124
+ else {
125
+ isSampledIn = this._getSamplingHashCode(traceId) < this._sampleRate;
126
+ }
127
+ // Add sample rate as span attribute
128
+ attributes = attributes || {};
129
+ attributes[AzureMonitorSampleRate] = this._sampleRate;
130
+ return isSampledIn
131
+ ? { decision: sdkTraceBase.SamplingDecision.RECORD_AND_SAMPLED, attributes: attributes }
132
+ : { decision: sdkTraceBase.SamplingDecision.NOT_RECORD, attributes: attributes };
133
+ }
134
+ /**
135
+ * Return Sampler description
136
+ */
137
+ toString() {
138
+ return `ApplicationInsightsSampler{${this._samplingRatio}}`;
139
+ }
140
+ _getSamplingHashCode(input) {
141
+ var csharpMin = -2147483648;
142
+ var csharpMax = 2147483647;
143
+ var hash = 5381;
144
+ if (!input) {
145
+ return 0;
146
+ }
147
+ while (input.length < 8) {
148
+ input = input + input;
149
+ }
150
+ for (var i = 0; i < input.length; i++) {
151
+ // JS doesn't respond to integer overflow by wrapping around. Simulate it with bitwise operators ( | 0)
152
+ hash = ((((hash << 5) + hash) | 0) + input.charCodeAt(i)) | 0;
153
+ }
154
+ hash = hash <= csharpMin ? csharpMax : Math.abs(hash);
155
+ return (hash / csharpMax) * 100;
156
+ }
157
+ }
158
+
45
159
  // Copyright (c) Microsoft Corporation.
46
160
  // Licensed under the MIT license.
47
161
  /**
@@ -63,7 +177,7 @@ const DEFAULT_BREEZE_ENDPOINT = "https://dc.services.visualstudio.com";
63
177
  * Default Breeze API version.
64
178
  * @internal
65
179
  */
66
- const DEFAULT_BREEZE_API_VERSION = exports.ServiceApiVersion.V2;
180
+ exports.ServiceApiVersion.V2;
67
181
  /**
68
182
  * Default Live Metrics endpoint.
69
183
  * @internal
@@ -193,20 +307,6 @@ class ConnectionStringParser {
193
307
  ConnectionStringParser.FIELDS_SEPARATOR = ";";
194
308
  ConnectionStringParser.FIELD_KEY_VALUE_SEPARATOR = "=";
195
309
 
196
- const DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60000;
197
- const DEFAULT_MAX_CONSECUTIVE_FAILURES_BEFORE_WARNING = 10;
198
- /**
199
- * Internal default Azure exporter configuration
200
- * @internal
201
- */
202
- const DEFAULT_EXPORTER_CONFIG = {
203
- instrumentationKey: "",
204
- endpointUrl: DEFAULT_BREEZE_ENDPOINT,
205
- batchSendRetryIntervalMs: DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS,
206
- maxConsecutiveFailuresBeforeWarning: DEFAULT_MAX_CONSECUTIVE_FAILURES_BEFORE_WARNING,
207
- apiVersion: DEFAULT_BREEZE_API_VERSION,
208
- };
209
-
210
310
  // Copyright (c) Microsoft Corporation.
211
311
  class FileAccessControl {
212
312
  // Check if file access control could be enabled
@@ -409,7 +509,8 @@ const confirmDirExists = async (directory) => {
409
509
  catch (err) {
410
510
  if (err && err.code === "ENOENT") {
411
511
  try {
412
- await mkdirAsync(directory);
512
+ const options = { recursive: true };
513
+ await mkdirAsync(directory, options);
413
514
  }
414
515
  catch (mkdirErr) {
415
516
  if (mkdirErr && mkdirErr.code !== "EEXIST") {
@@ -432,25 +533,31 @@ const writeFileAsync = util.promisify(fs__namespace.writeFile);
432
533
  * @internal
433
534
  */
434
535
  class FileSystemPersist {
435
- constructor(options = {}) {
536
+ constructor(instrumentationKey, _options) {
537
+ var _a, _b;
538
+ this._options = _options;
436
539
  this.fileRetemptionPeriod = 7 * 24 * 60 * 60 * 1000; // 7 days
437
540
  this.cleanupTimeOut = 60 * 60 * 1000; // 1 hour
438
541
  this.maxBytesOnDisk = 50000000; // ~50MB
439
542
  this._tempDirectory = "";
440
543
  this._fileCleanupTimer = null;
441
- this._options = Object.assign(Object.assign({}, DEFAULT_EXPORTER_CONFIG), options);
544
+ this._instrumentationKey = instrumentationKey;
545
+ if ((_a = this._options) === null || _a === void 0 ? void 0 : _a.disableOfflineStorage) {
546
+ this._enabled = false;
547
+ return;
548
+ }
442
549
  this._enabled = true;
443
550
  FileAccessControl.checkFileProtection();
444
551
  if (!FileAccessControl.OS_PROVIDES_FILE_PROTECTION) {
445
552
  this._enabled = false;
446
553
  api.diag.error("Sufficient file protection capabilities were not detected. Files will not be persisted");
447
554
  }
448
- if (!this._options.instrumentationKey) {
555
+ if (!this._instrumentationKey) {
449
556
  this._enabled = false;
450
557
  api.diag.error(`No instrumentation key was provided to FileSystemPersister. Files will not be persisted`);
451
558
  }
452
559
  if (this._enabled) {
453
- this._tempDirectory = path__namespace.join(os__namespace.tmpdir(), FileSystemPersist.TEMPDIR_PREFIX + this._options.instrumentationKey);
560
+ this._tempDirectory = path__namespace.join(((_b = this._options) === null || _b === void 0 ? void 0 : _b.storageDirectory) || os__namespace.tmpdir(), "Microsoft", "AzureMonitor", FileSystemPersist.TEMPDIR_PREFIX + this._instrumentationKey);
454
561
  // Starts file cleanup task
455
562
  if (!this._fileCleanupTimer) {
456
563
  this._fileCleanupTimer = setTimeout(() => {
@@ -596,48 +703,83 @@ FileSystemPersist.FILENAME_SUFFIX = ".ai.json";
596
703
  /** Known values of {@link DataPointType} that the service accepts. */
597
704
  var KnownDataPointType;
598
705
  (function (KnownDataPointType) {
706
+ /** Measurement */
599
707
  KnownDataPointType["Measurement"] = "Measurement";
708
+ /** Aggregation */
600
709
  KnownDataPointType["Aggregation"] = "Aggregation";
601
710
  })(KnownDataPointType || (KnownDataPointType = {}));
602
711
  /** Known values of {@link SeverityLevel} that the service accepts. */
603
712
  var KnownSeverityLevel;
604
713
  (function (KnownSeverityLevel) {
714
+ /** Verbose */
605
715
  KnownSeverityLevel["Verbose"] = "Verbose";
716
+ /** Information */
606
717
  KnownSeverityLevel["Information"] = "Information";
718
+ /** Warning */
607
719
  KnownSeverityLevel["Warning"] = "Warning";
720
+ /** Error */
608
721
  KnownSeverityLevel["Error"] = "Error";
722
+ /** Critical */
609
723
  KnownSeverityLevel["Critical"] = "Critical";
610
724
  })(KnownSeverityLevel || (KnownSeverityLevel = {}));
611
725
  /** Known values of {@link ContextTagKeys} that the service accepts. */
612
726
  var KnownContextTagKeys;
613
727
  (function (KnownContextTagKeys) {
728
+ /** AiApplicationVer */
614
729
  KnownContextTagKeys["AiApplicationVer"] = "ai.application.ver";
730
+ /** AiDeviceId */
615
731
  KnownContextTagKeys["AiDeviceId"] = "ai.device.id";
732
+ /** AiDeviceLocale */
616
733
  KnownContextTagKeys["AiDeviceLocale"] = "ai.device.locale";
734
+ /** AiDeviceModel */
617
735
  KnownContextTagKeys["AiDeviceModel"] = "ai.device.model";
736
+ /** AiDeviceOemName */
618
737
  KnownContextTagKeys["AiDeviceOemName"] = "ai.device.oemName";
738
+ /** AiDeviceOsVersion */
619
739
  KnownContextTagKeys["AiDeviceOsVersion"] = "ai.device.osVersion";
740
+ /** AiDeviceType */
620
741
  KnownContextTagKeys["AiDeviceType"] = "ai.device.type";
742
+ /** AiLocationIp */
621
743
  KnownContextTagKeys["AiLocationIp"] = "ai.location.ip";
744
+ /** AiLocationCountry */
622
745
  KnownContextTagKeys["AiLocationCountry"] = "ai.location.country";
746
+ /** AiLocationProvince */
623
747
  KnownContextTagKeys["AiLocationProvince"] = "ai.location.province";
748
+ /** AiLocationCity */
624
749
  KnownContextTagKeys["AiLocationCity"] = "ai.location.city";
750
+ /** AiOperationId */
625
751
  KnownContextTagKeys["AiOperationId"] = "ai.operation.id";
752
+ /** AiOperationName */
626
753
  KnownContextTagKeys["AiOperationName"] = "ai.operation.name";
754
+ /** AiOperationParentId */
627
755
  KnownContextTagKeys["AiOperationParentId"] = "ai.operation.parentId";
756
+ /** AiOperationSyntheticSource */
628
757
  KnownContextTagKeys["AiOperationSyntheticSource"] = "ai.operation.syntheticSource";
758
+ /** AiOperationCorrelationVector */
629
759
  KnownContextTagKeys["AiOperationCorrelationVector"] = "ai.operation.correlationVector";
760
+ /** AiSessionId */
630
761
  KnownContextTagKeys["AiSessionId"] = "ai.session.id";
762
+ /** AiSessionIsFirst */
631
763
  KnownContextTagKeys["AiSessionIsFirst"] = "ai.session.isFirst";
764
+ /** AiUserAccountId */
632
765
  KnownContextTagKeys["AiUserAccountId"] = "ai.user.accountId";
766
+ /** AiUserId */
633
767
  KnownContextTagKeys["AiUserId"] = "ai.user.id";
768
+ /** AiUserAuthUserId */
634
769
  KnownContextTagKeys["AiUserAuthUserId"] = "ai.user.authUserId";
770
+ /** AiCloudRole */
635
771
  KnownContextTagKeys["AiCloudRole"] = "ai.cloud.role";
772
+ /** AiCloudRoleVer */
636
773
  KnownContextTagKeys["AiCloudRoleVer"] = "ai.cloud.roleVer";
774
+ /** AiCloudRoleInstance */
637
775
  KnownContextTagKeys["AiCloudRoleInstance"] = "ai.cloud.roleInstance";
776
+ /** AiCloudLocation */
638
777
  KnownContextTagKeys["AiCloudLocation"] = "ai.cloud.location";
778
+ /** AiInternalSdkVersion */
639
779
  KnownContextTagKeys["AiInternalSdkVersion"] = "ai.internal.sdkVersion";
780
+ /** AiInternalAgentVersion */
640
781
  KnownContextTagKeys["AiInternalAgentVersion"] = "ai.internal.agentVersion";
782
+ /** AiInternalNodeName */
641
783
  KnownContextTagKeys["AiInternalNodeName"] = "ai.internal.nodeName";
642
784
  })(KnownContextTagKeys || (KnownContextTagKeys = {}));
643
785
 
@@ -1571,12 +1713,13 @@ var Mappers = /*#__PURE__*/Object.freeze({
1571
1713
  * Code generated by Microsoft (R) AutoRest Code Generator.
1572
1714
  * Changes may cause incorrect behavior and will be lost if the code is regenerated.
1573
1715
  */
1574
- class ApplicationInsightsClientContext extends coreClient__namespace.ServiceClient {
1716
+ class ApplicationInsightsClient extends coreClient__namespace.ServiceClient {
1575
1717
  /**
1576
- * Initializes a new instance of the ApplicationInsightsClientContext class.
1718
+ * Initializes a new instance of the ApplicationInsightsClient class.
1577
1719
  * @param options The parameter options
1578
1720
  */
1579
1721
  constructor(options) {
1722
+ var _a, _b;
1580
1723
  // Initializing default values for options
1581
1724
  if (!options) {
1582
1725
  options = {};
@@ -1584,34 +1727,33 @@ class ApplicationInsightsClientContext extends coreClient__namespace.ServiceClie
1584
1727
  const defaults = {
1585
1728
  requestContentType: "application/json; charset=utf-8"
1586
1729
  };
1587
- const packageDetails = `azsdk-js-monitor-opentelemetry-exporter/1.0.0-beta.7`;
1730
+ const packageDetails = `azsdk-js-monitor-opentelemetry-exporter/1.0.0-beta.9`;
1588
1731
  const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix
1589
1732
  ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`
1590
1733
  : `${packageDetails}`;
1591
1734
  const optionsWithDefaults = Object.assign(Object.assign(Object.assign({}, defaults), options), { userAgentOptions: {
1592
1735
  userAgentPrefix
1593
- }, baseUri: options.endpoint || "{Host}/v2.1" });
1736
+ }, baseUri: (_b = (_a = options.endpoint) !== null && _a !== void 0 ? _a : options.baseUri) !== null && _b !== void 0 ? _b : "{Host}/v2.1" });
1594
1737
  super(optionsWithDefaults);
1738
+ if ((options === null || options === void 0 ? void 0 : options.pipeline) && options.pipeline.getOrderedPolicies().length > 0) {
1739
+ const pipelinePolicies = options.pipeline.getOrderedPolicies();
1740
+ const bearerTokenAuthenticationPolicyFound = pipelinePolicies.some((pipelinePolicy) => pipelinePolicy.name ===
1741
+ coreRestPipeline__namespace.bearerTokenAuthenticationPolicyName);
1742
+ if (!bearerTokenAuthenticationPolicyFound) {
1743
+ this.pipeline.removePolicy({
1744
+ name: coreRestPipeline__namespace.bearerTokenAuthenticationPolicyName
1745
+ });
1746
+ this.pipeline.addPolicy(coreRestPipeline__namespace.bearerTokenAuthenticationPolicy({
1747
+ scopes: `${optionsWithDefaults.baseUri}/.default`,
1748
+ challengeCallbacks: {
1749
+ authorizeRequestOnChallenge: coreClient__namespace.authorizeRequestOnClaimChallenge
1750
+ }
1751
+ }));
1752
+ }
1753
+ }
1595
1754
  // Assigning values to Constant parameters
1596
1755
  this.host = options.host || "https://dc.services.visualstudio.com";
1597
1756
  }
1598
- }
1599
-
1600
- /*
1601
- * Copyright (c) Microsoft Corporation.
1602
- * Licensed under the MIT License.
1603
- *
1604
- * Code generated by Microsoft (R) AutoRest Code Generator.
1605
- * Changes may cause incorrect behavior and will be lost if the code is regenerated.
1606
- */
1607
- class ApplicationInsightsClient extends ApplicationInsightsClientContext {
1608
- /**
1609
- * Initializes a new instance of the ApplicationInsightsClient class.
1610
- * @param options The parameter options
1611
- */
1612
- constructor(options) {
1613
- super(options);
1614
- }
1615
1757
  /**
1616
1758
  * This operation sends a sequence of telemetry events that will be monitored by Azure Monitor.
1617
1759
  * @param body The list of telemetry events to track.
@@ -1668,19 +1810,16 @@ const applicationInsightsResource = "https://monitor.azure.com//.default";
1668
1810
  * @internal
1669
1811
  */
1670
1812
  class HttpSender {
1671
- constructor(_exporterOptions) {
1672
- this._exporterOptions = _exporterOptions;
1813
+ constructor(endpointUrl, options) {
1673
1814
  // Build endpoint using provided configuration or default values
1674
- this._appInsightsClientOptions = {
1675
- host: this._exporterOptions.endpointUrl,
1676
- };
1677
- this._appInsightsClient = new ApplicationInsightsClient(Object.assign({}, this._appInsightsClientOptions));
1815
+ this._appInsightsClientOptions = Object.assign({ host: endpointUrl }, options);
1816
+ this._appInsightsClient = new ApplicationInsightsClient(this._appInsightsClientOptions);
1678
1817
  // Handle redirects in HTTP Sender
1679
1818
  this._appInsightsClient.pipeline.removePolicy({ name: coreRestPipeline.redirectPolicyName });
1680
- if (this._exporterOptions.aadTokenCredential) {
1819
+ if (options === null || options === void 0 ? void 0 : options.aadTokenCredential) {
1681
1820
  let scopes = [applicationInsightsResource];
1682
1821
  this._appInsightsClient.pipeline.addPolicy(coreRestPipeline.bearerTokenAuthenticationPolicy({
1683
- credential: this._exporterOptions.aadTokenCredential,
1822
+ credential: options === null || options === void 0 ? void 0 : options.aadTokenCredential,
1684
1823
  scopes: scopes,
1685
1824
  }));
1686
1825
  }
@@ -1724,37 +1863,6 @@ class HttpSender {
1724
1863
  }
1725
1864
  }
1726
1865
 
1727
- // Copyright (c) Microsoft Corporation.
1728
- // Licensed under the MIT license.
1729
- /**
1730
- * AI MS Links.
1731
- * @internal
1732
- */
1733
- const MS_LINKS = "_MS.links";
1734
- /**
1735
- * AI enqueued time attribute.
1736
- * @internal
1737
- */
1738
- const ENQUEUED_TIME = "enqueuedTime";
1739
- /**
1740
- * AI time since enqueued attribute.
1741
- * @internal
1742
- */
1743
- const TIME_SINCE_ENQUEUED = "timeSinceEnqueued";
1744
- /**
1745
- * AzureMonitorTraceExporter version.
1746
- * @internal
1747
- */
1748
- const packageVersion = "1.0.0-beta.7";
1749
- var DependencyTypes;
1750
- (function (DependencyTypes) {
1751
- DependencyTypes["InProc"] = "InProc";
1752
- DependencyTypes["QueueMessage"] = "Queue Message";
1753
- DependencyTypes["Sql"] = "SQL";
1754
- DependencyTypes["Http"] = "Http";
1755
- DependencyTypes["Grpc"] = "GRPC";
1756
- })(DependencyTypes || (DependencyTypes = {}));
1757
-
1758
1866
  // Copyright (c) Microsoft Corporation.
1759
1867
  let instance = null;
1760
1868
  /**
@@ -1805,7 +1913,9 @@ function isRetriable(statusCode) {
1805
1913
  statusCode === 408 || // Timeout
1806
1914
  statusCode === 429 || // Too many requests
1807
1915
  statusCode === 500 || // Server Error
1808
- statusCode === 503 // Server Unavailable
1916
+ statusCode === 502 || // Bad Gateway
1917
+ statusCode === 503 || // Server Unavailable
1918
+ statusCode === 504 // Gateway Timeout
1809
1919
  );
1810
1920
  }
1811
1921
  /**
@@ -1828,6 +1938,203 @@ function msToTimeSpan(ms) {
1828
1938
  return `${daysText + hour}:${min}:${sec}`;
1829
1939
  }
1830
1940
 
1941
+ // Copyright (c) Microsoft Corporation.
1942
+ const DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60000;
1943
+ /**
1944
+ * Azure Monitor OpenTelemetry Trace Exporter.
1945
+ */
1946
+ class AzureMonitorBaseExporter {
1947
+ /**
1948
+ * Initializes a new instance of the AzureMonitorBaseExporter class.
1949
+ * @param AzureMonitorExporterOptions - Exporter configuration.
1950
+ */
1951
+ constructor(options = {}) {
1952
+ var _a;
1953
+ this._batchSendRetryIntervalMs = DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS;
1954
+ this._options = options;
1955
+ this._numConsecutiveRedirects = 0;
1956
+ this._instrumentationKey = "";
1957
+ this._endpointUrl = DEFAULT_BREEZE_ENDPOINT;
1958
+ const connectionString = this._options.connectionString || process.env[ENV_CONNECTION_STRING];
1959
+ if (connectionString) {
1960
+ const parsedConnectionString = ConnectionStringParser.parse(connectionString);
1961
+ this._instrumentationKey =
1962
+ parsedConnectionString.instrumentationkey || this._instrumentationKey;
1963
+ this._endpointUrl = ((_a = parsedConnectionString.ingestionendpoint) === null || _a === void 0 ? void 0 : _a.trim()) || this._endpointUrl;
1964
+ }
1965
+ // Instrumentation key is required
1966
+ if (!this._instrumentationKey) {
1967
+ const message = "No instrumentation key or connection string was provided to the Azure Monitor Exporter";
1968
+ api.diag.error(message);
1969
+ throw new Error(message);
1970
+ }
1971
+ this._sender = new HttpSender(this._endpointUrl, this._options);
1972
+ this._persister = new FileSystemPersist(this._instrumentationKey, this._options);
1973
+ this._retryTimer = null;
1974
+ api.diag.debug("AzureMonitorExporter was successfully setup");
1975
+ }
1976
+ /**
1977
+ * Persist envelopes to disk
1978
+ */
1979
+ async _persist(envelopes) {
1980
+ try {
1981
+ const success = await this._persister.push(envelopes);
1982
+ return success
1983
+ ? { code: core.ExportResultCode.SUCCESS }
1984
+ : {
1985
+ code: core.ExportResultCode.FAILED,
1986
+ error: new Error("Failed to persist envelope in disk."),
1987
+ };
1988
+ }
1989
+ catch (ex) {
1990
+ return { code: core.ExportResultCode.FAILED, error: ex };
1991
+ }
1992
+ }
1993
+ /**
1994
+ * Shutdown exporter
1995
+ */
1996
+ async _shutdown() {
1997
+ return this._sender.shutdown();
1998
+ }
1999
+ /**
2000
+ * Export envelopes
2001
+ */
2002
+ async _exportEnvelopes(envelopes) {
2003
+ api.diag.info(`Exporting ${envelopes.length} envelope(s)`);
2004
+ if (envelopes.length < 1) {
2005
+ return { code: core.ExportResultCode.SUCCESS };
2006
+ }
2007
+ try {
2008
+ const { result, statusCode } = await this._sender.send(envelopes);
2009
+ this._numConsecutiveRedirects = 0;
2010
+ if (statusCode === 200) {
2011
+ // Success -- @todo: start retry timer
2012
+ if (!this._retryTimer) {
2013
+ this._retryTimer = setTimeout(() => {
2014
+ this._retryTimer = null;
2015
+ this._sendFirstPersistedFile();
2016
+ }, this._batchSendRetryIntervalMs);
2017
+ this._retryTimer.unref();
2018
+ }
2019
+ return { code: core.ExportResultCode.SUCCESS };
2020
+ }
2021
+ else if (statusCode && isRetriable(statusCode)) {
2022
+ // Failed -- persist failed data
2023
+ if (result) {
2024
+ api.diag.info(result);
2025
+ const breezeResponse = JSON.parse(result);
2026
+ const filteredEnvelopes = [];
2027
+ if (breezeResponse.errors) {
2028
+ breezeResponse.errors.forEach((error) => {
2029
+ if (error.statusCode && isRetriable(error.statusCode)) {
2030
+ filteredEnvelopes.push(envelopes[error.index]);
2031
+ }
2032
+ });
2033
+ }
2034
+ if (filteredEnvelopes.length > 0) {
2035
+ // calls resultCallback(ExportResult) based on result of persister.push
2036
+ return await this._persist(filteredEnvelopes);
2037
+ }
2038
+ // Failed -- not retriable
2039
+ return {
2040
+ code: core.ExportResultCode.FAILED,
2041
+ };
2042
+ }
2043
+ else {
2044
+ // calls resultCallback(ExportResult) based on result of persister.push
2045
+ return await this._persist(envelopes);
2046
+ }
2047
+ }
2048
+ else {
2049
+ // Failed -- not retriable
2050
+ return {
2051
+ code: core.ExportResultCode.FAILED,
2052
+ };
2053
+ }
2054
+ }
2055
+ catch (error) {
2056
+ const restError = error;
2057
+ if (restError.statusCode &&
2058
+ (restError.statusCode === 307 || // Temporary redirect
2059
+ restError.statusCode === 308)) {
2060
+ // Permanent redirect
2061
+ this._numConsecutiveRedirects++;
2062
+ // To prevent circular redirects
2063
+ if (this._numConsecutiveRedirects < 10) {
2064
+ if (restError.response && restError.response.headers) {
2065
+ const location = restError.response.headers.get("location");
2066
+ if (location) {
2067
+ // Update sender URL
2068
+ this._sender.handlePermanentRedirect(location);
2069
+ // Send to redirect endpoint as HTTPs library doesn't handle redirect automatically
2070
+ return this._exportEnvelopes(envelopes);
2071
+ }
2072
+ }
2073
+ }
2074
+ else {
2075
+ return { code: core.ExportResultCode.FAILED, error: new Error("Circular redirect") };
2076
+ }
2077
+ }
2078
+ else if (restError.statusCode && isRetriable(restError.statusCode)) {
2079
+ return await this._persist(envelopes);
2080
+ }
2081
+ if (this._isNetworkError(restError)) {
2082
+ api.diag.error("Retrying due to transient client side error. Error message:", restError.message);
2083
+ return await this._persist(envelopes);
2084
+ }
2085
+ api.diag.error("Envelopes could not be exported and are not retriable. Error message:", restError.message);
2086
+ return { code: core.ExportResultCode.FAILED, error: restError };
2087
+ }
2088
+ }
2089
+ async _sendFirstPersistedFile() {
2090
+ try {
2091
+ const envelopes = (await this._persister.shift());
2092
+ if (envelopes) {
2093
+ await this._sender.send(envelopes);
2094
+ }
2095
+ }
2096
+ catch (err) {
2097
+ api.diag.warn(`Failed to fetch persisted file`, err);
2098
+ }
2099
+ }
2100
+ _isNetworkError(error) {
2101
+ if (error && error.code && error.code === "REQUEST_SEND_ERROR") {
2102
+ return true;
2103
+ }
2104
+ return false;
2105
+ }
2106
+ }
2107
+
2108
+ // Copyright (c) Microsoft Corporation.
2109
+ function createTagsFromResource(resource) {
2110
+ const context = getInstance();
2111
+ const tags = Object.assign({}, context.tags);
2112
+ if (resource && resource.attributes) {
2113
+ const serviceName = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAME];
2114
+ const serviceNamespace = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAMESPACE];
2115
+ if (serviceName) {
2116
+ if (serviceNamespace) {
2117
+ tags[KnownContextTagKeys.AiCloudRole] = `${serviceNamespace}.${serviceName}`;
2118
+ }
2119
+ else {
2120
+ tags[KnownContextTagKeys.AiCloudRole] = String(serviceName);
2121
+ }
2122
+ }
2123
+ const serviceInstanceId = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_INSTANCE_ID];
2124
+ if (serviceInstanceId) {
2125
+ tags[KnownContextTagKeys.AiCloudRoleInstance] = String(serviceInstanceId);
2126
+ }
2127
+ else {
2128
+ tags[KnownContextTagKeys.AiCloudRoleInstance] = os__default["default"] && os__default["default"].hostname();
2129
+ }
2130
+ const endUserId = resource.attributes[semanticConventions.SemanticAttributes.ENDUSER_ID];
2131
+ if (endUserId) {
2132
+ tags[KnownContextTagKeys.AiUserId] = String(endUserId);
2133
+ }
2134
+ }
2135
+ return tags;
2136
+ }
2137
+
1831
2138
  // Copyright (c) Microsoft Corporation.
1832
2139
  // Licensed under the MIT license.
1833
2140
  /**
@@ -1894,34 +2201,15 @@ const parseEventHubSpan = (span, baseData) => {
1894
2201
 
1895
2202
  // Copyright (c) Microsoft Corporation.
1896
2203
  function createTagsFromSpan(span) {
1897
- const context = getInstance();
1898
- const tags = Object.assign({}, context.tags);
2204
+ const tags = createTagsFromResource(span.resource);
1899
2205
  tags[KnownContextTagKeys.AiOperationId] = span.spanContext().traceId;
1900
2206
  if (span.parentSpanId) {
1901
2207
  tags[KnownContextTagKeys.AiOperationParentId] = span.parentSpanId;
1902
2208
  }
1903
- if (span.resource && span.resource.attributes) {
1904
- const serviceName = span.resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAME];
1905
- const serviceNamespace = span.resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAMESPACE];
1906
- if (serviceName) {
1907
- if (serviceNamespace) {
1908
- tags[KnownContextTagKeys.AiCloudRole] = `${serviceNamespace}.${serviceName}`;
1909
- }
1910
- else {
1911
- tags[KnownContextTagKeys.AiCloudRole] = String(serviceName);
1912
- }
1913
- }
1914
- const serviceInstanceId = span.resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_INSTANCE_ID];
1915
- if (serviceInstanceId) {
1916
- tags[KnownContextTagKeys.AiCloudRoleInstance] = String(serviceInstanceId);
1917
- }
1918
- else {
1919
- tags[KnownContextTagKeys.AiCloudRoleInstance] = os__default["default"] && os__default["default"].hostname();
1920
- }
1921
- const endUserId = span.resource.attributes[semanticConventions.SemanticAttributes.ENDUSER_ID];
1922
- if (endUserId) {
1923
- tags[KnownContextTagKeys.AiUserId] = String(endUserId);
1924
- }
2209
+ const httpUserAgent = span.attributes[semanticConventions.SemanticAttributes.HTTP_USER_AGENT];
2210
+ if (httpUserAgent) {
2211
+ // TODO: Not exposed in Swagger, need to update def
2212
+ tags["ai.user.userAgent"] = String(httpUserAgent);
1925
2213
  }
1926
2214
  if (span.kind === api.SpanKind.SERVER) {
1927
2215
  const httpMethod = span.attributes[semanticConventions.SemanticAttributes.HTTP_METHOD];
@@ -1956,25 +2244,34 @@ function createTagsFromSpan(span) {
1956
2244
  }
1957
2245
  }
1958
2246
  // TODO: Operation Name and Location IP TBD for non server spans
1959
- const httpUserAgent = span.attributes[semanticConventions.SemanticAttributes.HTTP_USER_AGENT];
1960
- if (httpUserAgent) {
1961
- // TODO: Not exposed in Swagger, need to update def
1962
- tags["ai.user.userAgent"] = String(httpUserAgent);
1963
- }
1964
2247
  return tags;
1965
2248
  }
1966
- function createPropertiesFromSpan(span) {
2249
+ function createPropertiesFromSpanAttributes(attributes) {
1967
2250
  const properties = {};
1968
- const measurements = {};
1969
- for (const key of Object.keys(span.attributes)) {
1970
- if (!(key.startsWith("http.") ||
1971
- key.startsWith("rpc.") ||
1972
- key.startsWith("db.") ||
1973
- key.startsWith("peer.") ||
1974
- key.startsWith("net."))) {
1975
- properties[key] = span.attributes[key];
2251
+ if (attributes) {
2252
+ for (const key of Object.keys(attributes)) {
2253
+ if (!(key.startsWith("http.") ||
2254
+ key.startsWith("rpc.") ||
2255
+ key.startsWith("db.") ||
2256
+ key.startsWith("peer.") ||
2257
+ key.startsWith("message.") ||
2258
+ key.startsWith("messaging.") ||
2259
+ key.startsWith("enduser.") ||
2260
+ key.startsWith("net.") ||
2261
+ key.startsWith("exception.") ||
2262
+ key.startsWith("thread.") ||
2263
+ key.startsWith("faas.") ||
2264
+ key.startsWith("code.") ||
2265
+ key.startsWith("_MS."))) {
2266
+ properties[key] = attributes[key];
2267
+ }
1976
2268
  }
1977
2269
  }
2270
+ return properties;
2271
+ }
2272
+ function createPropertiesFromSpan(span) {
2273
+ const properties = createPropertiesFromSpanAttributes(span.attributes);
2274
+ const measurements = {};
1978
2275
  const links = span.links.map((link) => ({
1979
2276
  operation_Id: link.context.traceId,
1980
2277
  id: link.context.spanId,
@@ -2103,7 +2400,7 @@ function createDependencyData(span) {
2103
2400
  }
2104
2401
  }
2105
2402
  }
2106
- catch (error) { }
2403
+ catch (ex) { }
2107
2404
  remoteDependencyData.target = `${target}`;
2108
2405
  }
2109
2406
  }
@@ -2192,7 +2489,6 @@ function createRequestData(span) {
2192
2489
  function readableSpanToEnvelope(span, ikey) {
2193
2490
  let name;
2194
2491
  let baseType;
2195
- const sampleRate = 100;
2196
2492
  let baseData;
2197
2493
  const time = new Date(core.hrTimeToMilliseconds(span.startTime));
2198
2494
  const instrumentationKey = ikey;
@@ -2218,6 +2514,10 @@ function readableSpanToEnvelope(span, ikey) {
2218
2514
  api.diag.error(`Unsupported span kind ${span.kind}`);
2219
2515
  throw new Error(`Unsupported span kind ${span.kind}`);
2220
2516
  }
2517
+ let sampleRate = 100;
2518
+ if (span.attributes[AzureMonitorSampleRate]) {
2519
+ sampleRate = Number(span.attributes[AzureMonitorSampleRate]);
2520
+ }
2221
2521
  // Azure SDK
2222
2522
  if (span.attributes[AzNamespace]) {
2223
2523
  if (span.kind === api.SpanKind.INTERNAL) {
@@ -2241,172 +2541,267 @@ function readableSpanToEnvelope(span, ikey) {
2241
2541
  },
2242
2542
  };
2243
2543
  }
2544
+ /**
2545
+ * Span Events to Azure envelopes parsing.
2546
+ * @internal
2547
+ */
2548
+ function spanEventsToEnvelopes(span, ikey) {
2549
+ let envelopes = [];
2550
+ if (span.events) {
2551
+ span.events.forEach((event) => {
2552
+ var _a;
2553
+ let baseType;
2554
+ let time = new Date(core.hrTimeToMilliseconds(event.time));
2555
+ let name = "";
2556
+ let baseData;
2557
+ const properties = createPropertiesFromSpanAttributes(event.attributes);
2558
+ let tags = createTagsFromResource(span.resource);
2559
+ tags[KnownContextTagKeys.AiOperationId] = span.spanContext().traceId;
2560
+ let spanId = (_a = span.spanContext()) === null || _a === void 0 ? void 0 : _a.spanId;
2561
+ if (spanId) {
2562
+ tags[KnownContextTagKeys.AiOperationParentId] = spanId;
2563
+ }
2564
+ // Only generate exception telemetry for incoming requests
2565
+ if (event.name == "exception" && span.kind == api.SpanKind.SERVER) {
2566
+ name = "Microsoft.ApplicationInsights.Exception";
2567
+ baseType = "ExceptionData";
2568
+ let typeName = "";
2569
+ let message = "Exception";
2570
+ let stack = "";
2571
+ let hasFullStack = false;
2572
+ if (event.attributes) {
2573
+ typeName = String(event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_TYPE]);
2574
+ stack = String(event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_STACKTRACE]);
2575
+ if (stack) {
2576
+ hasFullStack = true;
2577
+ }
2578
+ let exceptionMsg = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE];
2579
+ if (exceptionMsg) {
2580
+ message = String(exceptionMsg);
2581
+ }
2582
+ let escaped = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED];
2583
+ if (escaped != undefined) {
2584
+ properties[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED] = String(escaped);
2585
+ }
2586
+ }
2587
+ let exceptionDetails = {
2588
+ typeName: typeName,
2589
+ message: message,
2590
+ stack: stack,
2591
+ hasFullStack: hasFullStack,
2592
+ };
2593
+ let exceptionData = {
2594
+ exceptions: [exceptionDetails],
2595
+ version: 2,
2596
+ properties: properties,
2597
+ };
2598
+ baseData = exceptionData;
2599
+ }
2600
+ else {
2601
+ name = "Microsoft.ApplicationInsights.Message";
2602
+ baseType = "MessageData";
2603
+ let messageData = {
2604
+ message: event.name,
2605
+ version: 2,
2606
+ properties: properties,
2607
+ };
2608
+ baseData = messageData;
2609
+ }
2610
+ let sampleRate = 100;
2611
+ if (span.attributes[AzureMonitorSampleRate]) {
2612
+ sampleRate = Number(span.attributes[AzureMonitorSampleRate]);
2613
+ }
2614
+ let env = {
2615
+ name: name,
2616
+ time: time,
2617
+ instrumentationKey: ikey,
2618
+ version: 1,
2619
+ sampleRate: sampleRate,
2620
+ data: {
2621
+ baseType: baseType,
2622
+ baseData: baseData,
2623
+ },
2624
+ tags: tags,
2625
+ };
2626
+ envelopes.push(env);
2627
+ });
2628
+ }
2629
+ return envelopes;
2630
+ }
2244
2631
 
2245
2632
  // Copyright (c) Microsoft Corporation.
2246
2633
  /**
2247
2634
  * Azure Monitor OpenTelemetry Trace Exporter.
2248
2635
  */
2249
- class AzureMonitorTraceExporter {
2636
+ class AzureMonitorTraceExporter extends AzureMonitorBaseExporter {
2250
2637
  /**
2251
2638
  * Initializes a new instance of the AzureMonitorTraceExporter class.
2252
2639
  * @param AzureExporterConfig - Exporter configuration.
2253
2640
  */
2254
2641
  constructor(options = {}) {
2255
- var _a, _b, _c, _d;
2256
- this._numConsecutiveRedirects = 0;
2257
- const connectionString = options.connectionString || process.env[ENV_CONNECTION_STRING];
2258
- this._options = Object.assign({}, DEFAULT_EXPORTER_CONFIG);
2259
- this._options.apiVersion = (_a = options.apiVersion) !== null && _a !== void 0 ? _a : this._options.apiVersion;
2260
- this._options.aadTokenCredential = options.aadTokenCredential;
2261
- if (connectionString) {
2262
- const parsedConnectionString = ConnectionStringParser.parse(connectionString);
2263
- this._options.instrumentationKey =
2264
- (_b = parsedConnectionString.instrumentationkey) !== null && _b !== void 0 ? _b : this._options.instrumentationKey;
2265
- this._options.endpointUrl =
2266
- (_d = (_c = parsedConnectionString.ingestionendpoint) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : this._options.endpointUrl;
2267
- }
2268
- // Instrumentation key is required
2269
- if (!this._options.instrumentationKey) {
2270
- const message = "No instrumentation key or connection string was provided to the Azure Monitor Exporter";
2271
- api.diag.error(message);
2272
- throw new Error(message);
2273
- }
2274
- this._sender = new HttpSender(this._options);
2275
- this._persister = new FileSystemPersist(this._options);
2276
- this._retryTimer = null;
2642
+ super(options);
2643
+ /**
2644
+ * Flag to determine if Exporter is shutdown.
2645
+ */
2646
+ this._isShutdown = false;
2277
2647
  api.diag.debug("AzureMonitorTraceExporter was successfully setup");
2278
2648
  }
2279
- async _persist(envelopes) {
2280
- try {
2281
- const success = await this._persister.push(envelopes);
2282
- return success
2283
- ? { code: core.ExportResultCode.SUCCESS }
2284
- : {
2285
- code: core.ExportResultCode.FAILED,
2286
- error: new Error("Failed to persist envelope in disk."),
2287
- };
2649
+ /**
2650
+ * Export OpenTelemetry spans.
2651
+ * @param spans - Spans to export.
2652
+ * @param resultCallback - Result callback.
2653
+ */
2654
+ async export(spans, resultCallback) {
2655
+ if (this._isShutdown) {
2656
+ api.diag.info("Exporter shut down. Failed to export spans.");
2657
+ setTimeout(() => resultCallback({ code: core.ExportResultCode.FAILED }), 0);
2658
+ return;
2288
2659
  }
2289
- catch (ex) {
2290
- return { code: core.ExportResultCode.FAILED, error: ex };
2660
+ api.diag.info(`Exporting ${spans.length} span(s). Converting to envelopes...`);
2661
+ let envelopes = [];
2662
+ spans.forEach((span) => {
2663
+ envelopes.push(readableSpanToEnvelope(span, this._instrumentationKey));
2664
+ let spanEventEnvelopes = spanEventsToEnvelopes(span, this._instrumentationKey);
2665
+ if (spanEventEnvelopes.length > 0) {
2666
+ envelopes.push(...spanEventEnvelopes);
2667
+ }
2668
+ });
2669
+ resultCallback(await this._exportEnvelopes(envelopes));
2670
+ }
2671
+ /**
2672
+ * Shutdown AzureMonitorTraceExporter.
2673
+ */
2674
+ async shutdown() {
2675
+ this._isShutdown = true;
2676
+ api.diag.info("AzureMonitorTraceExporter shutting down");
2677
+ return this._shutdown();
2678
+ }
2679
+ }
2680
+
2681
+ // Copyright (c) Microsoft Corporation.
2682
+ function createPropertiesFromMetricAttributes(attributes) {
2683
+ const properties = {};
2684
+ if (attributes) {
2685
+ for (const key of Object.keys(attributes)) {
2686
+ properties[key] = attributes[key];
2291
2687
  }
2292
2688
  }
2293
- async exportEnvelopes(envelopes) {
2294
- api.diag.info(`Exporting ${envelopes.length} envelope(s)`);
2295
- try {
2296
- const { result, statusCode } = await this._sender.send(envelopes);
2297
- this._numConsecutiveRedirects = 0;
2298
- if (statusCode === 200) {
2299
- // Success -- @todo: start retry timer
2300
- if (!this._retryTimer) {
2301
- this._retryTimer = setTimeout(() => {
2302
- this._retryTimer = null;
2303
- this._sendFirstPersistedFile();
2304
- }, this._options.batchSendRetryIntervalMs);
2305
- this._retryTimer.unref();
2306
- }
2307
- return { code: core.ExportResultCode.SUCCESS };
2308
- }
2309
- else if (statusCode && isRetriable(statusCode)) {
2310
- // Failed -- persist failed data
2311
- if (result) {
2312
- api.diag.info(result);
2313
- const breezeResponse = JSON.parse(result);
2314
- const filteredEnvelopes = [];
2315
- breezeResponse.errors.forEach((error) => {
2316
- if (error.statusCode && isRetriable(error.statusCode)) {
2317
- filteredEnvelopes.push(envelopes[error.index]);
2318
- }
2319
- });
2320
- if (filteredEnvelopes.length > 0) {
2321
- // calls resultCallback(ExportResult) based on result of persister.push
2322
- return await this._persist(filteredEnvelopes);
2323
- }
2324
- // Failed -- not retriable
2325
- return {
2326
- code: core.ExportResultCode.FAILED,
2327
- };
2328
- }
2329
- else {
2330
- // calls resultCallback(ExportResult) based on result of persister.push
2331
- return await this._persist(envelopes);
2332
- }
2333
- }
2334
- else {
2335
- // Failed -- not retriable
2336
- return {
2337
- code: core.ExportResultCode.FAILED,
2689
+ return properties;
2690
+ }
2691
+ /**
2692
+ * Metric to Azure envelope parsing.
2693
+ * @internal
2694
+ */
2695
+ function resourceMetricsToEnvelope(metrics, ikey) {
2696
+ let envelopes = [];
2697
+ const time = new Date();
2698
+ const instrumentationKey = ikey;
2699
+ const tags = createTagsFromResource(metrics.resource);
2700
+ metrics.scopeMetrics.forEach((scopeMetric) => {
2701
+ scopeMetric.metrics.forEach((metric) => {
2702
+ metric.dataPoints.forEach((dataPoint) => {
2703
+ let baseData = {
2704
+ metrics: [],
2705
+ version: 2,
2706
+ properties: {},
2338
2707
  };
2339
- }
2340
- }
2341
- catch (error) {
2342
- const restError = error;
2343
- if (restError.statusCode &&
2344
- (restError.statusCode === 307 || // Temporary redirect
2345
- restError.statusCode === 308)) {
2346
- // Permanent redirect
2347
- this._numConsecutiveRedirects++;
2348
- // To prevent circular redirects
2349
- if (this._numConsecutiveRedirects < 10) {
2350
- if (restError.response && restError.response.headers) {
2351
- const location = restError.response.headers.get("location");
2352
- if (location) {
2353
- // Update sender URL
2354
- this._sender.handlePermanentRedirect(location);
2355
- // Send to redirect endpoint as HTTPs library doesn't handle redirect automatically
2356
- return this.exportEnvelopes(envelopes);
2357
- }
2358
- }
2708
+ baseData.properties = createPropertiesFromMetricAttributes(dataPoint.attributes);
2709
+ var metricDataPoint = {
2710
+ name: metric.descriptor.name,
2711
+ value: 0,
2712
+ dataPointType: "Aggregation",
2713
+ };
2714
+ if (metric.dataPointType == sdkMetrics.DataPointType.SUM ||
2715
+ metric.dataPointType == sdkMetrics.DataPointType.GAUGE) {
2716
+ metricDataPoint.value = dataPoint.value;
2717
+ metricDataPoint.count = 1;
2359
2718
  }
2360
2719
  else {
2361
- return { code: core.ExportResultCode.FAILED, error: new Error("Circular redirect") };
2362
- }
2363
- }
2364
- else if (restError.statusCode && isRetriable(restError.statusCode)) {
2365
- return await this._persist(envelopes);
2366
- }
2367
- if (this._isNetworkError(restError)) {
2368
- api.diag.error("Retrying due to transient client side error. Error message:", restError.message);
2369
- return await this._persist(envelopes);
2370
- }
2371
- api.diag.error("Envelopes could not be exported and are not retriable. Error message:", restError.message);
2372
- return { code: core.ExportResultCode.FAILED, error: restError };
2373
- }
2720
+ metricDataPoint.value = dataPoint.value.sum || 0;
2721
+ metricDataPoint.count = dataPoint.value.count;
2722
+ metricDataPoint.max = dataPoint.value.max;
2723
+ metricDataPoint.min = dataPoint.value.min;
2724
+ }
2725
+ baseData.metrics.push(metricDataPoint);
2726
+ let envelope = {
2727
+ name: "Microsoft.ApplicationInsights.Metric",
2728
+ time: time,
2729
+ sampleRate: 100,
2730
+ instrumentationKey: instrumentationKey,
2731
+ tags: tags,
2732
+ version: 1,
2733
+ data: {
2734
+ baseType: "MetricData",
2735
+ baseData: Object.assign({}, baseData),
2736
+ },
2737
+ };
2738
+ envelopes.push(envelope);
2739
+ });
2740
+ });
2741
+ });
2742
+ return envelopes;
2743
+ }
2744
+
2745
+ // Copyright (c) Microsoft Corporation.
2746
+ /**
2747
+ * Azure Monitor OpenTelemetry Metric Exporter.
2748
+ */
2749
+ class AzureMonitorMetricExporter extends AzureMonitorBaseExporter {
2750
+ /**
2751
+ * Initializes a new instance of the AzureMonitorMetricExporter class.
2752
+ * @param AzureExporterConfig - Exporter configuration.
2753
+ */
2754
+ constructor(options = {}) {
2755
+ super(options);
2756
+ /**
2757
+ * Flag to determine if Exporter is shutdown.
2758
+ */
2759
+ this._isShutdown = false;
2760
+ this._aggregationTemporality = sdkMetrics.AggregationTemporality.CUMULATIVE;
2761
+ api.diag.debug("AzureMonitorMetricExporter was successfully setup");
2374
2762
  }
2375
2763
  /**
2376
- * Export OpenTelemetry spans.
2377
- * @param spans - Spans to export.
2764
+ * Export OpenTelemetry resource metrics.
2765
+ * @param metrics - Resource metrics to export.
2378
2766
  * @param resultCallback - Result callback.
2379
2767
  */
2380
- async export(spans, resultCallback) {
2381
- api.diag.info(`Exporting ${spans.length} span(s). Converting to envelopes...`);
2382
- const envelopes = spans.map((span) => readableSpanToEnvelope(span, this._options.instrumentationKey));
2383
- resultCallback(await this.exportEnvelopes(envelopes));
2768
+ async export(metrics, resultCallback) {
2769
+ if (this._isShutdown) {
2770
+ api.diag.info("Exporter shut down. Failed to export spans.");
2771
+ setTimeout(() => resultCallback({ code: core.ExportResultCode.FAILED }), 0);
2772
+ return;
2773
+ }
2774
+ api.diag.info(`Exporting ${metrics.scopeMetrics.length} metrics(s). Converting to envelopes...`);
2775
+ let envelopes = resourceMetricsToEnvelope(metrics, this._instrumentationKey);
2776
+ // Supress tracing until OpenTelemetry Metrics SDK support it
2777
+ api.context.with(core.suppressTracing(api.context.active()), async () => {
2778
+ resultCallback(await this._exportEnvelopes(envelopes));
2779
+ });
2384
2780
  }
2385
2781
  /**
2386
- * Shutdown AzureMonitorTraceExporter.
2782
+ * Shutdown AzureMonitorMetricExporter.
2387
2783
  */
2388
2784
  async shutdown() {
2389
- api.diag.info("Azure Monitor Trace Exporter shutting down");
2390
- return this._sender.shutdown();
2785
+ this._isShutdown = true;
2786
+ api.diag.info("AzureMonitorMetricExporter shutting down");
2787
+ return this._shutdown();
2391
2788
  }
2392
- async _sendFirstPersistedFile() {
2393
- try {
2394
- const envelopes = (await this._persister.shift());
2395
- if (envelopes) {
2396
- await this._sender.send(envelopes);
2397
- }
2398
- }
2399
- catch (err) {
2400
- api.diag.warn(`Failed to fetch persisted file`, err);
2401
- }
2789
+ /**
2790
+ * Select aggregation temporality
2791
+ */
2792
+ selectAggregationTemporality(_instrumentType) {
2793
+ return this._aggregationTemporality;
2402
2794
  }
2403
- _isNetworkError(error) {
2404
- if (error && error.code && error.code === "REQUEST_SEND_ERROR") {
2405
- return true;
2406
- }
2407
- return false;
2795
+ /**
2796
+ * Force flush
2797
+ */
2798
+ async forceFlush() {
2799
+ return Promise.resolve();
2408
2800
  }
2409
2801
  }
2410
2802
 
2803
+ exports.ApplicationInsightsSampler = ApplicationInsightsSampler;
2804
+ exports.AzureMonitorBaseExporter = AzureMonitorBaseExporter;
2805
+ exports.AzureMonitorMetricExporter = AzureMonitorMetricExporter;
2411
2806
  exports.AzureMonitorTraceExporter = AzureMonitorTraceExporter;
2412
2807
  //# sourceMappingURL=index.js.map