@azure/monitor-opentelemetry-exporter 1.0.0-beta.11 → 1.0.0-beta.13

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 (33) hide show
  1. package/dist/index.js +401 -128
  2. package/dist-esm/src/Declarations/Constants.js +5 -0
  3. package/dist-esm/src/Declarations/Constants.js.map +1 -1
  4. package/dist-esm/src/export/base.js +2 -2
  5. package/dist-esm/src/export/base.js.map +1 -1
  6. package/dist-esm/src/export/log.js +53 -0
  7. package/dist-esm/src/export/log.js.map +1 -0
  8. package/dist-esm/src/export/trace.js +17 -8
  9. package/dist-esm/src/export/trace.js.map +1 -1
  10. package/dist-esm/src/generated/applicationInsightsClient.js +1 -1
  11. package/dist-esm/src/generated/applicationInsightsClient.js.map +1 -1
  12. package/dist-esm/src/index.js +1 -0
  13. package/dist-esm/src/index.js.map +1 -1
  14. package/dist-esm/src/platform/nodejs/context/context.js +11 -3
  15. package/dist-esm/src/platform/nodejs/context/context.js.map +1 -1
  16. package/dist-esm/src/platform/nodejs/persist/fileAccessControl.js +2 -1
  17. package/dist-esm/src/platform/nodejs/persist/fileAccessControl.js.map +1 -1
  18. package/dist-esm/src/platform/nodejs/persist/fileSystemPersist.js +2 -1
  19. package/dist-esm/src/platform/nodejs/persist/fileSystemPersist.js.map +1 -1
  20. package/dist-esm/src/utils/common.js +101 -15
  21. package/dist-esm/src/utils/common.js.map +1 -1
  22. package/dist-esm/src/utils/connectionStringParser.js +2 -1
  23. package/dist-esm/src/utils/connectionStringParser.js.map +1 -1
  24. package/dist-esm/src/utils/constants/applicationinsights.js +12 -30
  25. package/dist-esm/src/utils/constants/applicationinsights.js.map +1 -1
  26. package/dist-esm/src/utils/logUtils.js +177 -0
  27. package/dist-esm/src/utils/logUtils.js.map +1 -0
  28. package/dist-esm/src/utils/metricUtils.js +2 -42
  29. package/dist-esm/src/utils/metricUtils.js.map +1 -1
  30. package/dist-esm/src/utils/spanUtils.js +35 -31
  31. package/dist-esm/src/utils/spanUtils.js.map +1 -1
  32. package/package.json +13 -11
  33. package/types/monitor-opentelemetry-exporter.d.ts +27 -0
package/dist/index.js CHANGED
@@ -66,7 +66,7 @@ const TIME_SINCE_ENQUEUED = "timeSinceEnqueued";
66
66
  * AzureMonitorTraceExporter version.
67
67
  * @internal
68
68
  */
69
- const packageVersion = "1.0.0-beta.11";
69
+ const packageVersion = "1.0.0-beta.13";
70
70
  var DependencyTypes;
71
71
  (function (DependencyTypes) {
72
72
  DependencyTypes["InProc"] = "InProc";
@@ -76,35 +76,17 @@ var DependencyTypes;
76
76
  DependencyTypes["Grpc"] = "GRPC";
77
77
  })(DependencyTypes || (DependencyTypes = {}));
78
78
  const AzureMonitorSampleRate = "_MS.sampleRate";
79
- var StandardMetrics;
80
- (function (StandardMetrics) {
81
- StandardMetrics["HTTP_REQUEST_DURATION"] = "azureMonitor.http.requestDuration";
82
- StandardMetrics["HTTP_DEPENDENCY_DURATION"] = "azureMonitor.http.dependencyDuration";
83
- StandardMetrics["EXCEPTION_COUNT"] = "azureMonitor.exceptionCount";
84
- StandardMetrics["TRACE_COUNT"] = "azureMonitor.traceCount";
85
- })(StandardMetrics || (StandardMetrics = {}));
86
- var StandardMetricIds;
87
- (function (StandardMetricIds) {
88
- StandardMetricIds["REQUEST_DURATION"] = "requests/duration";
89
- StandardMetricIds["DEPENDENCY_DURATION"] = "dependencies/duration";
90
- StandardMetricIds["EXCEPTION_COUNT"] = "exceptions/count";
91
- StandardMetricIds["TRACE_COUNT"] = "traces/count";
92
- })(StandardMetricIds || (StandardMetricIds = {}));
93
- // Names expected in Breeze side for dimensions
94
- const PreAggregatedMetricPropertyNames = {
95
- cloudRoleInstance: "cloud/roleInstance",
96
- cloudRoleName: "cloud/roleName",
97
- operationSynthetic: "operation/synthetic",
98
- requestSuccess: "Request.Success",
99
- requestResultCode: "request/resultCode",
100
- dependencyType: "Dependency.Type",
101
- dependencyTarget: "dependency/target",
102
- dependencySuccess: "Dependency.Success",
103
- dependencyResultCode: "dependency/resultCode",
104
- traceSeverityLevel: "trace/severityLevel",
105
- metricId: "_MS.MetricId",
106
- IsAutocollected: "_MS.IsAutocollected",
107
- };
79
+ const ApplicationInsightsBaseType = "_MS.baseType";
80
+ const ApplicationInsightsMessageName = "Microsoft.ApplicationInsights.Message";
81
+ const ApplicationInsightsExceptionName = "Microsoft.ApplicationInsights.Exception";
82
+ const ApplicationInsightsPageViewName = "Microsoft.ApplicationInsights.PageView";
83
+ const ApplicationInsightsAvailabilityName = "Microsoft.ApplicationInsights.Availability";
84
+ const ApplicationInsightsEventName = "Microsoft.ApplicationInsights.Event";
85
+ const ApplicationInsightsMessageBaseType = "MessageData";
86
+ const ApplicationInsightsExceptionBaseType = "TelemetryExceptionData";
87
+ const ApplicationInsightsPageViewBaseType = "PageViewData";
88
+ const ApplicationInsightsAvailabilityBaseType = "AvailabilityData";
89
+ const ApplicationInsightsEventBaseType = "TelemetryEventData";
108
90
 
