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

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.
package/dist/index.js CHANGED
@@ -4,15 +4,16 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var api = require('@opentelemetry/api');
6
6
  var core = require('@opentelemetry/core');
7
- var os = require('os');
8
7
  var url = require('url');
9
- var semanticConventions = require('@opentelemetry/semantic-conventions');
10
8
  var coreRestPipeline = require('@azure/core-rest-pipeline');
11
9
  var coreClient = require('@azure/core-client');
12
10
  var fs = require('fs');
11
+ var os = require('os');
13
12
  var path = require('path');
14
13
  var child_process = require('child_process');
15
14
  var util = require('util');
15
+ var semanticConventions = require('@opentelemetry/semantic-conventions');
16
+ var sdkMetricsBase = require('@opentelemetry/sdk-metrics-base');
16
17
 
17
18
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
18
19
 
@@ -34,11 +35,11 @@ function _interopNamespace(e) {
34
35
  return Object.freeze(n);
35
36
  }
36
37
 
37
- var os__namespace = /*#__PURE__*/_interopNamespace(os);
38
- var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
39
38
  var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
40
39
  var coreClient__namespace = /*#__PURE__*/_interopNamespace(coreClient);
41
40
  var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
41
+ var os__namespace = /*#__PURE__*/_interopNamespace(os);
42
+ var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
42
43
  var path__namespace = /*#__PURE__*/_interopNamespace(path);
43
44
  var child_process__namespace = /*#__PURE__*/_interopNamespace(child_process);
44
45
 
@@ -1745,7 +1746,7 @@ const TIME_SINCE_ENQUEUED = "timeSinceEnqueued";
1745
1746
  * AzureMonitorTraceExporter version.
1746
1747
  * @internal
1747
1748
  */
1748
- const packageVersion = "1.0.0-beta.7";
1749
+ const packageVersion = "1.0.0-beta.8";
1749
1750
  var DependencyTypes;
