autotel
Version:
Write Once, Observe Anywhere
94 lines (93 loc) • 3.27 kB
JavaScript
//#region src/span-name-normalizer.ts
/**
* Built-in normalizer patterns
*/
const NORMALIZER_PATTERNS = {
numericId: /\/\d+(?=\/|$)/g,
uuid: /\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?=\/|$)/gi,
shortUuid: /\/[0-9a-f]{32}(?=\/|$)/gi,
objectId: /\/[0-9a-f]{24}(?=\/|$)/gi,
hash: /\/[0-9a-f]{6,}(?=\.[a-z]+$)/gi,
isoDate: /\/\d{4}-\d{2}-\d{2}(?=\/|$)/g,
timestamp: /\/1[0-9]{9}(?=\/|$)/g,
email: /\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?=\/|$)/g
};
/**
* Built-in normalizer presets
*/
const NORMALIZER_PRESETS = {
/**
* REST API preset - normalizes common REST path patterns
* Handles: numeric IDs, UUIDs, ObjectIds, dates, timestamps, emails
*/
"rest-api": (name) => {
return name.replaceAll(NORMALIZER_PATTERNS.uuid, "/:uuid").replaceAll(NORMALIZER_PATTERNS.shortUuid, "/:uuid").replaceAll(NORMALIZER_PATTERNS.objectId, "/:objectId").replaceAll(NORMALIZER_PATTERNS.isoDate, "/:date").replaceAll(NORMALIZER_PATTERNS.timestamp, "/:timestamp").replaceAll(NORMALIZER_PATTERNS.email, "/:email").replaceAll(NORMALIZER_PATTERNS.numericId, "/:id");
},
/**
* GraphQL preset - normalizes GraphQL operation names and paths
* Keeps query/mutation names but normalizes embedded IDs
*/
graphql: (name) => {
return name.replaceAll(NORMALIZER_PATTERNS.uuid, "/:uuid").replaceAll(NORMALIZER_PATTERNS.numericId, "/:id");
},
/**
* Minimal preset - only normalizes numeric IDs and UUIDs
*/
minimal: (name) => {
return name.replaceAll(NORMALIZER_PATTERNS.uuid, "/:uuid").replaceAll(NORMALIZER_PATTERNS.numericId, "/:id");
}
};
/**
* Resolve normalizer config to a function
*/
function resolveNormalizer(config) {
if (typeof config === "function") return config;
const preset = NORMALIZER_PRESETS[config];
if (!preset) throw new Error(`Unknown span name normalizer preset: "${config}". Available presets: ${Object.keys(NORMALIZER_PRESETS).join(", ")}`);
return preset;
}
/**
* Span processor that normalizes span names to reduce cardinality.
*
* Normalization happens in onStart() when we have access to the mutable Span.
* This allows us to call span.updateName() before the span is finalized.
*
* Common use cases:
* - REST APIs: /users/123/posts/456 → /users/:id/posts/:id
* - UUIDs: /items/550e8400-e29b-41d4-a716-446655440000 → /items/:uuid
* - Dates: /logs/2024-01-15 → /logs/:date
*/
var SpanNameNormalizingProcessor = class {
wrappedProcessor;
normalizer;
constructor(wrappedProcessor, options) {
this.wrappedProcessor = wrappedProcessor;
this.normalizer = resolveNormalizer(options.normalizer);
}
/**
* Normalize span name on start (when Span is mutable)
*/
onStart(span, parentContext) {
try {
const originalName = span.name;
const normalizedName = this.normalizer(originalName);
if (normalizedName !== originalName) span.updateName(normalizedName);
} catch {}
this.wrappedProcessor.onStart(span, parentContext);
}
/**
* Pass through onEnd unchanged
*/
onEnd(span) {
this.wrappedProcessor.onEnd(span);
}
forceFlush() {
return this.wrappedProcessor.forceFlush();
}
shutdown() {
return this.wrappedProcessor.shutdown();
}
};
//#endregion
export { NORMALIZER_PATTERNS, NORMALIZER_PRESETS, SpanNameNormalizingProcessor };
//# sourceMappingURL=span-name-normalizer.js.map