109
91
  /**
110
92
  * ApplicationInsightsSampler is responsible for the following:
@@ -217,6 +199,11 @@ const DEFAULT_LIVEMETRICS_ENDPOINT = "https://rt.services.visualstudio.com";
217
199
  * @internal
218
200
  */
219
201
  const ENV_CONNECTION_STRING = "APPLICATIONINSIGHTS_CONNECTION_STRING";
202
+ /**
203
+ * Disable Statsbeat environment variable name.
204
+ * @internal
205
+ */
206
+ const ENV_DISABLE_STATSBEAT = "APPLICATION_INSIGHTS_NO_STATSBEAT";
220
207
  /**
221
208
  * QuickPulse metric counter names.
222
209
  * @internal
@@ -1756,7 +1743,7 @@ class ApplicationInsightsClient extends coreClient__namespace.ServiceClient {
1756
1743
  const defaults = {
1757
1744
  requestContentType: "application/json; charset=utf-8"
1758
1745
  };
1759
- const packageDetails = `azsdk-js-monitor-opentelemetry-exporter/1.0.0-beta.11`;
1746
+ const packageDetails = `azsdk-js-monitor-opentelemetry-exporter/1.0.0-beta.13`;
1760
1747
  const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix
1761
1748
  ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`
1762
1749
  : `${packageDetails}`;
@@ -1912,14 +1899,21 @@ class Context {
1912
1899
  [Context.nodeVersion] = node.split(".");
1913
1900
  Context.opentelemetryVersion = core.SDK_INFO[semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_VERSION];
1914
1901
  Context.sdkVersion = packageVersion;
1915
- this.tags[KnownContextTagKeys.AiInternalSdkVersion] = `node${Context.nodeVersion}:otel${Context.opentelemetryVersion}:ext${Context.sdkVersion}`;
1902
+ let prefix = process.env["AZURE_MONITOR_AGENT_PREFIX"]
1903
+ ? process.env["AZURE_MONITOR_AGENT_PREFIX"]
1904
+ : "";
1905
+ let version = process.env["AZURE_MONITOR_DISTRO_VERSION"]
1906
+ ? `dst${process.env["AZURE_MONITOR_DISTRO_VERSION"]}`
1907
+ : `ext${Context.sdkVersion}`;
1908
+ let internalSdkVersion = `${prefix}node${Context.nodeVersion}:otel${Context.opentelemetryVersion}:${version}`;
1909
+ this.tags[KnownContextTagKeys.AiInternalSdkVersion] = internalSdkVersion;
1916
1910
  }
1917
1911
  }
1918
1912
  Context.sdkVersion = null;
1919
1913
  Context.opentelemetryVersion = null;
1920
1914
  Context.nodeVersion = "";
1921
1915
  /**
1922
- * Singleton Context instance.
1916
+ * Singleton Context instance
1923
1917
  * @internal
1924
1918
  */