1750
1751
  (function (DependencyTypes) {
1751
1752
  DependencyTypes["InProc"] = "InProc";
@@ -1828,6 +1829,200 @@ function msToTimeSpan(ms) {
1828
1829
  return `${daysText + hour}:${min}:${sec}`;
1829
1830
  }
1830
1831
 
1832
+ // Copyright (c) Microsoft Corporation.
1833
+ /**
1834
+ * Azure Monitor OpenTelemetry Trace Exporter.
1835
+ */
1836
+ class AzureMonitorBaseExporter {
1837
+ /**
1838
+ * Initializes a new instance of the AzureMonitorBaseExporter class.
1839
+ * @param AzureExporterConfig - Exporter configuration.
1840
+ */
1841
+ constructor(options = {}) {
1842
+ var _a, _b, _c, _d;
1843
+ this._numConsecutiveRedirects = 0;
1844
+ const connectionString = options.connectionString || process.env[ENV_CONNECTION_STRING];
1845
+ this._options = Object.assign({}, DEFAULT_EXPORTER_CONFIG);
1846
+ this._options.apiVersion = (_a = options.apiVersion) !== null && _a !== void 0 ? _a : this._options.apiVersion;
1847
+ this._options.aadTokenCredential = options.aadTokenCredential;
1848
+ if (connectionString) {
1849
+ const parsedConnectionString = ConnectionStringParser.parse(connectionString);
1850
+ this._options.instrumentationKey =
1851
+ (_b = parsedConnectionString.instrumentationkey) !== null && _b !== void 0 ? _b : this._options.instrumentationKey;
1852
+ this._options.endpointUrl =
1853
+ (_d = (_c = parsedConnectionString.ingestionendpoint) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : this._options.endpointUrl;
1854
+ }
1855
+ // Instrumentation key is required
1856
+ if (!this._options.instrumentationKey) {
1857
+ const message = "No instrumentation key or connection string was provided to the Azure Monitor Exporter";
1858
+ api.diag.error(message);
1859
+ throw new Error(message);
1860
+ }
1861
+ this._instrumentationKey = this._options.instrumentationKey;
1862
+ this._sender = new HttpSender(this._options);
1863
+ this._persister = new FileSystemPersist(this._options);
1864
+ this._retryTimer = null;
1865
+ api.diag.debug("AzureMonitorTraceExporter was successfully setup");
1866
+ }
1867
+ /**
1868
+ * Persist envelopes to disk
1869
+ */
1870
+ async _persist(envelopes) {
1871
+ try {
1872
+ const success = await this._persister.push(envelopes);
1873
+ return success
1874
+ ? { code: core.ExportResultCode.SUCCESS }
1875
+ : {
1876
+ code: core.ExportResultCode.FAILED,
1877
+ error: new Error("Failed to persist envelope in disk."),
1878
+ };
1879
+ }
1880
+ catch (ex) {
1881
+ return { code: core.ExportResultCode.FAILED, error: ex };
1882
+ }
1883
+ }
1884
+ /**
1885
+ * Shutdown exporter
1886
+ */
1887
+ async _shutdown() {
1888
+ return this._sender.shutdown();
1889
+ }
1890
+ /**
1891
+ * Export envelopes
1892
+ */
1893
+ async _exportEnvelopes(envelopes) {
1894
+ api.diag.info(`Exporting ${envelopes.length} envelope(s)`);
1895
+ try {
1896
+ const { result, statusCode } = await this._sender.send(envelopes);
1897
+ this._numConsecutiveRedirects = 0;
1898
+ if (statusCode === 200) {
1899
+ // Success -- @todo: start retry timer
1900
+ if (!this._retryTimer) {
1901
+ this._retryTimer = setTimeout(() => {
1902
+ this._retryTimer = null;
1903
+ this._sendFirstPersistedFile();
1904
+ }, this._options.batchSendRetryIntervalMs);
1905
+ this._retryTimer.unref();
1906
+ }
1907
+ return { code: core.ExportResultCode.SUCCESS };
1908
+ }
1909
+ else if (statusCode && isRetriable(statusCode)) {
1910
+ // Failed -- persist failed data
1911
+ if (result) {
1912
+ api.diag.info(result);
1913
+ const breezeResponse = JSON.parse(result);
1914
+ const filteredEnvelopes = [];
1915
+ if (breezeResponse.errors) {
1916
+ breezeResponse.errors.forEach((error) => {
1917
+ if (error.statusCode && isRetriable(error.statusCode)) {
1918
+ filteredEnvelopes.push(envelopes[error.index]);
1919
+ }
1920
+ });
1921
+ }
1922
+ if (filteredEnvelopes.length > 0) {
1923
+ // calls resultCallback(ExportResult) based on result of persister.push
1924
+ return await this._persist(filteredEnvelopes);
1925
+ }
1926
+ // Failed -- not retriable
1927
+ return {
1928
+ code: core.ExportResultCode.FAILED,
1929
+ };
1930
+ }
1931
+ else {
1932
+ // calls resultCallback(ExportResult) based on result of persister.push
1933
+ return await this._persist(envelopes);
1934
+ }
1935
+ }
1936
+ else {
1937
+ // Failed -- not retriable
1938
+ return {
1939
+ code: core.ExportResultCode.FAILED,
1940
+ };
1941
+ }
1942
+ }
1943
+ catch (error) {
1944
+ const restError = error;
1945
+ if (restError.statusCode &&
1946
+ (restError.statusCode === 307 || // Temporary redirect
1947
+ restError.statusCode === 308)) {
1948
+ // Permanent redirect
1949
+ this._numConsecutiveRedirects++;
1950
+ // To prevent circular redirects
1951
+ if (this._numConsecutiveRedirects < 10) {
1952
+ if (restError.response && restError.response.headers) {
1953
+ const location = restError.response.headers.get("location");
1954
+ if (location) {
1955
+ // Update sender URL
1956
+ this._sender.handlePermanentRedirect(location);
1957
+ // Send to redirect endpoint as HTTPs library doesn't handle redirect automatically
1958
+ return this._exportEnvelopes(envelopes);
1959
+ }
1960
+ }
1961
+ }
1962
+ else {
1963
+ return { code: core.ExportResultCode.FAILED, error: new Error("Circular redirect") };
1964
+ }
1965
+ }
1966
+ else if (restError.statusCode && isRetriable(restError.statusCode)) {
1967
+ return await this._persist(envelopes);
1968
+ }
1969
+ if (this._isNetworkError(restError)) {
1970
+ api.diag.error("Retrying due to transient client side error. Error message:", restError.message);
1971
+ return await this._persist(envelopes);
1972
+ }
1973
+ api.diag.error("Envelopes could not be exported and are not retriable. Error message:", restError.message);
1974
+ return { code: core.ExportResultCode.FAILED, error: restError };
1975
+ }
1976
+ }
1977
+ async _sendFirstPersistedFile() {
1978
+ try {
1979
+ const envelopes = (await this._persister.shift());
1980
+ if (envelopes) {
1981
+ await this._sender.send(envelopes);
1982
+ }
1983
+ }
1984
+ catch (err) {
1985
+ api.diag.warn(`Failed to fetch persisted file`, err);
1986
+ }
1987
+ }
1988
+ _isNetworkError(error) {
1989
+ if (error && error.code && error.code === "REQUEST_SEND_ERROR") {
1990
+ return true;
1991
+ }
1992
+ return false;
1993
+ }
1994
+ }
1995
+
1996
+ // Copyright (c) Microsoft Corporation.
1997
+ function createTagsFromResource(resource) {
1998
+ const context = getInstance();
1999
+ const tags = Object.assign({}, context.tags);
2000
+ if (resource && resource.attributes) {
2001
+ const serviceName = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAME];
2002
+ const serviceNamespace = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAMESPACE];
2003
+ if (serviceName) {
2004
+ if (serviceNamespace) {
2005
+ tags[KnownContextTagKeys.AiCloudRole] = `${serviceNamespace}.${serviceName}`;
2006
+ }
2007
+ else {
2008
+ tags[KnownContextTagKeys.AiCloudRole] = String(serviceName);
2009
+ }
2010
+ }
2011
+ const serviceInstanceId = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_INSTANCE_ID];
2012
+ if (serviceInstanceId) {
2013
+ tags[KnownContextTagKeys.AiCloudRoleInstance] = String(serviceInstanceId);
2014
+ }
2015
+ else {
2016
+ tags[KnownContextTagKeys.AiCloudRoleInstance] = os__default["default"] && os__default["default"].hostname();
2017
+ }
2018
+ const endUserId = resource.attributes[semanticConventions.SemanticAttributes.ENDUSER_ID];
2019
+ if (endUserId) {
2020
+ tags[KnownContextTagKeys.AiUserId] = String(endUserId);
2021
+ }
2022
+ }
2023
+ return tags;
2024
+ }
2025
+
1831
2026
  // Copyright (c) Microsoft Corporation.
