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
JavaScript
;
// 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