1925
1919
  function getInstance$1() {
@@ -2505,7 +2499,7 @@ class AzureMonitorBaseExporter {
2505
2499
  }
2506
2500
  this._sender = new HttpSender(this._endpointUrl, this._options);
2507
2501
  this._persister = new FileSystemPersist(this._instrumentationKey, this._options);
2508
- if (!this._isStatsbeatExporter) {
2502
+ if (!this._isStatsbeatExporter && !process.env[ENV_DISABLE_STATSBEAT]) {
2509
2503
  // Initialize statsbeatMetrics
2510
2504
  this._networkStatsbeatMetrics = new NetworkStatsbeatMetrics({
2511
2505
  instrumentationKey: this._instrumentationKey,
@@ -2695,29 +2689,80 @@ function createTagsFromResource(resource) {
2695
2689
  const context = getInstance$1();
2696
2690
  const tags = Object.assign({}, context.tags);
2697
2691
  if (resource && resource.attributes) {
2698
- const serviceName = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAME];
2699
- const serviceNamespace = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAMESPACE];
2700
- if (serviceName) {
2692
+ tags[KnownContextTagKeys.AiCloudRole] = getCloudRole(resource);
2693
+ tags[KnownContextTagKeys.AiCloudRoleInstance] = getCloudRoleInstance(resource);
2694
+ const endUserId = resource.attributes[semanticConventions.SemanticAttributes.ENDUSER_ID];
2695
+ if (endUserId) {
2696
+ tags[KnownContextTagKeys.AiUserId] = String(endUserId);
2697
+ }
2698
+ }
2699
+ return tags;
2700
+ }
2701
+ function getCloudRole(resource) {
2702
+ let cloudRole = "";
2703
+ // Service attributes
2704
+ const serviceName = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAME];
2705
+ const serviceNamespace = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_NAMESPACE];
2706
+ if (serviceName) {
2707
+ // Custom Service name provided by customer is highest precedence
2708
+ if (!String(serviceName).startsWith("unknown_service")) {
2701
2709
  if (serviceNamespace) {
2702
- tags[KnownContextTagKeys.AiCloudRole] = `${serviceNamespace}.${serviceName}`;
2710
+ return `${serviceNamespace}.${serviceName}`;
2703
2711
  }
2704
2712
  else {
2705
- tags[KnownContextTagKeys.AiCloudRole] = String(serviceName);
2713
+ return String(serviceName);
2706
2714
  }
2707
2715
  }
2708
- const serviceInstanceId = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_INSTANCE_ID];
2709
- if (serviceInstanceId) {
2710
- tags[KnownContextTagKeys.AiCloudRoleInstance] = String(serviceInstanceId);
2711
- }
2712
2716
  else {
2713
- tags[KnownContextTagKeys.AiCloudRoleInstance] = os__default["default"] && os__default["default"].hostname();
2714
- }
2715
- const endUserId = resource.attributes[semanticConventions.SemanticAttributes.ENDUSER_ID];
2716
- if (endUserId) {
2717
- tags[KnownContextTagKeys.AiUserId] = String(endUserId);
2717
+ // Service attributes will be only used if K8S attributes are not present
2718
+ if (serviceNamespace) {
2719
+ cloudRole = `${serviceNamespace}.${serviceName}`;
2720
+ }
2721
+ else {
2722
+ cloudRole = String(serviceName);
2723
+ }
2718
2724
  }
2719
2725
  }
2720
- return tags;
2726
+ // Kubernetes attributes should take precedence
2727
+ const kubernetesDeploymentName = resource.attributes[semanticConventions.SemanticResourceAttributes.K8S_DEPLOYMENT_NAME];
2728
+ if (kubernetesDeploymentName) {
2729
+ return String(kubernetesDeploymentName);
2730
+ }
2731
+ const kuberneteReplicasetName = resource.attributes[semanticConventions.SemanticResourceAttributes.K8S_REPLICASET_NAME];
2732
+ if (kuberneteReplicasetName) {
2733
+ return String(kuberneteReplicasetName);
2734
+ }
2735
+ const kubernetesStatefulSetName = resource.attributes[semanticConventions.SemanticResourceAttributes.K8S_STATEFULSET_NAME];
2736
+ if (kubernetesStatefulSetName) {
2737
+ return String(kubernetesStatefulSetName);
2738
+ }
2739
+ const kubernetesJobName = resource.attributes[semanticConventions.SemanticResourceAttributes.K8S_JOB_NAME];
2740
+ if (kubernetesJobName) {
2741
+ return String(kubernetesJobName);
2742
+ }
2743
+ const kubernetesCronjobName = resource.attributes[semanticConventions.SemanticResourceAttributes.K8S_CRONJOB_NAME];
2744
+ if (kubernetesCronjobName) {
2745
+ return String(kubernetesCronjobName);
2746
+ }
2747
+ const kubernetesDaemonsetName = resource.attributes[semanticConventions.SemanticResourceAttributes.K8S_DAEMONSET_NAME];
2748
+ if (kubernetesDaemonsetName) {
2749
+ return String(kubernetesDaemonsetName);
2750
+ }
2751
+ return cloudRole;
2752
+ }
2753
+ function getCloudRoleInstance(resource) {
2754
+ // Kubernetes attributes should take precedence
2755
+ const kubernetesPodName = resource.attributes[semanticConventions.SemanticResourceAttributes.K8S_POD_NAME];
2756
+ if (kubernetesPodName) {
2757
+ return String(kubernetesPodName);
2758
+ }
2759
+ // Service attributes
2760
+ const serviceInstanceId = resource.attributes[semanticConventions.SemanticResourceAttributes.SERVICE_INSTANCE_ID];
2761
+ if (serviceInstanceId) {
2762
+ return String(serviceInstanceId);
2763
+ }
2764
+ // Default
2765
+ return os__default["default"] && os__default["default"].hostname();
2721
2766
  }
2722
2767
  function isSqlDB(dbSystem) {
2723
2768
  return (dbSystem === semanticConventions.DbSystemValues.DB2 ||
@@ -2794,6 +2839,41 @@ function getDependencyTarget(attributes) {
2794
2839
  }
2795
2840
  return "";
2796
2841
  }
2842
+ function createResourceMetricEnvelope(resource, instrumentationKey) {
2843
+ if (resource && resource.attributes) {
2844
+ const tags = createTagsFromResource(resource);
2845
+ const resourceAttributes = {};
2846
+ for (const key of Object.keys(resource.attributes)) {
2847
+ // Avoid duplication ignoring fields already mapped.
2848
+ if (!(key.startsWith("_MS.") ||
2849
+ key == semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_VERSION ||
2850
+ key == semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE ||
2851
+ key == semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_NAME)) {
2852
+ resourceAttributes[key] = resource.attributes[key];
2853
+ }
2854
+ }
2855
+ // Only send event when resource attributes are available
2856
+ if (Object.keys(resourceAttributes).length > 0) {
2857
+ let envelope = {
2858
+ name: "_APPRESOURCEPREVIEW_",
2859
+ time: new Date(),
2860
+ sampleRate: 100,
2861
+ instrumentationKey: instrumentationKey,
2862
+ version: 1,
2863
+ data: {
2864
+ baseType: "MetricData",
2865
+ baseData: {
2866
+ version: 2,
2867
+ properties: resourceAttributes,
2868
+ },
2869
+ },
2870
+ tags: tags,
2871
+ };
2872
+ return envelope;
2873
+ }
2874
+ }
2875
+ return;
2876
+ }
2797
2877
 
2798
2878
  // Copyright (c) Microsoft Corporation.
2799
2879
  // Licensed under the MIT license.
@@ -2884,7 +2964,7 @@ function createTagsFromSpan(span) {
2884
2964
  }
2885
2965
  else if (httpUrl) {
2886
2966
  try {
2887
- let url$1 = new url.URL(String(httpUrl));
2967
+ const url$1 = new url.URL(String(httpUrl));
2888
2968
  tags[KnownContextTagKeys.AiOperationName] = `${httpMethod} ${url$1.pathname}`;
2889
2969
  }
2890
2970
  catch (ex) { }
@@ -2910,19 +2990,23 @@ function createPropertiesFromSpanAttributes(attributes) {
2910
2990
  const properties = {};
2911
2991
  if (attributes) {
2912
2992
  for (const key of Object.keys(attributes)) {
2913
- if (!(key.startsWith("http.") ||
2914
- key.startsWith("rpc.") ||
2915
- key.startsWith("db.") ||
2916
- key.startsWith("peer.") ||
2917
- key.startsWith("message.") ||
2918
- key.startsWith("messaging.") ||
2919
- key.startsWith("enduser.") ||
2920
- key.startsWith("net.") ||
2921
- key.startsWith("exception.") ||
2922
- key.startsWith("thread.") ||
2923
- key.startsWith("faas.") ||
2924
- key.startsWith("code.") ||
2925
- key.startsWith("_MS."))) {
2993
+ // Avoid duplication ignoring fields already mapped.
2994
+ if (!(key.startsWith("_MS.") ||
2995
+ key == semanticConventions.SemanticAttributes.NET_PEER_IP ||
2996
+ key == semanticConventions.SemanticAttributes.NET_PEER_NAME ||
2997
+ key == semanticConventions.SemanticAttributes.PEER_SERVICE ||
2998
+ key == semanticConventions.SemanticAttributes.HTTP_METHOD ||
2999
+ key == semanticConventions.SemanticAttributes.HTTP_URL ||
3000
+ key == semanticConventions.SemanticAttributes.HTTP_STATUS_CODE ||
3001
+ key == semanticConventions.SemanticAttributes.HTTP_ROUTE ||
3002
+ key == semanticConventions.SemanticAttributes.HTTP_HOST ||
3003
+ key == semanticConventions.SemanticAttributes.HTTP_URL ||
3004
+ key == semanticConventions.SemanticAttributes.DB_SYSTEM ||
3005
+ key == semanticConventions.SemanticAttributes.DB_STATEMENT ||
3006
+ key == semanticConventions.SemanticAttributes.DB_OPERATION ||
3007
+ key == semanticConventions.SemanticAttributes.DB_NAME ||
3008
+ key == semanticConventions.SemanticAttributes.RPC_SYSTEM ||
3009
+ key == semanticConventions.SemanticAttributes.RPC_GRPC_STATUS_CODE)) {
2926
3010
  properties[key] = attributes[key];
2927
3011
  }
2928
3012
  }
@@ -2965,7 +3049,7 @@ function createDependencyData(span) {
2965
3049
  const httpUrl = span.attributes[semanticConventions.SemanticAttributes.HTTP_URL];
2966
3050
  if (httpUrl) {
2967
3051
  try {
2968
- let dependencyUrl = new url.URL(String(httpUrl));
3052
+ const dependencyUrl = new url.URL(String(httpUrl));
2969
3053
  remoteDependencyData.name = `${httpMethod} ${dependencyUrl.pathname}`;
2970
3054
  }
2971
3055
  catch (ex) { }
@@ -2980,11 +3064,11 @@ function createDependencyData(span) {
2980
3064
  if (target) {
2981
3065
  try {
2982
3066
  // Remove default port
2983
- let portRegex = new RegExp(/(https?)(:\/\/.*)(:\d+)(\S*)/);
2984
- let res = portRegex.exec(target);
3067
+ const portRegex = new RegExp(/(https?)(:\/\/.*)(:\d+)(\S*)/);
3068
+ const res = portRegex.exec(target);
2985
3069
  if (res != null) {
2986
- let protocol = res[1];
2987
- let port = res[3];
3070
+ const protocol = res[1];
3071
+ const port = res[3];
2988
3072
  if ((protocol == "https" && port == ":443") || (protocol == "http" && port == ":80")) {
2989
3073
  // Drop port
2990
3074
  target = res[1] + res[2] + res[4];
@@ -3024,7 +3108,7 @@ function createDependencyData(span) {
3024
3108
  else if (dbOperation) {
3025
3109
  remoteDependencyData.data = String(dbOperation);
3026
3110
  }
3027
- let target = getDependencyTarget(span.attributes);
3111
+ const target = getDependencyTarget(span.attributes);
3028
3112
  const dbName = span.attributes[semanticConventions.SemanticAttributes.DB_NAME];
3029
3113
  if (target) {
3030
3114
  remoteDependencyData.target = dbName ? `${target}|${dbName}` : `${target}`;
@@ -3040,7 +3124,7 @@ function createDependencyData(span) {
3040
3124
  if (grpcStatusCode) {
3041
3125
  remoteDependencyData.resultCode = String(grpcStatusCode);
3042
3126
  }
3043
- let target = getDependencyTarget(span.attributes);
3127
+ const target = getDependencyTarget(span.attributes);
3044
3128
  if (target) {
3045
3129
  remoteDependencyData.target = `${target}`;
3046
3130
  }
@@ -3137,18 +3221,18 @@ function readableSpanToEnvelope(span, ikey) {
3137
3221
  * @internal
3138
3222
  */
3139
3223
  function spanEventsToEnvelopes(span, ikey) {
3140
- let envelopes = [];
3224
+ const envelopes = [];
3141
3225
  if (span.events) {
3142
3226
  span.events.forEach((event) => {
3143
3227
  var _a;
3144
3228
  let baseType;
3145
- let time = new Date(core.hrTimeToMilliseconds(event.time));
3229
+ const time = new Date(core.hrTimeToMilliseconds(event.time));
3146
3230
  let name = "";
3147
3231
  let baseData;
3148
3232
  const properties = createPropertiesFromSpanAttributes(event.attributes);
3149
- let tags = createTagsFromResource(span.resource);
3233
+ const tags = createTagsFromResource(span.resource);
3150
3234
  tags[KnownContextTagKeys.AiOperationId] = span.spanContext().traceId;
3151
- let spanId = (_a = span.spanContext()) === null || _a === void 0 ? void 0 : _a.spanId;
3235
+ const spanId = (_a = span.spanContext()) === null || _a === void 0 ? void 0 : _a.spanId;
3152
3236
  if (spanId) {
3153
3237
  tags[KnownContextTagKeys.AiOperationParentId] = spanId;
3154
3238
  }
@@ -3166,22 +3250,22 @@ function spanEventsToEnvelopes(span, ikey) {
3166
3250
  if (stack) {
3167
3251
  hasFullStack = true;
3168
3252
  }
3169
- let exceptionMsg = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE];
3253
+ const exceptionMsg = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE];
3170
3254
  if (exceptionMsg) {
3171
3255
  message = String(exceptionMsg);
3172
3256
  }
3173
- let escaped = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED];
3257
+ const escaped = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED];
3174
3258
  if (escaped != undefined) {
3175
3259
  properties[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED] = String(escaped);
3176
3260
  }
3177
3261
  }
3178
- let exceptionDetails = {
3262
+ const exceptionDetails = {
3179
3263
  typeName: typeName,
3180
3264
  message: message,
3181
3265
  stack: stack,
3182
3266
  hasFullStack: hasFullStack,
3183
3267
  };
3184
- let exceptionData = {
3268
+ const exceptionData = {
3185
3269
  exceptions: [exceptionDetails],
3186
3270
  version: 2,
3187
3271
  properties: properties,
@@ -3191,7 +3275,7 @@ function spanEventsToEnvelopes(span, ikey) {
3191
3275
  else {
3192
3276
  name = "Microsoft.ApplicationInsights.Message";
3193
3277
  baseType = "MessageData";
3194
- let messageData = {
3278
+ const messageData = {
3195
3279
  message: event.name,
3196
3280
  version: 2,
3197
3281
  properties: properties,
@@ -3202,7 +3286,7 @@ function spanEventsToEnvelopes(span, ikey) {
3202
3286
  if (span.attributes[AzureMonitorSampleRate]) {
3203
3287
  sampleRate = Number(span.attributes[AzureMonitorSampleRate]);
3204
3288
  }
3205
- let env = {
3289
+ const env = {
3206
3290
  name: name,
3207
3291
  time: time,
3208
3292
  instrumentationKey: ikey,
@@ -3249,15 +3333,23 @@ class AzureMonitorTraceExporter extends AzureMonitorBaseExporter {
3249
3333
  return;
3250
3334
  }
3251
3335
  api.diag.info(`Exporting ${spans.length} span(s). Converting to envelopes...`);
3252
- let envelopes = [];
3253
- spans.forEach((span) => {
3254
- envelopes.push(readableSpanToEnvelope(span, this._instrumentationKey));
3255
- let spanEventEnvelopes = spanEventsToEnvelopes(span, this._instrumentationKey);
3256
- if (spanEventEnvelopes.length > 0) {
3257
- envelopes.push(...spanEventEnvelopes);
3258
- }
3259
- });
3260
- resultCallback(await this._exportEnvelopes(envelopes));
3336
+ if (spans.length > 0) {
3337
+ let envelopes = [];
3338
+ const resourceMetricEnvelope = createResourceMetricEnvelope(spans[0].resource, this._instrumentationKey);
3339
+ if (resourceMetricEnvelope) {
3340
+ envelopes.push(resourceMetricEnvelope);
3341
+ }
3342
+ spans.forEach((span) => {
3343
+ envelopes.push(readableSpanToEnvelope(span, this._instrumentationKey));
3344
+ let spanEventEnvelopes = spanEventsToEnvelopes(span, this._instrumentationKey);
3345
+ if (spanEventEnvelopes.length > 0) {
3346
+ envelopes.push(...spanEventEnvelopes);
3347
+ }
3348
+ });
3349
+ resultCallback(await this._exportEnvelopes(envelopes));
3350
+ }
3351
+ // No data to export
3352
+ resultCallback({ code: core.ExportResultCode.SUCCESS });
3261
3353
  }
3262
3354
  /**
3263
3355
  * Shutdown AzureMonitorTraceExporter.
@@ -3297,20 +3389,13 @@ function resourceMetricsToEnvelope(metrics, ikey, isStatsbeat) {
3297
3389
  }
3298
3390
  metrics.scopeMetrics.forEach((scopeMetric) => {
3299
3391
  scopeMetric.metrics.forEach((metric) => {
3300
- var _a, _b;
3301
- const isStandardMetric = (_b = (_a = metric.descriptor) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.startsWith("azureMonitor.");
3302
3392
  metric.dataPoints.forEach((dataPoint) => {
3303
3393
  let baseData = {
3304
3394
  metrics: [],
3305
3395
  version: 2,
3306
3396
  properties: {},
3307
3397
  };
3308
- if (isStandardMetric) {
3309
- baseData.properties = createStandardMetricsProperties(metric.descriptor.name, dataPoint.attributes, tags);
3310
- }
3311
- else {
3312
- baseData.properties = createPropertiesFromMetricAttributes(dataPoint.attributes);
3313
- }
3398
+ baseData.properties = createPropertiesFromMetricAttributes(dataPoint.attributes);
3314
3399
  var metricDataPoint = {
3315
3400
  name: metric.descriptor.name,
3316
3401
  value: 0,
@@ -3346,37 +3431,6 @@ function resourceMetricsToEnvelope(metrics, ikey, isStatsbeat) {
3346
3431
  });
3347
3432
  return envelopes;
3348
3433
  }
3349
- function createStandardMetricsProperties(name, attributes, tags) {
3350
- const properties = {};
3351
- properties[PreAggregatedMetricPropertyNames.IsAutocollected] = "True";
3352
- properties[PreAggregatedMetricPropertyNames.cloudRoleInstance] =
3353
- tags[KnownContextTagKeys.AiCloudRoleInstance];
3354
- properties[PreAggregatedMetricPropertyNames.cloudRoleName] =
3355
- tags[KnownContextTagKeys.AiCloudRole];
3356
- if (name == StandardMetrics.HTTP_REQUEST_DURATION) {
3357
- properties[PreAggregatedMetricPropertyNames.metricId] = StandardMetricIds.REQUEST_DURATION;
3358
- let statusCode = String(attributes["http.status_code"]);
3359
- properties[PreAggregatedMetricPropertyNames.requestResultCode] = statusCode;
3360
- properties[PreAggregatedMetricPropertyNames.requestSuccess] =
3361
- statusCode == "200" ? "True" : "False";
3362
- }
3363
- else if (name == StandardMetrics.HTTP_DEPENDENCY_DURATION) {
3364
- properties[PreAggregatedMetricPropertyNames.metricId] = StandardMetricIds.DEPENDENCY_DURATION;
3365
- let statusCode = String(attributes["http.status_code"]);
3366
- properties[PreAggregatedMetricPropertyNames.dependencyTarget] = getDependencyTarget(attributes);
3367
- properties[PreAggregatedMetricPropertyNames.dependencyResultCode] = statusCode;
3368
- properties[PreAggregatedMetricPropertyNames.dependencyType] = "http";
3369
- properties[PreAggregatedMetricPropertyNames.dependencySuccess] =
3370
- statusCode == "200" ? "True" : "False";
3371
- }
3372
- else if (name == StandardMetrics.TRACE_COUNT) {
3373
- properties[PreAggregatedMetricPropertyNames.metricId] = StandardMetricIds.TRACE_COUNT;
3374
- }
3375
- else if (name == StandardMetrics.EXCEPTION_COUNT) {
3376
- properties[PreAggregatedMetricPropertyNames.metricId] = StandardMetricIds.EXCEPTION_COUNT;
3377
- }
3378
- return properties;
3379
- }
3380
3434
 
3381
3435
  // Copyright (c) Microsoft Corporation.
3382
3436
  /**
@@ -3436,6 +3490,224 @@ class AzureMonitorMetricExporter extends AzureMonitorBaseExporter {
3436
3490
  }
3437
3491
  }
3438
3492
 
3493
+ // Copyright (c) Microsoft Corporation.
3494
+ /**
3495
+ * Log to Azure envelope parsing.
3496
+ * @internal
3497
+ */
3498
+ function logToEnvelope(log, ikey) {
3499
+ const time = log.hrTime ? new Date(core.hrTimeToMilliseconds(log.hrTime)) : new Date();
3500
+ let sampleRate = 100;
3501
+ const instrumentationKey = ikey;
3502
+ const tags = createTagsFromLog(log);
3503
+ const [properties, measurements] = createPropertiesFromLog(log);
3504
+ let name;
3505
+ let baseType;
3506
+ let baseData;
3507
+ if (!log.attributes[ApplicationInsightsBaseType]) {
3508
+ // Get Exception attributes if available
3509
+ let exceptionType = log.attributes[semanticConventions.SemanticAttributes.EXCEPTION_TYPE];
3510
+ if (exceptionType) {
3511
+ let exceptionMessage = log.attributes[semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE];
3512
+ let exceptionStacktrace = log.attributes[semanticConventions.SemanticAttributes.EXCEPTION_STACKTRACE];
3513
+ name = ApplicationInsightsExceptionName;
3514
+ baseType = ApplicationInsightsExceptionBaseType;
3515
+ let exceptionDetails = {
3516
+ typeName: String(exceptionType),
3517
+ message: String(exceptionMessage),
3518
+ hasFullStack: exceptionStacktrace ? true : false,
3519
+ stack: String(exceptionStacktrace),
3520
+ };
3521
+ const exceptionData = {
3522
+ exceptions: [exceptionDetails],
3523
+ severityLevel: String(getSeverity(log.severityNumber)),
3524
+ version: 2,
3525
+ };
3526
+ baseData = exceptionData;
3527
+ }
3528
+ else {
3529
+ name = ApplicationInsightsMessageName;
3530
+ baseType = ApplicationInsightsMessageBaseType;
3531
+ const messageData = {
3532
+ message: String(log.body),
3533
+ severityLevel: String(getSeverity(log.severityNumber)),
3534
+ version: 2,
3535
+ };
3536
+ baseData = messageData;
3537
+ }
3538
+ }
3539
+ else {
3540
+ // If Legacy Application Insights Log
3541
+ baseType = String(log.attributes[ApplicationInsightsBaseType]);
3542
+ name = getLegacyApplicationInsightsName(log);
3543
+ baseData = getLegacyApplicationInsightsBaseData(log);
3544
+ if (!baseData) {
3545
+ // Failed to parse log
3546
+ return;
3547
+ }
3548
+ }
3549
+ return {
3550
+ name,
3551
+ sampleRate,
3552
+ time,
3553
+ instrumentationKey,
3554
+ tags,
3555
+ version: 1,
3556
+ data: {
3557
+ baseType,
3558
+ baseData: Object.assign(Object.assign({}, baseData), { properties,
3559
+ measurements }),
3560
+ },
3561
+ };
3562
+ }
3563
+ function createTagsFromLog(log) {
3564
+ var _a, _b;
3565
+ const tags = createTagsFromResource(log.resource);
3566
+ if ((_a = log.spanContext) === null || _a === void 0 ? void 0 : _a.traceId) {
3567
+ tags[KnownContextTagKeys.AiOperationId] = log.spanContext.traceId;
3568
+ }
3569
+ if ((_b = log.spanContext) === null || _b === void 0 ? void 0 : _b.spanId) {
3570
+ tags[KnownContextTagKeys.AiOperationParentId] = log.spanContext.spanId;
3571
+ }
3572
+ return tags;
3573
+ }
3574
+ function createPropertiesFromLog(log) {
3575
+ const measurements = {};
3576
+ const properties = {};
3577
+ if (log.attributes) {
3578
+ for (const key of Object.keys(log.attributes)) {
3579
+ // Avoid duplication ignoring fields already mapped.
3580
+ if (!(key.startsWith("_MS.") ||
3581
+ key == semanticConventions.SemanticAttributes.EXCEPTION_TYPE ||
3582
+ key == semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE ||
3583
+ key == semanticConventions.SemanticAttributes.EXCEPTION_STACKTRACE)) {
3584
+ properties[key] = log.attributes[key];
3585
+ }
3586
+ }
3587
+ }
3588
+ return [properties, measurements];
3589
+ }
3590
+ // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber
3591
+ function getSeverity(severityNumber) {
3592
+ if (severityNumber) {
3593
+ if (severityNumber > 0 && severityNumber < 9) {
3594
+ return KnownSeverityLevel.Verbose;
3595
+ }
3596
+ else if (severityNumber >= 9 && severityNumber < 13) {
3597
+ return KnownSeverityLevel.Information;
3598
+ }
3599
+ else if (severityNumber >= 13 && severityNumber < 17) {
3600
+ return KnownSeverityLevel.Warning;
3601
+ }
3602
+ else if (severityNumber >= 17 && severityNumber < 21) {
3603
+ return KnownSeverityLevel.Error;
3604
+ }
3605
+ else if (severityNumber >= 21 && severityNumber < 25) {
3606
+ return KnownSeverityLevel.Critical;
3607
+ }
3608
+ }
3609
+ return;
3610
+ }
3611
+ function getLegacyApplicationInsightsName(log) {
3612
+ let name = "";
3613
+ switch (log.attributes[ApplicationInsightsBaseType]) {
3614
+ case ApplicationInsightsAvailabilityBaseType:
3615
+ name = ApplicationInsightsAvailabilityName;
3616
+ break;
3617
+ case ApplicationInsightsExceptionBaseType:
3618
+ name = ApplicationInsightsExceptionName;
3619
+ break;
3620
+ case ApplicationInsightsMessageBaseType:
3621
+ name = ApplicationInsightsMessageName;
3622
+ break;
3623
+ case ApplicationInsightsPageViewBaseType:
3624
+ name = ApplicationInsightsPageViewName;
3625
+ break;
3626
+ case ApplicationInsightsEventBaseType:
3627
+ name = ApplicationInsightsEventName;
3628
+ break;
3629
+ }
3630
+ return name;
3631
+ }
3632
+ function getLegacyApplicationInsightsBaseData(log) {
3633
+ let baseData = {
3634
+ version: 2,
3635
+ };
3636
+ if (log.body) {
3637
+ try {
3638
+ switch (log.attributes[ApplicationInsightsBaseType]) {
3639
+ case ApplicationInsightsAvailabilityBaseType:
3640
+ baseData = JSON.parse(log.body);
3641
+ break;
3642
+ case ApplicationInsightsExceptionBaseType:
3643
+ baseData = JSON.parse(log.body);
3644
+ break;
3645
+ case ApplicationInsightsMessageBaseType:
3646
+ baseData = JSON.parse(log.body);
3647
+ break;
3648
+ case ApplicationInsightsPageViewBaseType:
3649
+ baseData = JSON.parse(log.body);
3650
+ break;
3651
+ case ApplicationInsightsEventBaseType:
3652
+ baseData = JSON.parse(log.body);
3653
+ break;
3654
+ }
3655
+ }
3656
+ catch (err) {
3657
+ api.diag.error("AzureMonitorLogExporter failed to parse Application Insights Telemetry");
3658
+ }
3659
+ }
3660
+ return baseData;
3661
+ }
3662
+
3663
+ // Copyright (c) Microsoft Corporation.
3664
+ /**
3665
+ * Azure Monitor OpenTelemetry Log Exporter.
3666
+ */
3667
+ class AzureMonitorLogExporter extends AzureMonitorBaseExporter {
3668
+ /**
3669
+ * Initializes a new instance of the AzureMonitorLogExporter class.
3670
+ * @param AzureExporterConfig - Exporter configuration.
3671
+ */
3672
+ constructor(options = {}) {
3673
+ super(options);
3674
+ /**
3675
+ * Flag to determine if Exporter is shutdown.
3676
+ */
3677
+ this._isShutdown = false;
3678
+ api.diag.debug("AzureMonitorLogExporter was successfully setup");
3679
+ }
3680
+ /**
3681
+ * Export OpenTelemetry logs.
3682
+ * @param logs - Logs to export.
3683
+ * @param resultCallback - Result callback.
3684
+ */
3685
+ async export(logs, resultCallback) {
3686
+ if (this._isShutdown) {
3687
+ api.diag.info("Exporter shut down. Failed to export spans.");
3688
+ setTimeout(() => resultCallback({ code: core.ExportResultCode.FAILED }), 0);
3689
+ return;
3690
+ }
3691
+ api.diag.info(`Exporting ${logs.length} logs(s). Converting to envelopes...`);
3692
+ let envelopes = [];
3693
+ logs.forEach((log) => {
3694
+ let envelope = logToEnvelope(log, this._instrumentationKey);
3695
+ if (envelope) {
3696
+ envelopes.push(envelope);
3697
+ }
3698
+ });
3699
+ resultCallback(await this._exportEnvelopes(envelopes));
3700
+ }
3701
+ /**
3702
+ * Shutdown AzureMonitorLogExporter.
3703
+ */
3704
+ async shutdown() {
3705
+ this._isShutdown = true;
3706
+ api.diag.info("AzureMonitorLogExporter shutting down");
3707
+ return this._shutdown();
3708
+ }
3709
+ }
3710
+
3439
3711
  // Copyright (c) Microsoft Corporation.
3440
3712
  /**
3441
3713
  * Azure Monitor Statsbeat Exporter
@@ -3484,6 +3756,7 @@ class AzureMonitorStatsbeatExporter extends AzureMonitorBaseExporter {
3484
3756
 
3485
3757
  exports.ApplicationInsightsSampler = ApplicationInsightsSampler;
3486
3758
  exports.AzureMonitorBaseExporter = AzureMonitorBaseExporter;
3759
+ exports.AzureMonitorLogExporter = AzureMonitorLogExporter;
3487
3760
  exports.AzureMonitorMetricExporter = AzureMonitorMetricExporter;
3488
3761
  exports.AzureMonitorStatsbeatExporter = AzureMonitorStatsbeatExporter;
3489
3762
  exports.AzureMonitorTraceExporter = AzureMonitorTraceExporter;