1832
2027
  // Licensed under the MIT license.
1833
2028
  /**
@@ -1893,36 +2088,21 @@ const parseEventHubSpan = (span, baseData) => {
1893
2088
  };
1894
2089
 
1895
2090
  // Copyright (c) Microsoft Corporation.
1896
- function createTagsFromSpan(span) {
1897
- const context = getInstance();
1898
- const tags = Object.assign({}, context.tags);
2091
+ function createGenericTagsFromSpan(span) {
2092
+ const tags = createTagsFromResource(span.resource);
1899
2093
  tags[KnownContextTagKeys.AiOperationId] = span.spanContext().traceId;
1900
2094
  if (span.parentSpanId) {
1901
2095
  tags[KnownContextTagKeys.AiOperationParentId] = span.parentSpanId;
1902
2096
  }
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
- }
2097
+ const httpUserAgent = span.attributes[semanticConventions.SemanticAttributes.HTTP_USER_AGENT];
2098
+ if (httpUserAgent) {
2099
+ // TODO: Not exposed in Swagger, need to update def
2100
+ tags["ai.user.userAgent"] = String(httpUserAgent);
1925
2101
  }
2102
+ return tags;
2103
+ }
2104
+ function createTagsFromSpan(span) {
2105
+ const tags = createGenericTagsFromSpan(span);
1926
2106
  if (span.kind === api.SpanKind.SERVER) {
1927
2107
  const httpMethod = span.attributes[semanticConventions.SemanticAttributes.HTTP_METHOD];
1928
2108
  const httpClientIp = span.attributes[semanticConventions.SemanticAttributes.HTTP_CLIENT_IP];
@@ -1956,25 +2136,33 @@ function createTagsFromSpan(span) {
1956
2136
  }
1957
2137
  }
1958
2138
  // 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
2139
  return tags;
1965
2140
  }
1966
- function createPropertiesFromSpan(span) {
2141
+ function createPropertiesFromSpanAttributes(attributes) {
1967
2142
  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];
2143
+ if (attributes) {
2144
+ for (const key of Object.keys(attributes)) {
2145
+ if (!(key.startsWith("http.") ||
2146
+ key.startsWith("rpc.") ||
2147
+ key.startsWith("db.") ||
2148
+ key.startsWith("peer.") ||
2149
+ key.startsWith("message.") ||
2150
+ key.startsWith("messaging.") ||
2151
+ key.startsWith("enduser.") ||
2152
+ key.startsWith("net.") ||
2153
+ key.startsWith("exception.") ||
2154
+ key.startsWith("thread.") ||
2155
+ key.startsWith("faas.") ||
2156
+ key.startsWith("code."))) {
2157
+ properties[key] = attributes[key];
2158
+ }
1976
2159
  }
1977
2160
  }
2161
+ return properties;
2162
+ }
2163
+ function createPropertiesFromSpan(span) {
2164
+ const properties = createPropertiesFromSpanAttributes(span.attributes);
2165
+ const measurements = {};
1978
2166
  const links = span.links.map((link) => ({
1979
2167
  operation_Id: link.context.traceId,
1980
2168
  id: link.context.spanId,
@@ -2103,7 +2291,7 @@ function createDependencyData(span) {
2103
2291
  }
2104
2292
  }
2105
2293
  }
2106
- catch (error) { }
2294
+ catch (ex) { }
2107
2295
  remoteDependencyData.target = `${target}`;
2108
2296
  }
2109
2297
  }
@@ -2241,172 +2429,219 @@ function readableSpanToEnvelope(span, ikey) {
2241
2429
  },
2242
2430
  };
2243
2431
  }
2432
+ /**
2433
+ * Span Events to Azure envelopes parsing.
2434
+ * @internal
2435
+ */
2436
+ function spanEventsToEnvelopes(span, ikey) {
2437
+ let envelopes = [];
2438
+ if (span.events) {
2439
+ span.events.forEach((event) => {
2440
+ let baseType;
2441
+ const sampleRate = 100;
2442
+ let time = new Date(core.hrTimeToMilliseconds(event.time));
2443
+ let name = "";
2444
+ let baseData;
2445
+ const properties = createPropertiesFromSpanAttributes(event.attributes);
2446
+ const tags = createGenericTagsFromSpan(span);
2447
+ if (event.name == "exception") {
2448
+ name = "Microsoft.ApplicationInsights.Exception";
2449
+ baseType = "ExceptionData";
2450
+ let typeName = "";
2451
+ let message = "Exception";
2452
+ let stack = "";
2453
+ let hasFullStack = false;
2454
+ if (event.attributes) {
2455
+ typeName = String(event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_TYPE]);
2456
+ stack = String(event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_STACKTRACE]);
2457
+ if (stack) {
2458
+ hasFullStack = true;
2459
+ }
2460
+ let exceptionMsg = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE];
2461
+ if (exceptionMsg) {
2462
+ message = String(exceptionMsg);
2463
+ }
2464
+ let escaped = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED];
2465
+ if (escaped != undefined) {
2466
+ properties[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED] = String(escaped);
2467
+ }
2468
+ }
2469
+ let exceptionDetails = {
2470
+ typeName: typeName,
2471
+ message: message,
2472
+ stack: stack,
2473
+ hasFullStack: hasFullStack,
2474
+ };
2475
+ let exceptionData = {
2476
+ exceptions: [exceptionDetails],
2477
+ version: 2,
2478
+ properties: properties,
2479
+ };
2480
+ baseData = exceptionData;
2481
+ }
2482
+ else {
2483
+ name = "Microsoft.ApplicationInsights.Message";
2484
+ baseType = "MessageData";
2485
+ let messageData = {
2486
+ message: event.name,
2487
+ version: 2,
2488
+ properties: properties,
2489
+ };
2490
+ baseData = messageData;
2491
+ }
2492
+ let env = {
2493
+ name: name,
2494
+ time: time,
2495
+ instrumentationKey: ikey,
2496
+ version: 1,
2497
+ sampleRate: sampleRate,
2498
+ data: {
2499
+ baseType: baseType,
2500
+ baseData: baseData,
2501
+ },
2502
+ tags: tags,
2503
+ };
2504
+ envelopes.push(env);
2505
+ });
2506
+ }
2507
+ return envelopes;
2508
+ }
2244
2509
 
