@azure/monitor-opentelemetry
Version:
Azure Monitor OpenTelemetry (Node.js)
706 lines • 35 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LiveMetrics = void 0;
const tslib_1 = require("tslib");
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
const os = tslib_1.__importStar(require("node:os"));
const sdk_metrics_1 = require("@opentelemetry/sdk-metrics");
const api_1 = require("@opentelemetry/api");
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
const index_js_1 = require("../../generated/index.js");
const utils_js_1 = require("./utils.js");
const exporter_js_1 = require("./export/exporter.js");
const sender_js_1 = require("./export/sender.js");
const connectionStringParser_js_1 = require("../../utils/connectionStringParser.js");
const types_js_1 = require("../../types.js");
const types_js_2 = require("./types.js");
const core_1 = require("@opentelemetry/core");
const statsbeat_js_1 = require("../../utils/statsbeat.js");
const filter_js_1 = require("./filtering/filter.js");
const validator_js_1 = require("./filtering/validator.js");
const collectionConfigurationErrorTracker_js_1 = require("./filtering/collectionConfigurationErrorTracker.js");
const projection_js_1 = require("./filtering/projection.js");
const quickpulseErrors_js_1 = require("./filtering/quickpulseErrors.js");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const utils_js_2 = require("../utils.js");
const utils_js_3 = require("../utils.js");
const logger_js_1 = require("../../shared/logging/logger.js");
const POST_INTERVAL = 1000;
const MAX_POST_WAIT_TIME = 20000;
const PING_INTERVAL = 5000;
const MAX_PING_WAIT_TIME = 60000;
const FALLBACK_INTERVAL = 60000;
/**
* Azure Monitor Live Metrics
* @internal
*/
class LiveMetrics {
/**
* Initializes a new instance of the StandardMetrics class.
* @param config - Distro configuration.
* @param options - Standard Metrics options.
*/
constructor(config) {
this.documents = [];
this.lastSuccessTime = Date.now();
this.totalRequestCount = 0;
this.totalFailedRequestCount = 0;
this.totalDependencyCount = 0;
this.totalFailedDependencyCount = 0;
this.totalExceptionCount = 0;
this.requestDuration = 0;
this.dependencyDuration = 0;
this.lastRequestDuration = {
count: 0,
duration: 0,
time: 0,
};
this.lastRequestRate = { count: 0, time: 0 };
this.lastFailedRequestRate = { count: 0, time: 0 };
this.lastDependencyDuration = {
count: 0,
duration: 0,
time: 0,
};
this.lastDependencyRate = { count: 0, time: 0 };
this.lastFailedDependencyRate = { count: 0, time: 0 };
this.lastExceptionRate = { count: 0, time: 0 };
this.statsbeatOptionsUpdated = false;
this.etag = "";
this.errorTracker = new collectionConfigurationErrorTracker_js_1.CollectionConfigurationErrorTracker();
// For tracking of duplicate metric ids in the same configuration.
this.seenMetricIds = new Set();
this.validDerivedMetrics = new Map();
this.derivedMetricProjection = new projection_js_1.Projection();
this.validator = new validator_js_1.Validator();
this.filter = new filter_js_1.Filter();
// type: Map<telemetryType, Map<id, FilterConjunctionGroupInfo[]>>
this.validDocumentFilterConjuctionGroupInfos = new Map();
this.config = config;
const idGenerator = new sdk_trace_base_1.RandomIdGenerator();
const streamId = idGenerator.generateTraceId();
const machineName = os.hostname();
const instance = (0, utils_js_3.getCloudRoleInstance)(this.config.resource);
const roleName = (0, utils_js_3.getCloudRole)(this.config.resource);
const version = (0, utils_js_1.getSdkVersion)();
this.baseMonitoringDataPoint = {
version: version,
invariantVersion: 5, // 5 means we support live metrics filtering of metrics and documents
instance: instance,
roleName: roleName,
machineName: machineName,
streamId: streamId,
performanceCollectionSupported: true,
isWebApp: process.env["WEBSITE_SITE_NAME"] ? true : false,
};
const parsedConnectionString = connectionStringParser_js_1.ConnectionStringParser.parse(this.config.azureMonitorExporterOptions.connectionString ||
process.env["APPLICATIONINSIGHTS_CONNECTION_STRING"]);
this.pingSender = new sender_js_1.QuickpulseSender({
endpointUrl: parsedConnectionString.liveendpoint || types_js_1.DEFAULT_LIVEMETRICS_ENDPOINT,
instrumentationKey: parsedConnectionString.instrumentationkey || "",
credential: this.config.azureMonitorExporterOptions.credential,
credentialScopes: parsedConnectionString.aadaudience ||
this.config.azureMonitorExporterOptions.credentialScopes,
});
const exporterOptions = {
endpointUrl: parsedConnectionString.liveendpoint || types_js_1.DEFAULT_LIVEMETRICS_ENDPOINT,
instrumentationKey: parsedConnectionString.instrumentationkey || "",
credential: this.config.azureMonitorExporterOptions.credential,
credentialScopes: parsedConnectionString.aadaudience ||
this.config.azureMonitorExporterOptions.credentialScopes,
// eslint-disable-next-line @typescript-eslint/no-misused-promises
postCallback: this.quickPulseDone.bind(this),
getDocumentsFn: this.getDocuments.bind(this),
getErrorsFn: this.getErrors.bind(this),
getDerivedMetricValuesFn: this.getDerivedMetricValues.bind(this),
baseMonitoringDataPoint: this.baseMonitoringDataPoint,
};
this.quickpulseExporter = new exporter_js_1.QuickpulseMetricExporter(exporterOptions);
this.isCollectingData = false;
this.pingInterval = PING_INTERVAL; // Default
this.postInterval = POST_INTERVAL;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.handle = setTimeout(this.goQuickpulse.bind(this), this.pingInterval);
this.handle.unref(); // Don't block apps from terminating
this.lastCpuUsage = process.cpuUsage();
this.lastHrTime = process.hrtime.bigint();
}
shutdown() {
var _a;
(_a = this.meterProvider) === null || _a === void 0 ? void 0 : _a.shutdown();
}
async goQuickpulse() {
if (!this.isCollectingData) {
// If not collecting, Ping
try {
const params = {
transmissionTime: (0, utils_js_1.getTransmissionTime)(),
monitoringDataPoint: this.baseMonitoringDataPoint,
configurationEtag: this.etag,
};
await api_1.context.with((0, core_1.suppressTracing)(api_1.context.active()), async () => {
const response = await this.pingSender.isSubscribed(params);
this.quickPulseDone(response);
});
}
catch (error) {
this.quickPulseDone(undefined);
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.handle = setTimeout(this.goQuickpulse.bind(this), this.pingInterval);
this.handle.unref();
}
if (this.isCollectingData) {
this.activateMetrics({ collectionInterval: this.postInterval });
}
}
// eslint-disable-next-line @typescript-eslint/require-await
async quickPulseDone(response) {
if (!response) {
if (!this.isCollectingData) {
if (Date.now() - this.lastSuccessTime >= MAX_PING_WAIT_TIME) {
this.pingInterval = FALLBACK_INTERVAL;
}
}
else {
if (Date.now() - this.lastSuccessTime >= MAX_POST_WAIT_TIME) {
this.postInterval = FALLBACK_INTERVAL;
this.deactivateMetrics();
this.activateMetrics({ collectionInterval: this.postInterval });
}
}
}
else {
this.postInterval = POST_INTERVAL;
// Update using response if needed
this.lastSuccessTime = Date.now();
this.isCollectingData =
response.xMsQpsSubscribed && response.xMsQpsSubscribed === "true" ? true : false;
if (response.xMsQpsConfigurationEtag && this.etag !== response.xMsQpsConfigurationEtag) {
this.updateConfiguration(response);
}
// If collecting was stoped
if (!this.isCollectingData && this.meterProvider) {
this.etag = "";
this.deactivateMetrics();
// eslint-disable-next-line @typescript-eslint/no-misused-promises
this.handle = setTimeout(this.goQuickpulse.bind(this), this.pingInterval);
this.handle.unref();
}
const endpointRedirect = response.xMsQpsServiceEndpointRedirectV2;
if (endpointRedirect) {
this.pingSender.handlePermanentRedirect(endpointRedirect);
this.quickpulseExporter.getSender().handlePermanentRedirect(endpointRedirect);
}
const pollingInterval = response.xMsQpsServicePollingIntervalHint;
if (pollingInterval) {
this.pingInterval = Number(pollingInterval);
}
else {
this.pingInterval = PING_INTERVAL;
}
}
}
// Activate live metrics collection
activateMetrics(options) {
if (this.meterProvider) {
return;
}
// Turn on live metrics active collection for statsbeat
if (!this.statsbeatOptionsUpdated) {
(0, statsbeat_js_1.getInstance)().setStatsbeatFeatures({}, { liveMetrics: true });
this.statsbeatOptionsUpdated = true;
}
this.totalDependencyCount = 0;
this.totalExceptionCount = 0;
this.totalFailedDependencyCount = 0;
this.totalFailedRequestCount = 0;
this.totalRequestCount = 0;
this.requestDuration = 0;
this.dependencyDuration = 0;
this.lastRequestDuration = { count: 0, duration: 0, time: 0 };
this.lastRequestRate = { count: 0, time: 0 };
this.lastFailedRequestRate = { count: 0, time: 0 };
this.lastDependencyDuration = { count: 0, duration: 0, time: 0 };
this.lastDependencyRate = { count: 0, time: 0 };
this.lastFailedDependencyRate = { count: 0, time: 0 };
this.lastExceptionRate = { count: 0, time: 0 };
const metricReaderOptions = {
exporter: this.quickpulseExporter,
exportIntervalMillis: options === null || options === void 0 ? void 0 : options.collectionInterval,
};
this.metricReader = new sdk_metrics_1.PeriodicExportingMetricReader(metricReaderOptions);
const meterProviderConfig = {
resource: this.config.resource,
readers: [this.metricReader],
};
this.meterProvider = new sdk_metrics_1.MeterProvider(meterProviderConfig);
this.meter = this.meterProvider.getMeter("AzureMonitorLiveMetricsMeter");
this.requestDurationGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.REQUEST_DURATION, {
valueType: api_1.ValueType.DOUBLE,
});
this.requestRateGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.REQUEST_RATE, {
valueType: api_1.ValueType.DOUBLE,
});
this.requestFailedRateGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.REQUEST_FAILURE_RATE, {
valueType: api_1.ValueType.DOUBLE,
});
this.dependencyDurationGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.DEPENDENCY_DURATION, {
valueType: api_1.ValueType.DOUBLE,
});
this.dependencyRateGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.DEPENDENCY_RATE, {
valueType: api_1.ValueType.DOUBLE,
});
this.dependencyFailedRateGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.DEPENDENCY_FAILURE_RATE, {
valueType: api_1.ValueType.DOUBLE,
});
this.processPhysicalBytesGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.PHYSICAL_BYTES, {
valueType: api_1.ValueType.INT,
});
this.percentProcessorTimeNormalizedGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.PROCESSOR_TIME_NORMALIZED, {
valueType: api_1.ValueType.DOUBLE,
});
this.exceptionsRateGauge = this.meter.createObservableGauge(types_js_2.QuickPulseOpenTelemetryMetricNames.EXCEPTION_RATE, {
valueType: api_1.ValueType.DOUBLE,
});
this.requestDurationGauge.addCallback(this.getRequestDuration.bind(this));
this.requestRateGauge.addCallback(this.getRequestRate.bind(this));
this.requestFailedRateGauge.addCallback(this.getRequestFailedRate.bind(this));
this.dependencyDurationGauge.addCallback(this.getDependencyDuration.bind(this));
this.dependencyRateGauge.addCallback(this.getDependencyRate.bind(this));
this.dependencyFailedRateGauge.addCallback(this.getDependencyFailedRate.bind(this));
this.exceptionsRateGauge.addCallback(this.getExceptionRate.bind(this));
this.processPhysicalBytesGauge.addCallback(this.getPhysicalMemory.bind(this));
this.percentProcessorTimeNormalizedGauge.addCallback(this.getProcessorTimeNormalized.bind(this));
}
/**
* Deactivate metric collection
*/
deactivateMetrics() {
var _a;
this.documents = [];
this.validDocumentFilterConjuctionGroupInfos.clear();
this.errorTracker.clearRunTimeErrors();
this.errorTracker.clearValidationTimeErrors();
this.validDerivedMetrics.clear();
this.derivedMetricProjection.clearProjectionMaps();
this.seenMetricIds.clear();
(_a = this.meterProvider) === null || _a === void 0 ? void 0 : _a.shutdown();
this.meterProvider = undefined;
}
/**
* Force flush Meter Provider.
*/
async flush() {
var _a;
await ((_a = this.meterProvider) === null || _a === void 0 ? void 0 : _a.forceFlush());
}
/**
*Get OpenTelemetry MeterProvider
*/
getMeterProvider() {
return this.meterProvider;
}
getDocuments() {
const result = this.documents;
this.documents = [];
return result;
}
getErrors() {
const result = this.errorTracker.getErrors();
this.errorTracker.clearRunTimeErrors();
return result;
}
getDerivedMetricValues() {
return this.derivedMetricProjection.getMetricValues();
}
addDocument(document) {
if (document) {
// Limit risk of memory leak by limiting doc length to something manageable
if (this.documents.length > 20) {
this.documents.shift(); // Remove oldest document
}
this.documents.push(document);
}
}
/**
* Record Span metrics
* @internal
*/
recordSpan(span) {
if (this.isCollectingData) {
const columns = (0, utils_js_1.getSpanData)(span);
let documentConfiguration;
let derivedMetricInfos;
if ((0, utils_js_1.isRequestData)(columns)) {
documentConfiguration =
this.validDocumentFilterConjuctionGroupInfos.get(index_js_1.KnownTelemetryType.Request) ||
new Map();
derivedMetricInfos = this.validDerivedMetrics.get(index_js_1.KnownTelemetryType.Request) || [];
}
else {
documentConfiguration =
this.validDocumentFilterConjuctionGroupInfos.get(index_js_1.KnownTelemetryType.Dependency) ||
new Map();
derivedMetricInfos = this.validDerivedMetrics.get(index_js_1.KnownTelemetryType.Dependency) || [];
}
this.applyDocumentFilters(documentConfiguration, columns);
this.checkMetricFilterAndCreateProjection(derivedMetricInfos, columns);
const durationMs = (0, core_1.hrTimeToMilliseconds)(span.duration);
const success = span.status.code !== api_1.SpanStatusCode.ERROR;
if (span.kind === api_1.SpanKind.SERVER || span.kind === api_1.SpanKind.CONSUMER) {
this.totalRequestCount++;
this.requestDuration += durationMs;
if (!success) {
this.totalFailedRequestCount++;
}
}
else {
this.totalDependencyCount++;
this.dependencyDuration += durationMs;
if (!success) {
this.totalFailedDependencyCount++;
}
}
if (span.events) {
span.events.forEach((event) => {
event.attributes = event.attributes || {};
if (event.name === "exception") {
const exceptionColumns = (0, utils_js_1.getSpanExceptionColumns)(event.attributes, span.attributes);
documentConfiguration =
this.validDocumentFilterConjuctionGroupInfos.get(index_js_1.KnownTelemetryType.Exception) ||
new Map();
this.applyDocumentFilters(documentConfiguration, exceptionColumns, event.attributes[semantic_conventions_1.SEMATTRS_EXCEPTION_TYPE]);
derivedMetricInfos = this.validDerivedMetrics.get(index_js_1.KnownTelemetryType.Exception) || [];
this.checkMetricFilterAndCreateProjection(derivedMetricInfos, exceptionColumns);
this.totalExceptionCount++;
}
});
}
}
}
/**
* Record LogRecord metrics, add attribute so data is not aggregated again in ingestion
* @internal
*/
recordLog(logRecord) {
if (this.isCollectingData) {
const columns = (0, utils_js_1.getLogData)(logRecord);
let derivedMetricInfos;
let documentConfiguration;
if ((0, utils_js_1.isExceptionData)(columns)) {
documentConfiguration =
this.validDocumentFilterConjuctionGroupInfos.get(index_js_1.KnownTelemetryType.Exception) ||
new Map();
this.applyDocumentFilters(documentConfiguration, columns, logRecord.attributes[semantic_conventions_1.SEMATTRS_EXCEPTION_TYPE]);
derivedMetricInfos = this.validDerivedMetrics.get(index_js_1.KnownTelemetryType.Exception) || [];
this.totalExceptionCount++;
}
else {
// trace
documentConfiguration =
this.validDocumentFilterConjuctionGroupInfos.get(index_js_1.KnownTelemetryType.Trace) ||
new Map();
this.applyDocumentFilters(documentConfiguration, columns);
derivedMetricInfos = this.validDerivedMetrics.get(index_js_1.KnownTelemetryType.Trace) || [];
}
this.checkMetricFilterAndCreateProjection(derivedMetricInfos, columns);
}
}
getRequestDuration(observableResult) {
const currentTime = +new Date();
const requestInterval = this.totalRequestCount - this.lastRequestDuration.count || 0;
const durationInterval = this.requestDuration - this.lastRequestDuration.duration || 0;
const elapsedMs = currentTime - this.lastRequestDuration.time;
if (elapsedMs > 0) {
const averageExecutionTime = durationInterval / requestInterval || 0; // default to 0 in case no requests in this interval
observableResult.observe(averageExecutionTime);
}
this.lastRequestDuration = {
count: this.totalRequestCount,
duration: this.requestDuration,
time: currentTime,
};
}
getRequestRate(observableResult) {
const currentTime = +new Date();
const intervalRequests = this.totalRequestCount - this.lastRequestRate.count || 0;
const elapsedMs = currentTime - this.lastRequestRate.time;
if (elapsedMs > 0) {
const elapsedSeconds = elapsedMs / 1000;
const dataPerSec = intervalRequests / elapsedSeconds;
observableResult.observe(dataPerSec);
}
this.lastRequestRate = {
count: this.totalRequestCount,
time: currentTime,
};
}
getRequestFailedRate(observableResult) {
const currentTime = +new Date();
const intervalRequests = this.totalFailedRequestCount - this.lastFailedRequestRate.count || 0;
const elapsedMs = currentTime - this.lastFailedRequestRate.time;
if (elapsedMs > 0) {
const elapsedSeconds = elapsedMs / 1000;
const dataPerSec = intervalRequests / elapsedSeconds;
observableResult.observe(dataPerSec);
}
this.lastFailedRequestRate = {
count: this.totalFailedRequestCount,
time: currentTime,
};
}
getDependencyDuration(observableResult) {
const currentTime = +new Date();
const dependencyInterval = this.totalDependencyCount - this.lastDependencyDuration.count || 0;
const durationInterval = this.dependencyDuration - this.lastDependencyDuration.duration || 0;
const elapsedMs = currentTime - this.lastDependencyDuration.time;
if (elapsedMs > 0) {
const averageExecutionTime = durationInterval / dependencyInterval || 0; // default to 0 in case no dependencies in this interval
observableResult.observe(averageExecutionTime);
}
this.lastDependencyDuration = {
count: this.totalDependencyCount,
duration: this.dependencyDuration,
time: currentTime,
};
}
getDependencyRate(observableResult) {
const currentTime = +new Date();
const intervalData = this.totalDependencyCount - this.lastDependencyRate.count || 0;
const elapsedMs = currentTime - this.lastDependencyRate.time;
if (elapsedMs > 0) {
const elapsedSeconds = elapsedMs / 1000;
const dataPerSec = intervalData / elapsedSeconds;
observableResult.observe(dataPerSec);
}
this.lastDependencyRate = {
count: this.totalDependencyCount,
time: currentTime,
};
}
getDependencyFailedRate(observableResult) {
const currentTime = +new Date();
const intervalData = this.totalFailedDependencyCount - this.lastFailedDependencyRate.count || 0;
const elapsedMs = currentTime - this.lastFailedDependencyRate.time;
if (elapsedMs > 0) {
const elapsedSeconds = elapsedMs / 1000;
const dataPerSec = intervalData / elapsedSeconds;
observableResult.observe(dataPerSec);
}
this.lastFailedDependencyRate = {
count: this.totalFailedDependencyCount,
time: currentTime,
};
}
getExceptionRate(observableResult) {
const currentTime = +new Date();
const intervalData = this.totalExceptionCount - this.lastExceptionRate.count || 0;
const elapsedMs = currentTime - this.lastExceptionRate.time;
if (elapsedMs > 0) {
const elapsedSeconds = elapsedMs / 1000;
const dataPerSec = intervalData / elapsedSeconds;
observableResult.observe(dataPerSec);
}
this.lastExceptionRate = {
count: this.totalExceptionCount,
time: currentTime,
};
}
getPhysicalMemory(observableResult) {
const rss = (0, utils_js_2.getPhysicalMemory)();
observableResult.observe(rss);
}
getProcessorTimeNormalized(observableResult) {
if (process && process.hrtime) {
const cpuUsagePercent = (0, utils_js_2.getProcessorTimeNormalized)(this.lastHrTime, this.lastCpuUsage);
observableResult.observe(cpuUsagePercent);
this.lastHrTime = process.hrtime.bigint();
this.lastCpuUsage = process.cpuUsage();
}
else {
logger_js_1.Logger.getInstance().debug("Getting Normalized Processor Time Failed. No process available.");
}
}
updateConfiguration(response) {
this.etag = response.xMsQpsConfigurationEtag || "";
this.quickpulseExporter.setEtag(this.etag);
this.errorTracker.clearValidationTimeErrors();
this.validDocumentFilterConjuctionGroupInfos.clear();
this.validDerivedMetrics.clear();
this.derivedMetricProjection.clearProjectionMaps();
this.seenMetricIds.clear();
this.parseDocumentFilterConfiguration(response);
this.parseMetricFilterConfiguration(response);
}
parseDocumentFilterConfiguration(response) {
if (!(response === null || response === void 0 ? void 0 : response.documentStreams) || typeof response.documentStreams.forEach !== "function") {
return;
}
response.documentStreams.forEach((documentStreamInfo) => {
documentStreamInfo.documentFilterGroups.forEach((documentFilterGroupInfo) => {
var _a;
try {
this.validator.validateTelemetryType(documentFilterGroupInfo.telemetryType);
this.validator.validateDocumentFilters(documentFilterGroupInfo);
this.filter.renameExceptionFieldNamesForFiltering(documentFilterGroupInfo.filters);
if (!this.validDocumentFilterConjuctionGroupInfos.has(documentFilterGroupInfo.telemetryType)) {
this.validDocumentFilterConjuctionGroupInfos.set(documentFilterGroupInfo.telemetryType, new Map());
}
const innerMap = this.validDocumentFilterConjuctionGroupInfos.get(documentFilterGroupInfo.telemetryType);
if (!(innerMap === null || innerMap === void 0 ? void 0 : innerMap.has(documentStreamInfo.id))) {
innerMap === null || innerMap === void 0 ? void 0 : innerMap.set(documentStreamInfo.id, [documentFilterGroupInfo.filters]);
}
else {
(_a = innerMap.get(documentStreamInfo.id)) === null || _a === void 0 ? void 0 : _a.push(documentFilterGroupInfo.filters);
}
}
catch (error) {
const configError = {
collectionConfigurationErrorType: "",
message: "",
fullException: "",
data: [],
};
if (error instanceof quickpulseErrors_js_1.TelemetryTypeError) {
configError.collectionConfigurationErrorType = "DocumentTelemetryTypeUnsupported";
}
else if (error instanceof quickpulseErrors_js_1.UnexpectedFilterCreateError) {
configError.collectionConfigurationErrorType =
index_js_1.KnownCollectionConfigurationErrorType.DocumentStreamFailureToCreateFilterUnexpected;
}
if (error instanceof Error) {
configError.message = error.message;
configError.fullException = error.stack || "";
}
const data = [];
data.push({ key: "DocumentStreamInfoId", value: documentStreamInfo.id });
data.push({ key: "ETag", value: this.etag });
configError.data = data;
this.errorTracker.addValidationError(configError);
}
});
});
}
applyDocumentFilters(documentConfiguration, data, exceptionType) {
const streamIds = new Set();
documentConfiguration.forEach((filterConjunctionGroupInfoList, streamId) => {
filterConjunctionGroupInfoList.forEach((filterConjunctionGroupInfo) => {
// by going though each filterConjuctionGroupInfo, we are implicitly -OR-ing
// different filterConjunctionGroupInfo within documentStreamInfo. If there are multiple
// documentStreamInfos, this logic will -OR- the filtering results of each documentStreamInfo.
if (this.filter.checkFilterConjunctionGroup(filterConjunctionGroupInfo, data)) {
streamIds.add(streamId);
}
});
});
// Emit a document when a telemetry data matches a particular filtering configuration,
// or when filtering configuration is empty.
if (streamIds.size > 0 || documentConfiguration.size === 0) {
let document;
if ((0, utils_js_1.isRequestData)(data) || (0, utils_js_1.isDependencyData)(data)) {
document = (0, utils_js_1.getSpanDocument)(data);
}
else if ((0, utils_js_1.isExceptionData)(data) && exceptionType) {
document = (0, utils_js_1.getLogDocument)(data, exceptionType);
}
else {
document = (0, utils_js_1.getLogDocument)(data);
}
document.documentStreamIds = [...streamIds];
this.addDocument(document);
}
}
parseMetricFilterConfiguration(response) {
// eslint-disable-next-line eqeqeq
if (!(response === null || response === void 0 ? void 0 : response.documentStreams) || typeof response.documentStreams.forEach !== "function") {
return;
}
response.metrics.forEach((derivedMetricInfo) => {
var _a;
try {
if (!this.seenMetricIds.has(derivedMetricInfo.id)) {
this.seenMetricIds.add(derivedMetricInfo.id);
this.validator.validateTelemetryType(derivedMetricInfo.telemetryType);
this.validator.checkCustomMetricProjection(derivedMetricInfo);
this.validator.validateMetricFilters(derivedMetricInfo);
derivedMetricInfo.filterGroups.forEach((filterConjunctionGroupInfo) => {
this.filter.renameExceptionFieldNamesForFiltering(filterConjunctionGroupInfo);
});
if (this.validDerivedMetrics.has(derivedMetricInfo.telemetryType)) {
(_a = this.validDerivedMetrics.get(derivedMetricInfo.telemetryType)) === null || _a === void 0 ? void 0 : _a.push(derivedMetricInfo);
}
else {
this.validDerivedMetrics.set(derivedMetricInfo.telemetryType, [derivedMetricInfo]);
}
}
else {
throw new quickpulseErrors_js_1.DuplicateMetricIdError(`Duplicate Metric Id: ${derivedMetricInfo.id}`);
}
this.derivedMetricProjection.initDerivedMetricProjection(derivedMetricInfo);
}
catch (error) {
const configError = {
collectionConfigurationErrorType: "",
message: "",
fullException: "",
data: [],
};
if (error instanceof quickpulseErrors_js_1.TelemetryTypeError) {
configError.collectionConfigurationErrorType =
index_js_1.KnownCollectionConfigurationErrorType.MetricTelemetryTypeUnsupported;
}
else if (error instanceof quickpulseErrors_js_1.UnexpectedFilterCreateError) {
configError.collectionConfigurationErrorType =
index_js_1.KnownCollectionConfigurationErrorType.MetricFailureToCreateFilterUnexpected;
}
else if (error instanceof quickpulseErrors_js_1.DuplicateMetricIdError) {
configError.collectionConfigurationErrorType =
index_js_1.KnownCollectionConfigurationErrorType.MetricDuplicateIds;
}
if (error instanceof Error) {
configError.message = error.message;
configError.fullException = error.stack || "";
}
const data = [];
data.push({ key: "MetricId", value: derivedMetricInfo.id });
data.push({ key: "ETag", value: this.etag });
configError.data = data;
this.errorTracker.addValidationError(configError);
}
});
}
checkMetricFilterAndCreateProjection(derivedMetricInfoList, data) {
derivedMetricInfoList.forEach((derivedMetricInfo) => {
if (this.filter.checkMetricFilters(derivedMetricInfo, data)) {
try {
this.derivedMetricProjection.calculateProjection(derivedMetricInfo, data);
}
catch (error) {
const configError = {
collectionConfigurationErrorType: "",
message: "",
fullException: "",
data: [],
};
if (error instanceof quickpulseErrors_js_1.MetricFailureToCreateError) {
configError.collectionConfigurationErrorType =
index_js_1.KnownCollectionConfigurationErrorType.MetricFailureToCreate;
if (error instanceof Error) {
configError.message = error.message;
configError.fullException = error.stack || "";
}
const errorData = [];
errorData.push({ key: "MetricId", value: derivedMetricInfo.id });
errorData.push({ key: "ETag", value: this.etag });
configError.data = errorData;
this.errorTracker.addRunTimeError(configError);
}
}
}
});
}
}
exports.LiveMetrics = LiveMetrics;
//# sourceMappingURL=liveMetrics.js.map