UNPKG

enhanced-adot-node-autoinstrumentation

Version:

This package provides Amazon Web Services distribution of the OpenTelemetry Node Instrumentation, which allows for auto-instrumentation of NodeJS applications.

133 lines 7.45 kB
"use strict"; // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 Object.defineProperty(exports, "__esModule", { value: true }); exports.SamplingRuleApplier = void 0; const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base"); const semantic_conventions_1 = require("@opentelemetry/semantic-conventions"); const rate_limiting_sampler_1 = require("./rate-limiting-sampler"); const sampling_rule_1 = require("./sampling-rule"); const statistics_1 = require("./statistics"); const utils_1 = require("./utils"); // Max date time in JavaScript const MAX_DATE_TIME_MILLIS = new Date(8640000000000000).getTime(); class SamplingRuleApplier { constructor(samplingRule, statistics = new statistics_1.Statistics(), target) { this.samplingRule = new sampling_rule_1.SamplingRule(samplingRule); this.fixedRateSampler = new sdk_trace_base_1.TraceIdRatioBasedSampler(this.samplingRule.FixedRate); if (samplingRule.ReservoirSize > 0) { this.reservoirSampler = new rate_limiting_sampler_1.RateLimitingSampler(1); } else { this.reservoirSampler = new rate_limiting_sampler_1.RateLimitingSampler(0); } this.reservoirExpiryTimeInMillis = MAX_DATE_TIME_MILLIS; this.statistics = statistics; this.statistics.resetStatistics(); this.borrowingEnabled = true; if (target) { this.borrowingEnabled = false; if (target.ReservoirQuota) { this.reservoirSampler = new rate_limiting_sampler_1.RateLimitingSampler(target.ReservoirQuota); } if (target.ReservoirQuotaTTL) { this.reservoirExpiryTimeInMillis = new Date(target.ReservoirQuotaTTL * 1000).getTime(); } else { this.reservoirExpiryTimeInMillis = Date.now(); } if (target.FixedRate) { this.fixedRateSampler = new sdk_trace_base_1.TraceIdRatioBasedSampler(target.FixedRate); } } } withTarget(target) { const newApplier = new SamplingRuleApplier(this.samplingRule, this.statistics, target); return newApplier; } matches(attributes, resource) { var _a, _b, _c, _d, _e; let httpTarget = undefined; let httpUrl = undefined; let httpMethod = undefined; let httpHost = undefined; let serviceName = undefined; if (attributes) { httpTarget = (_a = attributes[semantic_conventions_1.SEMATTRS_HTTP_TARGET]) !== null && _a !== void 0 ? _a : attributes[semantic_conventions_1.ATTR_URL_PATH]; httpUrl = (_b = attributes[semantic_conventions_1.SEMATTRS_HTTP_URL]) !== null && _b !== void 0 ? _b : attributes[semantic_conventions_1.ATTR_URL_FULL]; httpMethod = (_c = attributes[semantic_conventions_1.SEMATTRS_HTTP_METHOD]) !== null && _c !== void 0 ? _c : attributes[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD]; httpHost = (_e = (_d = attributes[semantic_conventions_1.SEMATTRS_HTTP_HOST]) !== null && _d !== void 0 ? _d : attributes[semantic_conventions_1.ATTR_SERVER_ADDRESS]) !== null && _e !== void 0 ? _e : attributes[semantic_conventions_1.ATTR_CLIENT_ADDRESS]; } let serviceType = undefined; let resourceARN = undefined; if (resource) { serviceName = resource.attributes[semantic_conventions_1.SEMRESATTRS_SERVICE_NAME] || ''; const cloudPlatform = resource.attributes[semantic_conventions_1.SEMRESATTRS_CLOUD_PLATFORM]; if (typeof cloudPlatform === 'string') { serviceType = utils_1.CLOUD_PLATFORM_MAPPING[cloudPlatform]; } resourceARN = this.getArn(resource, attributes); } // target may be in url if (httpTarget === undefined && typeof httpUrl === 'string') { const schemeEndIndex = httpUrl.indexOf('://'); // For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format // Per spec, url.full is always populated with scheme:// // If scheme is not present, assume it's bad instrumentation and ignore. if (schemeEndIndex > -1) { // urlparse("scheme://netloc/path;parameters?query#fragment") httpTarget = new URL(httpUrl).pathname; if (httpTarget === '') httpTarget = '/'; } } else if (httpTarget === undefined && httpUrl === undefined) { // When missing, the URL Path is assumed to be '/' httpTarget = '/'; } return ((0, utils_1.attributeMatch)(attributes, this.samplingRule.Attributes) && (0, utils_1.wildcardMatch)(this.samplingRule.Host, httpHost) && (0, utils_1.wildcardMatch)(this.samplingRule.HTTPMethod, httpMethod) && (0, utils_1.wildcardMatch)(this.samplingRule.ServiceName, serviceName) && (0, utils_1.wildcardMatch)(this.samplingRule.URLPath, httpTarget) && (0, utils_1.wildcardMatch)(this.samplingRule.ServiceType, serviceType) && (0, utils_1.wildcardMatch)(this.samplingRule.ResourceARN, resourceARN)); } shouldSample(context, traceId, spanName, spanKind, attributes, links) { let hasBorrowed = false; let result = { decision: sdk_trace_base_1.SamplingDecision.NOT_RECORD }; const nowInMillis = Date.now(); const reservoirExpired = nowInMillis >= this.reservoirExpiryTimeInMillis; if (!reservoirExpired) { result = this.reservoirSampler.shouldSample(context, traceId, spanName, spanKind, attributes, links); hasBorrowed = this.borrowingEnabled && result.decision !== sdk_trace_base_1.SamplingDecision.NOT_RECORD; } if (result.decision === sdk_trace_base_1.SamplingDecision.NOT_RECORD) { result = this.fixedRateSampler.shouldSample(context, traceId); } this.statistics.SampleCount += result.decision !== sdk_trace_base_1.SamplingDecision.NOT_RECORD ? 1 : 0; this.statistics.BorrowCount += hasBorrowed ? 1 : 0; this.statistics.RequestCount += 1; return result; } snapshotStatistics() { const statisticsCopy = Object.assign({}, this.statistics); this.statistics.resetStatistics(); return statisticsCopy; } getArn(resource, attributes) { let arn = resource.attributes[semantic_conventions_1.SEMRESATTRS_AWS_ECS_CONTAINER_ARN] || resource.attributes[semantic_conventions_1.SEMRESATTRS_AWS_ECS_CLUSTER_ARN] || resource.attributes[semantic_conventions_1.SEMRESATTRS_AWS_EKS_CLUSTER_ARN]; if (arn === undefined && (resource === null || resource === void 0 ? void 0 : resource.attributes[semantic_conventions_1.SEMRESATTRS_CLOUD_PLATFORM]) === semantic_conventions_1.CLOUDPLATFORMVALUES_AWS_LAMBDA) { arn = this.getLambdaArn(resource, attributes); } return arn; } getLambdaArn(resource, attributes) { const arn = (resource === null || resource === void 0 ? void 0 : resource.attributes[semantic_conventions_1.SEMRESATTRS_FAAS_ID]) || attributes[semantic_conventions_1.SEMATTRS_AWS_LAMBDA_INVOKED_ARN]; return arn; } } exports.SamplingRuleApplier = SamplingRuleApplier; //# sourceMappingURL=sampling-rule-applier.js.map