2245
2510
  // Copyright (c) Microsoft Corporation.
2246
2511
  /**
2247
2512
  * Azure Monitor OpenTelemetry Trace Exporter.
2248
2513
  */
2249
- class AzureMonitorTraceExporter {
2514
+ class AzureMonitorTraceExporter extends AzureMonitorBaseExporter {
2250
2515
  /**
2251
2516
  * Initializes a new instance of the AzureMonitorTraceExporter class.
2252
2517
  * @param AzureExporterConfig - Exporter configuration.
2253
2518
  */
2254
2519
  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;
2520
+ super(options);
2277
2521
  api.diag.debug("AzureMonitorTraceExporter was successfully setup");
2278
2522
  }
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
- };
2288
- }
2289
- catch (ex) {
2290
- return { code: core.ExportResultCode.FAILED, error: ex };
2291
- }
2292
- }
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
- }
2523
+ /**
2524
+ * Export OpenTelemetry spans.
2525
+ * @param spans - Spans to export.
2526
+ * @param resultCallback - Result callback.
2527
+ */
2528
+ async export(spans, resultCallback) {
2529
+ api.diag.info(`Exporting ${spans.length} span(s). Converting to envelopes...`);
2530
+ let envelopes = [];
2531
+ spans.forEach((span) => {
2532
+ envelopes.push(readableSpanToEnvelope(span, this._instrumentationKey));
2533
+ let spanEventEnvelopes = spanEventsToEnvelopes(span, this._instrumentationKey);
2534
+ if (spanEventEnvelopes.length > 0) {
2535
+ envelopes.push(...spanEventEnvelopes);
2333
2536
  }
2334
- else {
2335
- // Failed -- not retriable
2336
- return {
2337
- code: core.ExportResultCode.FAILED,
2537
+ });
2538
+ resultCallback(await this._exportEnvelopes(envelopes));
2539
+ }
2540
+ /**
2541
+ * Shutdown AzureMonitorTraceExporter.
2542
+ */
2543
+ async shutdown() {
2544
+ api.diag.info("Azure Monitor Trace Exporter shutting down");
2545
+ return this._shutdown();
2546
+ }
2547
+ }
2548
+
2549
+ // Copyright (c) Microsoft Corporation.
2550
+ /**
2551
+ * Metric to Azure envelope parsing.
2552
+ * @internal
2553
+ */
2554
+ function resourceMetricsToEnvelope(metrics, ikey) {
2555
+ let envelopes = [];
2556
+ const time = new Date();
2557
+ const instrumentationKey = ikey;
2558
+ const tags = createTagsFromResource(metrics.resource);
2559
+ metrics.scopeMetrics.forEach((scopeMetric) => {
2560
+ let baseData = {
2561
+ metrics: [],
2562
+ version: 2,
2563
+ };
2564
+ scopeMetric.metrics.forEach((metric) => {
2565
+ metric.dataPoints.forEach((dataPoint) => {
2566
+ var metricDataPoint = {
2567
+ name: metric.descriptor.name,
2568
+ value: 0,
2569
+ dataPointType: "Aggregation",
2338
2570
  };
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
- }
2571
+ if (metric.dataPointType == sdkMetricsBase.DataPointType.SINGULAR) {
2572
+ metricDataPoint.value = dataPoint.value;
2573
+ metricDataPoint.count = 1;
2359
2574
  }
2360
2575
  else {
2361
- return { code: core.ExportResultCode.FAILED, error: new Error("Circular redirect") };
2576
+ metricDataPoint.value = dataPoint.value.sum;
2577
+ metricDataPoint.count = dataPoint.value.count;
2362
2578
  }
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
- }
2579
+ baseData.metrics.push(metricDataPoint);
2580
+ });
2581
+ });
2582
+ let envelope = {
2583
+ name: "Microsoft.ApplicationInsights.Metric",
2584
+ time: time,
2585
+ sampleRate: 100,
2586
+ instrumentationKey: instrumentationKey,
2587
+ tags: tags,
2588
+ version: 1,
2589
+ data: {
2590
+ baseType: "MetricData",
2591
+ baseData: Object.assign({}, baseData),
2592
+ },
2593
+ };
2594
+ envelopes.push(envelope);
2595
+ });
2596
+ return envelopes;
2597
+ }
2598
+
2599
+ // Copyright (c) Microsoft Corporation.
2600
+ /**
2601
+ * Azure Monitor OpenTelemetry Metric Exporter.
2602
+ */
2603
+ class AzureMonitorMetricExporter extends AzureMonitorBaseExporter {
2604
+ /**
2605
+ * Initializes a new instance of the AzureMonitorMetricExporter class.
2606
+ * @param AzureExporterConfig - Exporter configuration.
2607
+ */
2608
+ constructor(options = {}) {
2609
+ super(options);
2610
+ api.diag.debug("AzureMonitorMetricExporter was successfully setup");
2374
2611
  }
2375
2612
  /**
2376
- * Export OpenTelemetry spans.
2377
- * @param spans - Spans to export.
2613
+ * Export OpenTelemetry resource metrics.
2614
+ * @param metrics - Resource metrics to export.
2378
2615
  * @param resultCallback - Result callback.
2379
2616
  */
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));
2617
+ async export(metrics, resultCallback) {
2618
+ api.diag.info(`Exporting ${metrics.scopeMetrics.length} metrics(s). Converting to envelopes...`);
2619
+ let envelopes = resourceMetricsToEnvelope(metrics, this._instrumentationKey);
2620
+ resultCallback(await this._exportEnvelopes(envelopes));
2384
2621
  }
