autotel
Version:
Write Once, Observe Anywhere
591 lines (585 loc) • 25.9 kB
JavaScript
import { REDACTOR_PATTERNS } from "./attribute-redacting-processor.js";
import { C as URLAttributes, S as ThreadAttributes, _ as RPCAttributes, a as DeviceAttributes, b as SessionAttributes, c as FaaSAttributes, d as HTTPAttributes, f as K8sAttributes, g as ProcessAttributes, h as OTelAttributes, i as DBAttributes, l as FeatureFlagAttributes, m as NetworkAttributes, n as CodeAttributes, o as ErrorAttributes, p as MessagingAttributes, r as ContainerAttributes, s as ExceptionAttributes, t as CloudAttributes, u as GraphQLAttributes, v as ServerAddressAttributes, w as UserAttributes, x as TLSAttributes, y as ServiceAttributes } from "./registry-DVSmWg6Y.js";
import { resourceFromAttributes } from "@opentelemetry/resources";
//#region src/attributes/builders.ts
/**
* Attribute builders for constructing OpenTelemetry attributes
* Provides both key builders (Pattern A) and object builders (Pattern B)
*
* @example Pattern A: Key builders
* ```typescript
* attrs.user.id('123') // { 'user.id': '123' }
* attrs.user.email('user@example.com') // { 'user.email': 'user@example.com' }
* attrs.http.request.method('GET') // { 'http.request.method': 'GET' }
* attrs.http.response.statusCode(200) // { 'http.response.status_code': 200 }
* ```
*
* @example Pattern B: Object builders
* ```typescript
* attrs.user({ id: '123', email: 'user@example.com' })
* attrs.http.server({ method: 'GET', route: '/users/:id', statusCode: 200 })
* attrs.db.client({ system: 'postgresql', operation: 'SELECT', collectionName: 'users' })
* ```
*/
const attrs = {
user: {
id: (value) => ({ [UserAttributes.id]: value }),
email: (value) => ({ [UserAttributes.email]: value }),
name: (value) => ({ [UserAttributes.name]: value }),
fullName: (value) => ({ [UserAttributes.fullName]: value }),
hash: (value) => ({ [UserAttributes.hash]: value }),
roles: (value) => ({ [UserAttributes.roles]: value }),
data: (data) => {
const result = {};
if (data.id !== void 0) result[UserAttributes.id] = data.id;
if (data.email !== void 0) result[UserAttributes.email] = data.email;
if (data.name !== void 0) result[UserAttributes.name] = data.name;
if (data.fullName !== void 0) result[UserAttributes.fullName] = data.fullName;
if (data.hash !== void 0) result[UserAttributes.hash] = data.hash;
if (data.roles !== void 0) result[UserAttributes.roles] = data.roles;
return result;
}
},
session: {
id: (value) => ({ [SessionAttributes.id]: value }),
previousId: (value) => ({ [SessionAttributes.previousId]: value }),
data: (data) => {
const result = {};
if (data.id !== void 0) result[SessionAttributes.id] = data.id;
if (data.previousId !== void 0) result[SessionAttributes.previousId] = data.previousId;
return result;
}
},
device: {
id: (value) => ({ [DeviceAttributes.id]: value }),
manufacturer: (value) => ({ [DeviceAttributes.manufacturer]: value }),
modelIdentifier: (value) => ({ [DeviceAttributes.modelIdentifier]: value }),
modelName: (value) => ({ [DeviceAttributes.modelName]: value }),
data: (data) => {
const result = {};
if (data.id !== void 0) result[DeviceAttributes.id] = data.id;
if (data.manufacturer !== void 0) result[DeviceAttributes.manufacturer] = data.manufacturer;
if (data.modelIdentifier !== void 0) result[DeviceAttributes.modelIdentifier] = data.modelIdentifier;
if (data.modelName !== void 0) result[DeviceAttributes.modelName] = data.modelName;
return result;
}
},
http: {
request: {
method: (value) => ({ [HTTPAttributes.requestMethod]: value }),
methodOriginal: (value) => ({ [HTTPAttributes.requestMethodOriginal]: value }),
resendCount: (value) => ({ [HTTPAttributes.requestResendCount]: value }),
size: (value) => ({ [HTTPAttributes.requestSize]: value }),
bodySize: (value) => ({ [HTTPAttributes.requestBodySize]: value })
},
response: {
statusCode: (value) => ({ [HTTPAttributes.responseStatusCode]: value }),
size: (value) => ({ [HTTPAttributes.responseSize]: value }),
bodySize: (value) => ({ [HTTPAttributes.responseBodySize]: value })
},
route: (value) => ({ [HTTPAttributes.route]: value }),
connectionState: (value) => ({ [HTTPAttributes.connectionState]: value }),
server: (data) => {
const result = {};
if (data.method !== void 0) result[HTTPAttributes.requestMethod] = data.method;
if (data.route !== void 0) result[HTTPAttributes.route] = data.route;
if (data.statusCode !== void 0) result[HTTPAttributes.responseStatusCode] = data.statusCode;
if (data.bodySize !== void 0) result[HTTPAttributes.requestBodySize] = data.bodySize;
if (data.requestSize !== void 0) result[HTTPAttributes.requestSize] = data.requestSize;
if (data.responseSize !== void 0) result[HTTPAttributes.responseSize] = data.responseSize;
if (data.resendCount !== void 0) result[HTTPAttributes.requestResendCount] = data.resendCount;
return result;
},
client: (data) => {
const result = {};
if (data.method !== void 0) result[HTTPAttributes.requestMethod] = data.method;
if (data.url !== void 0) result[HTTPAttributes.route] = data.url;
if (data.statusCode !== void 0) result[HTTPAttributes.responseStatusCode] = data.statusCode;
return result;
}
},
db: { client: {
system: (value) => ({ [DBAttributes.systemName]: value }),
operation: (value) => ({ [DBAttributes.operationName]: value }),
collectionName: (value) => ({ [DBAttributes.collectionName]: value }),
namespace: (value) => ({ [DBAttributes.namespace]: value }),
statement: (value) => ({ [DBAttributes.statement]: value }),
querySummary: (value) => ({ [DBAttributes.querySummary]: value }),
queryText: (value) => ({ [DBAttributes.queryText]: value }),
responseStatus: (value) => ({ [DBAttributes.responseStatusCode]: value }),
rowsReturned: (value) => ({ [DBAttributes.responseReturnedRows]: value }),
data: (data) => {
const result = {};
if (data.system !== void 0) result[DBAttributes.systemName] = data.system;
if (data.operation !== void 0) result[DBAttributes.operationName] = data.operation;
if (data.collectionName !== void 0) result[DBAttributes.collectionName] = data.collectionName;
if (data.name !== void 0) result[DBAttributes.namespace] = data.name;
if (data.namespace !== void 0) result[DBAttributes.namespace] = data.namespace;
if (data.statement !== void 0) result[DBAttributes.statement] = data.statement;
if (data.querySummary !== void 0) result[DBAttributes.querySummary] = data.querySummary;
if (data.queryText !== void 0) result[DBAttributes.queryText] = data.queryText;
if (data.responseStatus !== void 0) result[DBAttributes.responseStatusCode] = data.responseStatus;
if (data.rowsReturned !== void 0) result[DBAttributes.responseReturnedRows] = data.rowsReturned;
return result;
}
} },
service: {
name: (value) => ({ [ServiceAttributes.name]: value }),
instance: (value) => ({ [ServiceAttributes.instance]: value }),
version: (value) => ({ [ServiceAttributes.version]: value }),
data: (data) => {
const result = {};
if (data.name !== void 0) result[ServiceAttributes.name] = data.name;
if (data.instance !== void 0) result[ServiceAttributes.instance] = data.instance;
if (data.version !== void 0) result[ServiceAttributes.version] = data.version;
return result;
}
},
network: {
peerAddress: (value) => ({ [NetworkAttributes.peerAddress]: value }),
peerPort: (value) => ({ [NetworkAttributes.peerPort]: value }),
transport: (value) => ({ [NetworkAttributes.transport]: value }),
protocolName: (value) => ({ [NetworkAttributes.protocolName]: value }),
protocolVersion: (value) => ({ [NetworkAttributes.protocolVersion]: value }),
data: (data) => {
const result = {};
if (data.peerAddress !== void 0) result[NetworkAttributes.peerAddress] = data.peerAddress;
if (data.peerPort !== void 0) result[NetworkAttributes.peerPort] = data.peerPort;
if (data.transport !== void 0) result[NetworkAttributes.transport] = data.transport;
if (data.protocolName !== void 0) result[NetworkAttributes.protocolName] = data.protocolName;
if (data.protocolVersion !== void 0) result[NetworkAttributes.protocolVersion] = data.protocolVersion;
return result;
}
},
server: {
address: (value) => ({ [ServerAddressAttributes.address]: value }),
port: (value) => ({ [ServerAddressAttributes.port]: value }),
socketAddress: (value) => ({ [ServerAddressAttributes.socketAddress]: value }),
data: (data) => {
const result = {};
if (data.address !== void 0) result[ServerAddressAttributes.address] = data.address;
if (data.port !== void 0) result[ServerAddressAttributes.port] = data.port;
if (data.socketAddress !== void 0) result[ServerAddressAttributes.socketAddress] = data.socketAddress;
return result;
}
},
url: {
scheme: (value) => ({ [URLAttributes.scheme]: value }),
full: (value) => ({ [URLAttributes.full]: value }),
path: (value) => ({ [URLAttributes.path]: value }),
query: (value) => ({ [URLAttributes.query]: value }),
fragment: (value) => ({ [URLAttributes.fragment]: value }),
data: (data) => {
const result = {};
if (data.scheme !== void 0) result[URLAttributes.scheme] = data.scheme;
if (data.full !== void 0) result[URLAttributes.full] = data.full;
if (data.path !== void 0) result[URLAttributes.path] = data.path;
if (data.query !== void 0) result[URLAttributes.query] = data.query;
if (data.fragment !== void 0) result[URLAttributes.fragment] = data.fragment;
return result;
}
},
error: {
type: (value) => ({ [ErrorAttributes.type]: value }),
message: (value) => ({ [ErrorAttributes.message]: value }),
stackTrace: (value) => ({ [ErrorAttributes.stackTrace]: value }),
code: (value) => ({ [ErrorAttributes.code]: value }),
data: (data) => {
const result = {};
if (data.type !== void 0) result[ErrorAttributes.type] = data.type;
if (data.message !== void 0) result[ErrorAttributes.message] = data.message;
if (data.stackTrace !== void 0) result[ErrorAttributes.stackTrace] = data.stackTrace;
if (data.code !== void 0) result[ErrorAttributes.code] = data.code;
return result;
}
},
exception: {
escaped: (value) => ({ [ExceptionAttributes.escaped]: value }),
message: (value) => ({ [ExceptionAttributes.message]: value }),
stackTrace: (value) => ({ [ExceptionAttributes.stackTrace]: value }),
type: (value) => ({ [ExceptionAttributes.type]: value }),
moduleName: (value) => ({ [ExceptionAttributes.moduleName]: value }),
data: (data) => {
const result = {};
if (data.escaped !== void 0) result[ExceptionAttributes.escaped] = data.escaped;
if (data.message !== void 0) result[ExceptionAttributes.message] = data.message;
if (data.stackTrace !== void 0) result[ExceptionAttributes.stackTrace] = data.stackTrace;
if (data.type !== void 0) result[ExceptionAttributes.type] = data.type;
if (data.moduleName !== void 0) result[ExceptionAttributes.moduleName] = data.moduleName;
return result;
}
},
process: {
pid: (value) => ({ [ProcessAttributes.pid]: value }),
executablePath: (value) => ({ [ProcessAttributes.executablePath]: value }),
command: (value) => ({ [ProcessAttributes.command]: value }),
owner: (value) => ({ [ProcessAttributes.owner]: value }),
data: (data) => {
const result = {};
if (data.pid !== void 0) result[ProcessAttributes.pid] = data.pid;
if (data.executablePath !== void 0) result[ProcessAttributes.executablePath] = data.executablePath;
if (data.command !== void 0) result[ProcessAttributes.command] = data.command;
if (data.owner !== void 0) result[ProcessAttributes.owner] = data.owner;
return result;
}
},
thread: {
id: (value) => ({ [ThreadAttributes.id]: value }),
name: (value) => ({ [ThreadAttributes.name]: value })
},
container: {
id: (value) => ({ [ContainerAttributes.id]: value }),
name: (value) => ({ [ContainerAttributes.name]: value }),
image: (value) => ({ [ContainerAttributes.image]: value }),
tag: (value) => ({ [ContainerAttributes.tag]: value }),
data: (data) => {
const result = {};
if (data.id !== void 0) result[ContainerAttributes.id] = data.id;
if (data.name !== void 0) result[ContainerAttributes.name] = data.name;
if (data.image !== void 0) result[ContainerAttributes.image] = data.image;
if (data.tag !== void 0) result[ContainerAttributes.tag] = data.tag;
return result;
}
},
k8s: {
podName: (value) => ({ [K8sAttributes.podName]: value }),
namespaceName: (value) => ({ [K8sAttributes.namespaceName]: value }),
deploymentName: (value) => ({ [K8sAttributes.deploymentName]: value }),
state: (value) => ({ [K8sAttributes.state]: value })
},
cloud: {
provider: (value) => ({ [CloudAttributes.provider]: value }),
accountId: (value) => ({ [CloudAttributes.accountId]: value }),
region: (value) => ({ [CloudAttributes.region]: value }),
availabilityZone: (value) => ({ [CloudAttributes.availabilityZone]: value }),
platform: (value) => ({ [CloudAttributes.platform]: value }),
data: (data) => {
const result = {};
if (data.provider !== void 0) result[CloudAttributes.provider] = data.provider;
if (data.accountId !== void 0) result[CloudAttributes.accountId] = data.accountId;
if (data.region !== void 0) result[CloudAttributes.region] = data.region;
if (data.availabilityZone !== void 0) result[CloudAttributes.availabilityZone] = data.availabilityZone;
if (data.platform !== void 0) result[CloudAttributes.platform] = data.platform;
return result;
}
},
faas: {
name: (value) => ({ [FaaSAttributes.name]: value }),
version: (value) => ({ [FaaSAttributes.version]: value }),
instance: (value) => ({ [FaaSAttributes.instance]: value }),
execution: (value) => ({ [FaaSAttributes.execution]: value }),
coldstart: (value) => ({ [FaaSAttributes.coldstart]: value })
},
featureFlag: {
key: (value) => ({ [FeatureFlagAttributes.key]: value }),
provider: (value) => ({ [FeatureFlagAttributes.provider]: value }),
variant: (value) => ({ [FeatureFlagAttributes.variant]: value })
},
messaging: {
system: (value) => ({ [MessagingAttributes.system]: value }),
destination: (value) => ({ [MessagingAttributes.destination]: value }),
operation: (value) => ({ [MessagingAttributes.operation]: value }),
messageId: (value) => ({ [MessagingAttributes.messageId]: value }),
conversationId: (value) => ({ [MessagingAttributes.conversationId]: value }),
data: (data) => {
const result = {};
if (data.system !== void 0) result[MessagingAttributes.system] = data.system;
if (data.destination !== void 0) result[MessagingAttributes.destination] = data.destination;
if (data.operation !== void 0) result[MessagingAttributes.operation] = data.operation;
if (data.messageId !== void 0) result[MessagingAttributes.messageId] = data.messageId;
if (data.conversationId !== void 0) result[MessagingAttributes.conversationId] = data.conversationId;
return result;
}
},
rpc: {
system: (value) => ({ [RPCAttributes.system]: value }),
service: (value) => ({ [RPCAttributes.service]: value }),
method: (value) => ({ [RPCAttributes.method]: value }),
grpcStatusCode: (value) => ({ [RPCAttributes.grpcStatusCode]: value })
},
graphql: {
document: (value) => ({ [GraphQLAttributes.document]: value }),
operationName: (value) => ({ [GraphQLAttributes.operationName]: value }),
operationType: (value) => ({ [GraphQLAttributes.operationType]: value })
},
otel: {
libraryName: (value) => ({ [OTelAttributes.libraryName]: value }),
libraryVersion: (value) => ({ [OTelAttributes.libraryVersion]: value }),
statusCode: (value) => ({ [OTelAttributes.statusCode]: value })
},
code: {
namespace: (value) => ({ [CodeAttributes.namespace]: value }),
filepath: (value) => ({ [CodeAttributes.filepath]: value }),
function: (value) => ({ [CodeAttributes.function]: value }),
class: (value) => ({ [CodeAttributes.class]: value }),
method: (value) => ({ [CodeAttributes.method]: value }),
column: (value) => ({ [CodeAttributes.column]: value }),
lineNumber: (value) => ({ [CodeAttributes.lineNumber]: value }),
repository: (value) => ({ [CodeAttributes.repository]: value }),
revision: (value) => ({ [CodeAttributes.revision]: value })
},
tls: {
protocolVersion: (value) => ({ [TLSAttributes.protocolVersion]: value }),
cipher: (value) => ({ [TLSAttributes.cipher]: value }),
curveName: (value) => ({ [TLSAttributes.curveName]: value }),
resumed: (value) => ({ [TLSAttributes.resumed]: value })
}
};
//#endregion
//#region src/attributes/validators.ts
/**
* Attribute validation, PII detection, and guardrails
* Provides safe-by-default attribute handling with configurable policies
*/
const DEPRECATED_ATTRIBUTES = {
"enduser.id": "user.id",
"enduser.role": "user.roles",
"enduser.scope": void 0,
"http.method": "http.request.method",
"http.host": "server.address",
"http.status_code": "http.response.status_code",
"http.target": "url.path",
"http.url": "url.full",
"http.user_agent": "user_agent.original",
"http.flavor": "network.protocol.name",
"http.scheme": "url.scheme",
"http.server_name": "server.address",
"db.name": "db.namespace",
"db.operation": "db.operation.name",
"db.statement": "db.query.text",
"db.system": "db.system.name",
"db.collection": "db.collection.name",
"db.instance.id": void 0,
"db.jdbc.driver_classname": void 0,
"db.mssql.instance_name": "mssql.instance.name",
"db.sql.table": "db.collection.name",
"http.client_ip": "client.address",
"user_agent.original": "user_agent.original"
};
const HTTP_METHODS = new Set([
"GET",
"POST",
"PUT",
"DELETE",
"PATCH",
"HEAD",
"OPTIONS",
"TRACE",
"QUERY",
"_OTHER"
]);
function validateAttribute(key, value, policy = {}) {
const { guardrails = {} } = policy;
if (value === void 0 || value === null) return;
if (typeof value !== "string") return value;
const stringValue = value;
if (guardrails.pii) {
const piiResult = applyPIIPolicy(key, stringValue, guardrails.pii);
if (piiResult !== stringValue) return piiResult;
}
if (guardrails.maxLength && stringValue.length > guardrails.maxLength) return truncateValue(key, stringValue, guardrails.maxLength);
if (guardrails.validateEnum && HTTP_METHODS.has(stringValue)) {
const normalizedMethod = normalizeHTTPMethod(stringValue);
if (normalizedMethod !== stringValue) return normalizedMethod;
}
return stringValue;
}
function applyPIIPolicy(key, value, pii) {
if (pii === "allow") return value;
if (pii === "redact") return redactIfPII(key, value);
if (pii === "hash") return hashIfPII(key, value);
if (pii === "block" && isPIIKey(key)) throw new Error(`PII attribute "${key}" is blocked by guardrails. Use pii: "allow" to enable it.`);
return value;
}
function isPIIKey(key) {
const piiKeyPatterns = [
"email",
"phone",
"ssn",
"credit_card",
"password",
"secret",
"token",
"api_key",
"authorization"
];
const lowerKey = key.toLowerCase();
return piiKeyPatterns.some((pattern) => lowerKey.includes(pattern));
}
function redactIfPII(key, value) {
if (isPIIKey(key)) {
for (const [, pattern] of Object.entries(REDACTOR_PATTERNS)) if (pattern instanceof RegExp && pattern.test(value)) return "[REDACTED]";
return "[REDACTED]";
}
return value;
}
function hashIfPII(key, value) {
if (!isPIIKey(key)) return value;
const FNV_PRIME = 16777619;
const FNV_OFFSET = 2166136261;
const hashes = [];
for (let round = 0; round < 4; round++) {
let hash = FNV_OFFSET;
for (let i = 0; i < value.length; i++) {
hash ^= (value.codePointAt(i) ?? 0) + round;
hash = Math.imul(hash, FNV_PRIME);
}
hashes.push(hash >>> 0);
}
return `hash_${hashes.map((h) => h.toString(16).padStart(8, "0")).join("")}`;
}
function truncateValue(key, value, maxLength) {
if (value.length <= maxLength) return value;
return value.slice(0, maxLength - 3) + "...";
}
function normalizeHTTPMethod(method) {
const upper = method.toUpperCase();
if (HTTP_METHODS.has(upper)) return upper;
return upper;
}
function checkDeprecatedAttribute(key, policy = {}) {
const { guardrails = {}, deprecatedWarnings = {} } = policy;
const { warnDeprecated = true } = guardrails;
if (!warnDeprecated) return null;
if (key in DEPRECATED_ATTRIBUTES) {
const replacement = DEPRECATED_ATTRIBUTES[key];
if (replacement === void 0) console.warn(`[autotel/attributes] Attribute "${key}" is deprecated and has no replacement. Remove or find a replacement in OpenTelemetry semantic conventions.`);
else console.warn(`[autotel/attributes] Attribute "${key}" is deprecated. Use "${replacement}" instead.`);
}
if (deprecatedWarnings[key]) console.warn(`[autotel/attributes] ${deprecatedWarnings[key]}`);
return DEPRECATED_ATTRIBUTES[key] ?? null;
}
function autoRedactPII(attributes, policy = {}) {
const { guardrails = { pii: "redact" } } = policy;
const redacted = {};
for (const [key, value] of Object.entries(attributes)) redacted[key] = validateAttribute(key, value, { guardrails });
return redacted;
}
function defaultGuardrails() {
return {
pii: "redact",
maxLength: 255,
validateEnum: true,
warnDeprecated: true
};
}
//#endregion
//#region src/attributes/utils.ts
function mergeAttrs(...attrSets) {
const result = {};
for (const attrSet of attrSets) if (attrSet) Object.assign(result, attrSet);
return result;
}
function safeSetAttributes(span, attrs, policy) {
const mergedGuardrails = {
...defaultGuardrails(),
...policy?.guardrails
};
const effectivePolicy = {
...policy,
guardrails: mergedGuardrails
};
const validated = autoRedactPII(attrs, effectivePolicy);
const sanitizedAttrs = {};
for (const [key, value] of Object.entries(validated)) if (value !== void 0) {
checkDeprecatedAttribute(key, effectivePolicy);
const validatedValue = validateAttribute(key, value, effectivePolicy);
if (validatedValue !== void 0) sanitizedAttrs[key] = validatedValue;
}
span.setAttributes(sanitizedAttrs);
}
//#endregion
//#region src/attributes/attachers.ts
function setUser(spanOrContext, data, guardrails) {
safeSetAttributes(spanOrContext, attrs.user.data(data), guardrails);
}
function setSession(spanOrContext, data, guardrails) {
safeSetAttributes(spanOrContext, attrs.session.data(data), guardrails);
}
function setDevice(spanOrContext, data, guardrails) {
safeSetAttributes(spanOrContext, attrs.device.data(data), guardrails);
}
function httpServer(spanOrContext, data, guardrails) {
const attributes = attrs.http.server(data);
if ("updateName" in spanOrContext && data.method && data.route) spanOrContext.updateName(`HTTP ${data.method} ${data.route}`);
safeSetAttributes(spanOrContext, attributes, guardrails);
}
function httpClient(spanOrContext, data, guardrails) {
safeSetAttributes(spanOrContext, attrs.http.client(data), guardrails);
}
function dbClient(spanOrContext, data, guardrails) {
safeSetAttributes(spanOrContext, attrs.db.client.data(data), guardrails);
}
/**
* Merge service attributes into a Resource and return a new Resource.
*
* Resource.attributes is readonly, so this function returns a new merged
* Resource rather than mutating the input.
*
* @param resource - The existing resource to merge with
* @param data - Service attributes to add
* @returns A new Resource with the merged attributes
*
* @example
* ```typescript
* const baseResource = Resource.default();
* const enrichedResource = mergeServiceResource(baseResource, {
* name: 'my-service',
* version: '1.0.0',
* });
* ```
*/
function mergeServiceResource(resource, data) {
const attributes = attrs.service.data(data);
return resource.merge(resourceFromAttributes(attributes));
}
function identify(spanOrContext, data, guardrails) {
const allAttrs = [];
if (data.user) allAttrs.push(attrs.user.data(data.user));
if (data.session) allAttrs.push(attrs.session.data(data.session));
if (data.device) allAttrs.push(attrs.device.data(data.device));
const merged = {};
for (const attrSet of allAttrs) Object.assign(merged, attrSet);
safeSetAttributes(spanOrContext, merged, guardrails);
}
function request(spanOrContext, data, guardrails) {
const httpAttrs = attrs.http.server(data);
const networkAttrs = attrs.network.peerAddress(data.clientIp || "");
safeSetAttributes(spanOrContext, {
...httpAttrs,
...networkAttrs
}, guardrails);
}
function setError(spanOrContext, data, guardrails) {
safeSetAttributes(spanOrContext, attrs.error.data(data), guardrails);
}
function setException(spanOrContext, data, guardrails) {
safeSetAttributes(spanOrContext, attrs.exception.data(data), guardrails);
}
//#endregion
//#region src/attributes/domains.ts
/**
* Domain helpers for common attribute patterns
* These bundle multiple attribute groups into semantic helpers
*/
function transaction(spanOrContext, config, guardrails) {
const userAttrs = attrs.user.data(config.user || {});
const sessionAttrs = attrs.session.data(config.session || {});
const httpAttrs = attrs.http.server({
method: config.method,
route: config.route,
statusCode: config.statusCode
});
const networkAttrs = attrs.network.peerAddress(config.clientIp || "");
const merged = {
...userAttrs,
...sessionAttrs,
...httpAttrs,
...networkAttrs
};
if (config.method && config.route && "updateName" in spanOrContext) spanOrContext.updateName(`HTTP ${config.method} ${config.route}`);
safeSetAttributes(spanOrContext, merged, guardrails);
}
//#endregion
export { defaultGuardrails as _, identify as a, setDevice as c, setSession as d, setUser as f, checkDeprecatedAttribute as g, autoRedactPII as h, httpServer as i, setError as l, safeSetAttributes as m, dbClient as n, mergeServiceResource as o, mergeAttrs as p, httpClient as r, request as s, transaction as t, setException as u, validateAttribute as v, attrs as y };
//# sourceMappingURL=attributes-CmYpdqCN.js.map