UNPKG

@vtex/diagnostics-nodejs

Version:

Diagnostics library for Node.js applications

132 lines 5.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigurableSampler = void 0; const api_1 = require("@opentelemetry/api"); const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base"); const metadata_1 = require("./metadata"); class ConfigurableSampler { constructor(config) { this.config = config; } shouldSample(context, traceId, spanName, spanKind, attributes, links) { const metadata = (0, metadata_1.newSamplerMetadata)('configurable'); if (this.config.parentBased !== false) { const parentContext = api_1.trace.getSpanContext(context); if (parentContext?.traceFlags && (parentContext.traceFlags & 1)) { return { decision: sdk_trace_base_1.SamplingDecision.RECORD_AND_SAMPLED, attributes: metadata .setDecision(sdk_trace_base_1.SamplingDecision.RECORD_AND_SAMPLED, 'parent_sampled') .setRate(1.0) .toAttributes() }; } } if (this.config.rules) { for (const rule of this.config.rules) { if (this.ruleMatches(rule, attributes, spanName)) { const sampleRate = rule.sampleRate ?? 1.0; const decision = this.sampleByRate(traceId, sampleRate); return { decision, attributes: metadata .setDecision(decision, 'rule_match') .setRule(rule.name || 'unnamed') .setRate(sampleRate) .addExtra('conditions_count', rule.conditions?.length || 0) .toAttributes() }; } } } const defaultRate = this.config.defaultRate ?? 0.05; const decision = this.sampleByRate(traceId, defaultRate); return { decision, attributes: metadata .setDecision(decision, 'default_rate') .setRate(defaultRate) .addExtra('rules_evaluated', this.config.rules?.length || 0) .toAttributes() }; } updateConfig(newConfig) { this.config = newConfig; } ruleMatches(rule, attributes, spanName) { if (!rule.conditions || rule.conditions.length === 0) { return true; } return rule.conditions.every((condition) => this.conditionMatches(condition, attributes, spanName)); } conditionMatches(condition, attributes, spanName) { let value; if (condition.attribute === 'span.name' && spanName) { value = spanName; } else { value = String(attributes[condition.attribute] || ''); } switch (condition.operator) { case 'Equals': return value === condition.value; case 'NotEquals': return value !== condition.value; case 'Contains': return value.includes(condition.value || ''); case 'StartsWith': return value.startsWith(condition.value || ''); case 'EndsWith': return value.endsWith(condition.value || ''); case 'In': return (condition.values || []).includes(value); case 'NotIn': return !(condition.values || []).includes(value); case 'Regex': try { const regex = new RegExp(condition.value || ''); return regex.test(value); } catch { return false; } case 'GreaterThan': return this.numericCompare(value, condition.value, (a, b) => a > b); case 'LessThan': return this.numericCompare(value, condition.value, (a, b) => a < b); case 'GreaterThanEqual': return this.numericCompare(value, condition.value, (a, b) => a >= b); case 'LessThanEqual': return this.numericCompare(value, condition.value, (a, b) => a <= b); default: return false; } } numericCompare(value, target, compareFn) { const numValue = parseFloat(value); const numTarget = parseFloat(target || '0'); if (isNaN(numValue) || isNaN(numTarget)) { return false; } return compareFn(numValue, numTarget); } sampleByRate(traceId, rate) { if (rate <= 0.0) { return sdk_trace_base_1.SamplingDecision.NOT_RECORD; } if (rate >= 1.0) { return sdk_trace_base_1.SamplingDecision.RECORD_AND_SAMPLED; } const hashHex = traceId.substring(0, 8); const hashValue = parseInt(hashHex, 16); const normalizedValue = hashValue / 0xFFFFFFFF; return normalizedValue < rate ? sdk_trace_base_1.SamplingDecision.RECORD_AND_SAMPLED : sdk_trace_base_1.SamplingDecision.NOT_RECORD; } toString() { return `ConfigurableSampler(rules=${this.config.rules?.length || 0})`; } } exports.ConfigurableSampler = ConfigurableSampler; //# sourceMappingURL=configurable.js.map