2385
2622
  /**
2386
- * Shutdown AzureMonitorTraceExporter.
2623
+ * Shutdown AzureMonitorMetricExporter.
2387
2624
  */
2388
2625
  async shutdown() {
2389
2626
  api.diag.info("Azure Monitor Trace Exporter shutting down");
2390
- return this._sender.shutdown();
2627
+ return this._shutdown();
2391
2628
  }
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
- }
2629
+ /**
2630
+ * Select aggregation temporality
2631
+ */
2632
+ selectAggregationTemporality() {
2633
+ return sdkMetricsBase.AggregationTemporality.CUMULATIVE;
2402
2634
  }
2403
- _isNetworkError(error) {
2404
- if (error && error.code && error.code === "REQUEST_SEND_ERROR") {
2405
- return true;
2406
- }
2407
- return false;
2635
+ /**
2636
+ * Force flush
2637
+ */
2638
+ async forceFlush() {
2639
+ // TODO: https://github.com/open-telemetry/opentelemetry-js/issues/3060
2640
+ throw new Error("Method not implemented.");
2408
2641
  }
2409
2642
  }
2410
2643
 
2644
+ exports.AzureMonitorBaseExporter = AzureMonitorBaseExporter;
2645
+ exports.AzureMonitorMetricExporter = AzureMonitorMetricExporter;
2411
2646
  exports.AzureMonitorTraceExporter = AzureMonitorTraceExporter;
2412
2647
  //# sourceMappingURL=index.js.map