@c15t/backend 2.0.0-rc.0 → 2.0.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/302.js +473 -0
- package/dist/583.js +540 -0
- package/dist/915.js +1771 -0
- package/dist/cache.cjs +5 -5
- package/dist/cache.js +4 -415
- package/dist/core.cjs +1356 -120
- package/dist/core.js +163 -1981
- package/dist/db/adapters/drizzle.cjs +1 -1
- package/dist/db/adapters/drizzle.js +1 -2
- package/dist/db/adapters/kysely.cjs +1 -1
- package/dist/db/adapters/kysely.js +1 -2
- package/dist/db/adapters/mongo.cjs +1 -1
- package/dist/db/adapters/mongo.js +1 -2
- package/dist/db/adapters/prisma.cjs +1 -1
- package/dist/db/adapters/prisma.js +1 -2
- package/dist/db/adapters/typeorm.cjs +1 -1
- package/dist/db/adapters/typeorm.js +1 -2
- package/dist/db/adapters.cjs +1 -1
- package/dist/db/migrator.cjs +1 -1
- package/dist/db/schema.cjs +43 -3
- package/dist/db/schema.js +35 -4
- package/dist/define-config.cjs +1 -1
- package/dist/edge.cjs +1106 -0
- package/dist/edge.js +190 -0
- package/dist/router.cjs +885 -123
- package/dist/router.js +1 -1507
- package/dist/{types.cjs → types/index.cjs} +1 -1
- package/{dist → dist-types}/cache/adapters/cloudflare-kv.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/index.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/memory.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/upstash-redis.d.ts +0 -1
- package/{dist → dist-types}/cache/gvl-resolver.d.ts +0 -1
- package/{dist → dist-types}/cache/index.d.ts +0 -1
- package/{dist → dist-types}/cache/keys.d.ts +0 -1
- package/{dist → dist-types}/cache/types.d.ts +0 -1
- package/{dist → dist-types}/core.d.ts +8 -1
- package/{dist → dist-types}/db/migrator/index.d.ts +0 -1
- package/dist-types/db/registry/consent-policy.d.ts +78 -0
- package/{dist → dist-types}/db/registry/consent-purpose.d.ts +0 -1
- package/{dist → dist-types}/db/registry/domain.d.ts +0 -1
- package/dist-types/db/registry/index.d.ts +118 -0
- package/dist-types/db/registry/runtime-policy-decision.d.ts +60 -0
- package/{dist → dist-types}/db/registry/subject.d.ts +0 -2
- package/{dist → dist-types}/db/registry/types.d.ts +1 -1
- package/{dist → dist-types}/db/registry/utils/generate-id.d.ts +0 -1
- package/{dist → dist-types}/db/registry/utils.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/audit-log.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-policy.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-purpose.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-record.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent.d.ts +1 -2
- package/{dist → dist-types}/db/schema/1.0.0/domain.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/index.d.ts +0 -32
- package/{dist → dist-types}/db/schema/1.0.0/subject.d.ts +0 -2
- package/{dist → dist-types}/db/schema/2.0.0/audit-log.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/consent-policy.d.ts +3 -3
- package/{dist → dist-types}/db/schema/2.0.0/consent-purpose.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/consent.d.ts +7 -2
- package/{dist → dist-types}/db/schema/2.0.0/domain.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/index.d.ts +455 -28
- package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +23 -0
- package/{dist → dist-types}/db/schema/2.0.0/subject.d.ts +1 -3
- package/{dist → dist-types}/db/schema/index.d.ts +908 -86
- package/{dist → dist-types}/db/tenant-scope.d.ts +0 -1
- package/dist-types/define-config.d.ts +17 -0
- package/dist-types/edge/index.d.ts +5 -0
- package/dist-types/edge/init-handler.d.ts +40 -0
- package/dist-types/edge/resolve-consent.d.ts +80 -0
- package/dist-types/edge/types.d.ts +13 -0
- package/{dist → dist-types}/handlers/consent/check.handler.d.ts +0 -1
- package/{src/handlers/consent/index.ts → dist-types/handlers/consent/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/init/geo.d.ts +2 -3
- package/{dist → dist-types}/handlers/init/index.d.ts +2 -3
- package/dist-types/handlers/init/policy.d.ts +26 -0
- package/dist-types/handlers/init/resolve-init.d.ts +44 -0
- package/dist-types/handlers/init/translations.d.ts +48 -0
- package/dist-types/handlers/legal-document/current.handler.d.ts +11 -0
- package/dist-types/handlers/legal-document/snapshot.d.ts +39 -0
- package/dist-types/handlers/policy/snapshot.d.ts +99 -0
- package/{src/handlers/status/index.ts → dist-types/handlers/status/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/status/status.handler.d.ts +0 -1
- package/{dist → dist-types}/handlers/subject/get.handler.d.ts +3 -2
- package/{src/handlers/subject/index.ts → dist-types/handlers/subject/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/subject/list.handler.d.ts +3 -2
- package/{dist → dist-types}/handlers/subject/patch.handler.d.ts +0 -2
- package/{dist → dist-types}/handlers/subject/post.handler.d.ts +12 -1
- package/{dist → dist-types}/handlers/utils/consent-enrichment.d.ts +3 -1
- package/{dist → dist-types}/init.d.ts +4 -7
- package/{dist → dist-types}/middleware/auth/index.d.ts +0 -1
- package/{dist → dist-types}/middleware/auth/validate-api-key.d.ts +0 -1
- package/{dist → dist-types}/middleware/cors/cors.d.ts +0 -1
- package/{src/middleware/cors/index.ts → dist-types/middleware/cors/index.d.ts} +0 -1
- package/{dist → dist-types}/middleware/cors/is-origin-trusted.d.ts +0 -1
- package/{dist → dist-types}/middleware/cors/process-cors.d.ts +0 -1
- package/{dist → dist-types}/middleware/openapi/config.d.ts +0 -1
- package/{dist → dist-types}/middleware/openapi/handlers.d.ts +0 -1
- package/{src/middleware/openapi/index.ts → dist-types/middleware/openapi/index.d.ts} +0 -1
- package/{dist → dist-types}/middleware/process-ip/index.d.ts +0 -1
- package/dist-types/policies/builder.d.ts +127 -0
- package/dist-types/policies/defaults.d.ts +2 -0
- package/dist-types/policies/matchers.d.ts +3 -0
- package/{dist → dist-types}/router.d.ts +0 -1
- package/{dist → dist-types}/routes/consent.d.ts +0 -1
- package/{dist → dist-types}/routes/index.d.ts +1 -1
- package/{dist → dist-types}/routes/init.d.ts +0 -1
- package/dist-types/routes/legal-document.d.ts +7 -0
- package/{dist → dist-types}/routes/status.d.ts +0 -1
- package/{dist → dist-types}/routes/subject.d.ts +0 -1
- package/{dist → dist-types}/types/api.d.ts +0 -1
- package/dist-types/types/index.d.ts +464 -0
- package/dist-types/utils/background.d.ts +6 -0
- package/{dist → dist-types}/utils/create-telemetry-options.d.ts +1 -2
- package/{dist → dist-types}/utils/env.d.ts +0 -1
- package/{dist → dist-types}/utils/extract-error-message.d.ts +0 -1
- package/{dist → dist-types}/utils/instrumentation.d.ts +2 -3
- package/{dist → dist-types}/utils/logger.d.ts +0 -1
- package/{dist → dist-types}/utils/metrics.d.ts +0 -1
- package/dist-types/version.d.ts +1 -0
- package/docs/README.md +49 -0
- package/docs/api/configuration.md +208 -0
- package/docs/api/endpoints.md +211 -0
- package/docs/guides/caching.md +85 -0
- package/docs/guides/database-setup.md +128 -0
- package/docs/guides/edge-deployment.md +251 -0
- package/docs/guides/framework-integration.md +142 -0
- package/docs/guides/iab-tcf.md +89 -0
- package/docs/guides/observability.md +96 -0
- package/docs/guides/policy-packs.md +396 -0
- package/docs/quickstart.md +129 -0
- package/package.json +53 -39
- package/.turbo/turbo-build.log +0 -49
- package/CHANGELOG.md +0 -89
- package/dist/cache/adapters/cloudflare-kv.d.ts.map +0 -1
- package/dist/cache/adapters/index.d.ts.map +0 -1
- package/dist/cache/adapters/memory.d.ts.map +0 -1
- package/dist/cache/adapters/upstash-redis.d.ts.map +0 -1
- package/dist/cache/gvl-resolver.d.ts.map +0 -1
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/keys.d.ts.map +0 -1
- package/dist/cache/types.d.ts.map +0 -1
- package/dist/core.d.ts.map +0 -1
- package/dist/db/adapters/drizzle.d.ts +0 -2
- package/dist/db/adapters/drizzle.d.ts.map +0 -1
- package/dist/db/adapters/index.d.ts +0 -2
- package/dist/db/adapters/index.d.ts.map +0 -1
- package/dist/db/adapters/kysely.d.ts +0 -2
- package/dist/db/adapters/kysely.d.ts.map +0 -1
- package/dist/db/adapters/mongo.d.ts +0 -2
- package/dist/db/adapters/mongo.d.ts.map +0 -1
- package/dist/db/adapters/prisma.d.ts +0 -2
- package/dist/db/adapters/prisma.d.ts.map +0 -1
- package/dist/db/adapters/typeorm.d.ts +0 -2
- package/dist/db/adapters/typeorm.d.ts.map +0 -1
- package/dist/db/migrator/index.d.ts.map +0 -1
- package/dist/db/registry/consent-policy.d.ts +0 -23
- package/dist/db/registry/consent-policy.d.ts.map +0 -1
- package/dist/db/registry/consent-purpose.d.ts.map +0 -1
- package/dist/db/registry/domain.d.ts.map +0 -1
- package/dist/db/registry/index.d.ts +0 -57
- package/dist/db/registry/index.d.ts.map +0 -1
- package/dist/db/registry/subject.d.ts.map +0 -1
- package/dist/db/registry/types.d.ts.map +0 -1
- package/dist/db/registry/utils/generate-id.d.ts.map +0 -1
- package/dist/db/registry/utils.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/audit-log.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-policy.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-purpose.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-record.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/domain.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/index.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/subject.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/audit-log.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent-policy.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent-purpose.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/domain.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/index.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/subject.d.ts.map +0 -1
- package/dist/db/schema/index.d.ts.map +0 -1
- package/dist/db/tenant-scope.d.ts.map +0 -1
- package/dist/define-config.d.ts +0 -5
- package/dist/define-config.d.ts.map +0 -1
- package/dist/handlers/consent/check.handler.d.ts.map +0 -1
- package/dist/handlers/consent/index.d.ts +0 -12
- package/dist/handlers/consent/index.d.ts.map +0 -1
- package/dist/handlers/init/geo.d.ts.map +0 -1
- package/dist/handlers/init/index.d.ts.map +0 -1
- package/dist/handlers/init/translations.d.ts +0 -28
- package/dist/handlers/init/translations.d.ts.map +0 -1
- package/dist/handlers/status/index.d.ts +0 -7
- package/dist/handlers/status/index.d.ts.map +0 -1
- package/dist/handlers/status/status.handler.d.ts.map +0 -1
- package/dist/handlers/subject/get.handler.d.ts.map +0 -1
- package/dist/handlers/subject/index.d.ts +0 -10
- package/dist/handlers/subject/index.d.ts.map +0 -1
- package/dist/handlers/subject/list.handler.d.ts.map +0 -1
- package/dist/handlers/subject/patch.handler.d.ts.map +0 -1
- package/dist/handlers/subject/post.handler.d.ts.map +0 -1
- package/dist/handlers/utils/consent-enrichment.d.ts.map +0 -1
- package/dist/init.d.ts.map +0 -1
- package/dist/middleware/auth/index.d.ts.map +0 -1
- package/dist/middleware/auth/validate-api-key.d.ts.map +0 -1
- package/dist/middleware/cors/cors.d.ts.map +0 -1
- package/dist/middleware/cors/index.d.ts +0 -30
- package/dist/middleware/cors/index.d.ts.map +0 -1
- package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
- package/dist/middleware/cors/process-cors.d.ts.map +0 -1
- package/dist/middleware/openapi/config.d.ts.map +0 -1
- package/dist/middleware/openapi/handlers.d.ts.map +0 -1
- package/dist/middleware/openapi/index.d.ts +0 -12
- package/dist/middleware/openapi/index.d.ts.map +0 -1
- package/dist/middleware/process-ip/index.d.ts.map +0 -1
- package/dist/router.d.ts.map +0 -1
- package/dist/routes/consent.d.ts.map +0 -1
- package/dist/routes/index.d.ts.map +0 -1
- package/dist/routes/init.d.ts.map +0 -1
- package/dist/routes/status.d.ts.map +0 -1
- package/dist/routes/subject.d.ts.map +0 -1
- package/dist/types/api.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -255
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/create-telemetry-options.d.ts.map +0 -1
- package/dist/utils/env.d.ts.map +0 -1
- package/dist/utils/extract-error-message.d.ts.map +0 -1
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/instrumentation.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/metrics.d.ts.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.d.ts.map +0 -1
- package/knip.json +0 -31
- package/rslib.config.ts +0 -93
- package/src/cache/adapters/cloudflare-kv.ts +0 -71
- package/src/cache/adapters/index.ts +0 -22
- package/src/cache/adapters/memory.ts +0 -111
- package/src/cache/adapters/upstash-redis.ts +0 -113
- package/src/cache/gvl-resolver.ts +0 -289
- package/src/cache/index.ts +0 -34
- package/src/cache/keys.ts +0 -68
- package/src/cache/types.ts +0 -66
- package/src/core.ts +0 -368
- package/src/db/migrator/index.ts +0 -80
- package/src/db/registry/consent-policy.test.ts +0 -451
- package/src/db/registry/consent-policy.ts +0 -82
- package/src/db/registry/consent-purpose.test.ts +0 -428
- package/src/db/registry/consent-purpose.ts +0 -61
- package/src/db/registry/domain.test.ts +0 -445
- package/src/db/registry/domain.ts +0 -91
- package/src/db/registry/index.ts +0 -14
- package/src/db/registry/subject.test.ts +0 -388
- package/src/db/registry/subject.ts +0 -129
- package/src/db/registry/types.ts +0 -10
- package/src/db/registry/utils/generate-id.test.ts +0 -216
- package/src/db/registry/utils/generate-id.ts +0 -133
- package/src/db/registry/utils.ts +0 -133
- package/src/db/schema/1.0.0/audit-log.ts +0 -15
- package/src/db/schema/1.0.0/consent-policy.ts +0 -14
- package/src/db/schema/1.0.0/consent-purpose.ts +0 -14
- package/src/db/schema/1.0.0/consent-record.ts +0 -10
- package/src/db/schema/1.0.0/consent.ts +0 -20
- package/src/db/schema/1.0.0/domain.ts +0 -12
- package/src/db/schema/1.0.0/index.ts +0 -48
- package/src/db/schema/1.0.0/subject.ts +0 -12
- package/src/db/schema/2.0.0/audit-log.ts +0 -18
- package/src/db/schema/2.0.0/consent-policy.ts +0 -28
- package/src/db/schema/2.0.0/consent-purpose.ts +0 -12
- package/src/db/schema/2.0.0/consent.ts +0 -26
- package/src/db/schema/2.0.0/domain.ts +0 -12
- package/src/db/schema/2.0.0/index.ts +0 -47
- package/src/db/schema/2.0.0/subject.ts +0 -14
- package/src/db/schema/index.ts +0 -15
- package/src/db/tenant-scope.test.ts +0 -750
- package/src/db/tenant-scope.ts +0 -103
- package/src/define-config.ts +0 -5
- package/src/handlers/consent/check.handler.ts +0 -126
- package/src/handlers/init/geo.test.ts +0 -317
- package/src/handlers/init/geo.ts +0 -195
- package/src/handlers/init/index.test.ts +0 -205
- package/src/handlers/init/index.ts +0 -114
- package/src/handlers/init/translations.test.ts +0 -121
- package/src/handlers/init/translations.ts +0 -72
- package/src/handlers/status/status.handler.test.ts +0 -155
- package/src/handlers/status/status.handler.ts +0 -51
- package/src/handlers/subject/get.handler.ts +0 -93
- package/src/handlers/subject/list.handler.ts +0 -93
- package/src/handlers/subject/patch.handler.ts +0 -122
- package/src/handlers/subject/post.handler.test.ts +0 -294
- package/src/handlers/subject/post.handler.ts +0 -254
- package/src/handlers/utils/consent-enrichment.test.ts +0 -380
- package/src/handlers/utils/consent-enrichment.ts +0 -218
- package/src/init.test.ts +0 -126
- package/src/init.ts +0 -87
- package/src/middleware/auth/index.ts +0 -11
- package/src/middleware/auth/validate-api-key.test.ts +0 -86
- package/src/middleware/auth/validate-api-key.ts +0 -107
- package/src/middleware/cors/cors.test.ts +0 -135
- package/src/middleware/cors/cors.ts +0 -186
- package/src/middleware/cors/is-origin-trusted.test.ts +0 -164
- package/src/middleware/cors/is-origin-trusted.ts +0 -130
- package/src/middleware/cors/process-cors.ts +0 -91
- package/src/middleware/openapi/config.ts +0 -29
- package/src/middleware/openapi/handlers.ts +0 -34
- package/src/middleware/process-ip/index.test.ts +0 -195
- package/src/middleware/process-ip/index.ts +0 -199
- package/src/router.ts +0 -15
- package/src/routes/consent.ts +0 -52
- package/src/routes/index.ts +0 -10
- package/src/routes/init.ts +0 -102
- package/src/routes/status.ts +0 -46
- package/src/routes/subject.ts +0 -152
- package/src/types/api.ts +0 -48
- package/src/types/index.ts +0 -288
- package/src/utils/create-telemetry-options.test.ts +0 -302
- package/src/utils/create-telemetry-options.ts +0 -229
- package/src/utils/env.ts +0 -84
- package/src/utils/extract-error-message.ts +0 -21
- package/src/utils/instrumentation.test.ts +0 -185
- package/src/utils/instrumentation.ts +0 -196
- package/src/utils/logger.ts +0 -41
- package/src/utils/metrics.test.ts +0 -323
- package/src/utils/metrics.ts +0 -402
- package/src/utils/telemetry-pii.test.ts +0 -325
- package/src/version.ts +0 -2
- package/tsconfig.json +0 -11
- package/vitest.config.ts +0 -28
- /package/dist/{types.js → types/index.js} +0 -0
- /package/{src/db/adapters/drizzle.ts → dist-types/db/adapters/drizzle.d.ts} +0 -0
- /package/{src/db/adapters/index.ts → dist-types/db/adapters/index.d.ts} +0 -0
- /package/{src/db/adapters/kysely.ts → dist-types/db/adapters/kysely.d.ts} +0 -0
- /package/{src/db/adapters/mongo.ts → dist-types/db/adapters/mongo.d.ts} +0 -0
- /package/{src/db/adapters/prisma.ts → dist-types/db/adapters/prisma.d.ts} +0 -0
- /package/{src/db/adapters/typeorm.ts → dist-types/db/adapters/typeorm.d.ts} +0 -0
- /package/{src/utils/index.ts → dist-types/utils/index.d.ts} +0 -0
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
context,
|
|
3
|
-
type Meter,
|
|
4
|
-
metrics,
|
|
5
|
-
type Span,
|
|
6
|
-
SpanStatusCode,
|
|
7
|
-
trace,
|
|
8
|
-
} from '@opentelemetry/api';
|
|
9
|
-
import type { C15TOptions } from '../types';
|
|
10
|
-
import { version } from '../version';
|
|
11
|
-
import { extractErrorMessage } from './extract-error-message';
|
|
12
|
-
|
|
13
|
-
type TelemetryConfig = NonNullable<C15TOptions['advanced']>['telemetry'];
|
|
14
|
-
|
|
15
|
-
// ── Cached config (set once during init) ──────────────────────────────
|
|
16
|
-
let cachedConfig: TelemetryConfig | null = null;
|
|
17
|
-
let cachedDefaultAttributes: Record<string, string | number | boolean> = {};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Creates telemetry configuration from provided options
|
|
21
|
-
*
|
|
22
|
-
* This function merges user-provided telemetry options with sensible defaults,
|
|
23
|
-
* ensuring that service name and version are always properly set.
|
|
24
|
-
*
|
|
25
|
-
* Telemetry is opt-in by default - users must explicitly set enabled: true.
|
|
26
|
-
*
|
|
27
|
-
* @param appName - The application name to use for service.name attribute
|
|
28
|
-
* @param telemetryConfig - Optional user-provided telemetry configuration
|
|
29
|
-
* @param tenantId - Optional tenant ID for multi-tenant deployments
|
|
30
|
-
* @returns Properly structured telemetry options for the OpenTelemetry SDK
|
|
31
|
-
*/
|
|
32
|
-
export function createTelemetryOptions(
|
|
33
|
-
appName = 'c15t',
|
|
34
|
-
telemetryConfig?: TelemetryConfig,
|
|
35
|
-
tenantId?: string
|
|
36
|
-
): TelemetryConfig {
|
|
37
|
-
const defaultAttributes: Record<string, string | number | boolean> = {
|
|
38
|
-
...(telemetryConfig?.defaultAttributes || {}),
|
|
39
|
-
|
|
40
|
-
// Always ensure these core attributes are set
|
|
41
|
-
'service.name': String(appName),
|
|
42
|
-
'service.version': version,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
if (tenantId) {
|
|
46
|
-
defaultAttributes['tenant.id'] = tenantId;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const config: TelemetryConfig = {
|
|
50
|
-
// Opt-in: disabled by default, must be explicitly enabled
|
|
51
|
-
enabled: telemetryConfig?.enabled ?? false,
|
|
52
|
-
tracer: telemetryConfig?.tracer,
|
|
53
|
-
meter: telemetryConfig?.meter,
|
|
54
|
-
defaultAttributes,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Cache for use without explicit options
|
|
58
|
-
cachedConfig = config;
|
|
59
|
-
cachedDefaultAttributes = defaultAttributes;
|
|
60
|
-
|
|
61
|
-
return config;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Checks if telemetry is enabled.
|
|
66
|
-
* When called without options, uses the cached config from init.
|
|
67
|
-
*/
|
|
68
|
-
export function isTelemetryEnabled(options?: C15TOptions): boolean {
|
|
69
|
-
if (options) {
|
|
70
|
-
return options.advanced?.telemetry?.enabled === true;
|
|
71
|
-
}
|
|
72
|
-
return cachedConfig?.enabled === true;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Gets the tracer for the c15t backend.
|
|
77
|
-
* When called without options, uses the cached config from init.
|
|
78
|
-
*/
|
|
79
|
-
export const getTracer = (options?: C15TOptions) => {
|
|
80
|
-
if (!isTelemetryEnabled(options)) {
|
|
81
|
-
// Return a no-op tracer when telemetry is disabled
|
|
82
|
-
return trace.getTracer('c15t-noop');
|
|
83
|
-
}
|
|
84
|
-
const tracer = options?.advanced?.telemetry?.tracer ?? cachedConfig?.tracer;
|
|
85
|
-
if (tracer) {
|
|
86
|
-
return tracer;
|
|
87
|
-
}
|
|
88
|
-
return trace.getTracer(options?.appName ?? 'c15t');
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Gets the meter for the c15t backend.
|
|
93
|
-
* When called without options, uses the cached config from init.
|
|
94
|
-
*/
|
|
95
|
-
export const getMeter = (options?: C15TOptions): Meter => {
|
|
96
|
-
if (!isTelemetryEnabled(options)) {
|
|
97
|
-
// Return a no-op meter when telemetry is disabled
|
|
98
|
-
return metrics.getMeter('c15t-noop');
|
|
99
|
-
}
|
|
100
|
-
const meter = options?.advanced?.telemetry?.meter ?? cachedConfig?.meter;
|
|
101
|
-
if (meter) {
|
|
102
|
-
return meter;
|
|
103
|
-
}
|
|
104
|
-
return metrics.getMeter(options?.appName ?? 'c15t');
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Gets the cached default attributes.
|
|
109
|
-
* Used by span wrappers when no explicit options are provided.
|
|
110
|
-
*/
|
|
111
|
-
export function getDefaultAttributes(): Record<
|
|
112
|
-
string,
|
|
113
|
-
string | number | boolean
|
|
114
|
-
> {
|
|
115
|
-
return cachedDefaultAttributes;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Resets the cached telemetry config (for testing).
|
|
120
|
-
*/
|
|
121
|
-
export function resetTelemetryConfig(): void {
|
|
122
|
-
cachedConfig = null;
|
|
123
|
-
cachedDefaultAttributes = {};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Creates a span for an API request
|
|
128
|
-
*/
|
|
129
|
-
export const createRequestSpan = (
|
|
130
|
-
method: string,
|
|
131
|
-
path: string,
|
|
132
|
-
options?: C15TOptions
|
|
133
|
-
) => {
|
|
134
|
-
if (!isTelemetryEnabled(options)) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const tracer = getTracer(options);
|
|
139
|
-
const defaultAttrs =
|
|
140
|
-
options?.advanced?.telemetry?.defaultAttributes || getDefaultAttributes();
|
|
141
|
-
|
|
142
|
-
const span = tracer.startSpan(`${method} ${path}`, {
|
|
143
|
-
attributes: {
|
|
144
|
-
'http.method': method,
|
|
145
|
-
...defaultAttrs,
|
|
146
|
-
},
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
return span;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Wraps an API request handler in a span.
|
|
154
|
-
* The span is set as active context so child spans nest correctly.
|
|
155
|
-
*/
|
|
156
|
-
export const withRequestSpan = async <T>(
|
|
157
|
-
method: string,
|
|
158
|
-
path: string,
|
|
159
|
-
operation: () => Promise<T>,
|
|
160
|
-
options?: C15TOptions
|
|
161
|
-
): Promise<T> => {
|
|
162
|
-
const span = createRequestSpan(method, path, options);
|
|
163
|
-
|
|
164
|
-
if (!span) {
|
|
165
|
-
return operation();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
try {
|
|
169
|
-
const result = await withSpanContext(span, operation);
|
|
170
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
171
|
-
return result;
|
|
172
|
-
} catch (error) {
|
|
173
|
-
handleSpanError(span, error);
|
|
174
|
-
throw error;
|
|
175
|
-
} finally {
|
|
176
|
-
span.end();
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Handles errors in spans
|
|
182
|
-
*/
|
|
183
|
-
export const handleSpanError = (span: Span, error: unknown) => {
|
|
184
|
-
span.setStatus({
|
|
185
|
-
code: SpanStatusCode.ERROR,
|
|
186
|
-
message: extractErrorMessage(error),
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
if (error instanceof Error) {
|
|
190
|
-
span.setAttribute('error.type', error.name);
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Gets the current trace context for log correlation.
|
|
196
|
-
* Returns trace and span IDs from the active span.
|
|
197
|
-
*
|
|
198
|
-
* @returns Object with traceId and spanId, or null if no active span
|
|
199
|
-
*/
|
|
200
|
-
export function getTraceContext(): {
|
|
201
|
-
traceId: string;
|
|
202
|
-
spanId: string;
|
|
203
|
-
} | null {
|
|
204
|
-
const activeSpan = trace.getActiveSpan();
|
|
205
|
-
if (!activeSpan) {
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const spanContext = activeSpan.spanContext();
|
|
210
|
-
if (!spanContext) {
|
|
211
|
-
return null;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return {
|
|
215
|
-
traceId: spanContext.traceId,
|
|
216
|
-
spanId: spanContext.spanId,
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Runs a function within a span context, making the span active.
|
|
222
|
-
* This allows nested operations to access the parent span via trace.getActiveSpan().
|
|
223
|
-
*/
|
|
224
|
-
export const withSpanContext = async <T>(
|
|
225
|
-
span: Span,
|
|
226
|
-
operation: () => Promise<T>
|
|
227
|
-
): Promise<T> => {
|
|
228
|
-
return context.with(trace.setSpan(context.active(), span), operation);
|
|
229
|
-
};
|
package/src/utils/env.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Environment variables object
|
|
3
|
-
*
|
|
4
|
-
* Provides access to environment variables in a way that works in both
|
|
5
|
-
* browser and Node.js environments. In Node.js, this will be process.env,
|
|
6
|
-
* and in browsers, it will be an empty object.
|
|
7
|
-
*
|
|
8
|
-
* @returns An object containing environment variables accessible in the current runtime
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* // Access an environment variable
|
|
13
|
-
* const apiKey = env.API_KEY;
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
export const env = typeof process !== 'undefined' ? process.env : {};
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Determines if the application is running in production mode
|
|
20
|
-
*
|
|
21
|
-
* Checks if NODE_ENV is set to 'production'. This is useful for
|
|
22
|
-
* conditionally enabling or disabling features based on the environment.
|
|
23
|
-
*
|
|
24
|
-
* @returns Boolean indicating whether the application is running in production mode
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* // Conditionally execute code based on environment
|
|
29
|
-
* if (isProduction) {
|
|
30
|
-
* // Production-only code
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export const isProduction =
|
|
35
|
-
typeof process !== 'undefined' && process.env.NODE_ENV === 'production';
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Converts a string or boolean value to a boolean
|
|
39
|
-
*
|
|
40
|
-
* @param val - The value to convert to boolean
|
|
41
|
-
* @returns `false` if the value is falsy or the string 'false', otherwise `true`
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```ts
|
|
45
|
-
* toBoolean('true'); // true
|
|
46
|
-
* toBoolean('false'); // false
|
|
47
|
-
* toBoolean(undefined); // false
|
|
48
|
-
* toBoolean(true); // true
|
|
49
|
-
* ```
|
|
50
|
-
*
|
|
51
|
-
* @internal Used for environment variable parsing
|
|
52
|
-
*/
|
|
53
|
-
function toBoolean(val: boolean | string | undefined) {
|
|
54
|
-
return val ? val !== 'false' : false;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* The current Node.js environment value
|
|
59
|
-
*
|
|
60
|
-
* Retrieves the NODE_ENV environment variable value if available,
|
|
61
|
-
* otherwise returns an empty string.
|
|
62
|
-
*
|
|
63
|
-
* @returns The current NODE_ENV value or empty string if not set
|
|
64
|
-
*/
|
|
65
|
-
export const nodeENV =
|
|
66
|
-
(typeof process !== 'undefined' && process.env && process.env.NODE_ENV) || '';
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Determines if the application is running in test mode
|
|
70
|
-
*
|
|
71
|
-
* Checks if NODE_ENV is set to 'test' or if the TEST environment
|
|
72
|
-
* variable is truthy and not 'false'.
|
|
73
|
-
*
|
|
74
|
-
* @returns Boolean indicating whether the application is running in test mode
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* ```ts
|
|
78
|
-
* // Skip expensive operations in tests
|
|
79
|
-
* if (!isTest) {
|
|
80
|
-
* runExpensiveOperation();
|
|
81
|
-
* }
|
|
82
|
-
* ```
|
|
83
|
-
*/
|
|
84
|
-
export const isTest = nodeENV === 'test' || toBoolean(env.TEST);
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extracts a useful error message from any error type.
|
|
3
|
-
*
|
|
4
|
-
* Handles `AggregateError` (e.g. from Node.js `net.connect` failing on both
|
|
5
|
-
* IPv4/IPv6) where `error.message` is empty but `error.errors[]` contains the
|
|
6
|
-
* real messages.
|
|
7
|
-
*/
|
|
8
|
-
export function extractErrorMessage(error: unknown): string {
|
|
9
|
-
if (error instanceof AggregateError && error.errors?.length > 0) {
|
|
10
|
-
const inner = error.errors
|
|
11
|
-
.map((e: unknown) => (e instanceof Error ? e.message : String(e)))
|
|
12
|
-
.join('; ');
|
|
13
|
-
return `AggregateError: ${inner}`;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (error instanceof Error) {
|
|
17
|
-
return error.message || error.name;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return String(error);
|
|
21
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import type { C15TOptions } from '../types';
|
|
3
|
-
import {
|
|
4
|
-
withCacheSpan,
|
|
5
|
-
withDatabaseSpan,
|
|
6
|
-
withExternalSpan,
|
|
7
|
-
} from './instrumentation';
|
|
8
|
-
|
|
9
|
-
// Mock create-telemetry-options
|
|
10
|
-
vi.mock('./create-telemetry-options', () => {
|
|
11
|
-
const { SpanStatusCode } = require('@opentelemetry/api');
|
|
12
|
-
|
|
13
|
-
const mockSpan = () => ({
|
|
14
|
-
setStatus: vi.fn(),
|
|
15
|
-
setAttribute: vi.fn(),
|
|
16
|
-
updateName: vi.fn(),
|
|
17
|
-
end: vi.fn(),
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
isTelemetryEnabled: vi.fn(
|
|
22
|
-
(options) => options?.advanced?.telemetry?.enabled === true
|
|
23
|
-
),
|
|
24
|
-
getTracer: vi.fn(() => ({
|
|
25
|
-
startSpan: vi.fn(() => mockSpan()),
|
|
26
|
-
})),
|
|
27
|
-
getDefaultAttributes: vi.fn(() => ({
|
|
28
|
-
'service.name': 'test',
|
|
29
|
-
'service.version': '1.0.0',
|
|
30
|
-
})),
|
|
31
|
-
withSpanContext: vi.fn((_span, operation) => operation()),
|
|
32
|
-
handleSpanError: vi.fn((span, error) => {
|
|
33
|
-
span.setStatus({
|
|
34
|
-
code: SpanStatusCode.ERROR,
|
|
35
|
-
message: error instanceof Error ? error.message : String(error),
|
|
36
|
-
});
|
|
37
|
-
if (error instanceof Error) {
|
|
38
|
-
span.setAttribute('error.type', error.name);
|
|
39
|
-
}
|
|
40
|
-
}),
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
vi.clearAllMocks();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const enabledOptions: C15TOptions = {
|
|
49
|
-
trustedOrigins: [],
|
|
50
|
-
adapter: {} as C15TOptions['adapter'],
|
|
51
|
-
advanced: {
|
|
52
|
-
telemetry: {
|
|
53
|
-
enabled: true,
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
describe('withDatabaseSpan', () => {
|
|
59
|
-
it('returns operation result when telemetry is disabled', async () => {
|
|
60
|
-
const result = await withDatabaseSpan(
|
|
61
|
-
{ operation: 'find', entity: 'subject' },
|
|
62
|
-
async () => ({ id: '123', name: 'test' })
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
expect(result).toEqual({ id: '123', name: 'test' });
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('returns operation result when telemetry is enabled', async () => {
|
|
69
|
-
const result = await withDatabaseSpan(
|
|
70
|
-
{ operation: 'find', entity: 'subject' },
|
|
71
|
-
async () => ({ id: '123', name: 'test' }),
|
|
72
|
-
enabledOptions
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
expect(result).toEqual({ id: '123', name: 'test' });
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('propagates errors from operation', async () => {
|
|
79
|
-
const error = new Error('DB connection failed');
|
|
80
|
-
|
|
81
|
-
await expect(
|
|
82
|
-
withDatabaseSpan(
|
|
83
|
-
{ operation: 'find', entity: 'subject' },
|
|
84
|
-
async () => {
|
|
85
|
-
throw error;
|
|
86
|
-
},
|
|
87
|
-
enabledOptions
|
|
88
|
-
)
|
|
89
|
-
).rejects.toThrow('DB connection failed');
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('executes operation without span when telemetry is disabled', async () => {
|
|
93
|
-
const operation = vi.fn().mockResolvedValue('result');
|
|
94
|
-
|
|
95
|
-
const result = await withDatabaseSpan(
|
|
96
|
-
{ operation: 'create', entity: 'consent' },
|
|
97
|
-
operation
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
expect(result).toBe('result');
|
|
101
|
-
expect(operation).toHaveBeenCalledTimes(1);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('withExternalSpan', () => {
|
|
106
|
-
it('returns operation result when telemetry is disabled', async () => {
|
|
107
|
-
const result = await withExternalSpan(
|
|
108
|
-
{ url: 'https://example.com/api', method: 'GET' },
|
|
109
|
-
async () => ({ status: 200 })
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
expect(result).toEqual({ status: 200 });
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('returns operation result when telemetry is enabled', async () => {
|
|
116
|
-
const result = await withExternalSpan(
|
|
117
|
-
{ url: 'https://example.com/api', method: 'GET' },
|
|
118
|
-
async () => ({ status: 200 }),
|
|
119
|
-
enabledOptions
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
expect(result).toEqual({ status: 200 });
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('propagates errors from operation', async () => {
|
|
126
|
-
const error = new Error('Network error');
|
|
127
|
-
|
|
128
|
-
await expect(
|
|
129
|
-
withExternalSpan(
|
|
130
|
-
{ url: 'https://example.com/api', method: 'POST' },
|
|
131
|
-
async () => {
|
|
132
|
-
throw error;
|
|
133
|
-
},
|
|
134
|
-
enabledOptions
|
|
135
|
-
)
|
|
136
|
-
).rejects.toThrow('Network error');
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe('withCacheSpan', () => {
|
|
141
|
-
it('returns operation result when telemetry is disabled', async () => {
|
|
142
|
-
const result = await withCacheSpan('get', 'memory', async () => ({
|
|
143
|
-
data: 'cached',
|
|
144
|
-
}));
|
|
145
|
-
|
|
146
|
-
expect(result).toEqual({ data: 'cached' });
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('returns operation result when telemetry is enabled', async () => {
|
|
150
|
-
const result = await withCacheSpan(
|
|
151
|
-
'get',
|
|
152
|
-
'external',
|
|
153
|
-
async () => ({ data: 'cached' }),
|
|
154
|
-
enabledOptions
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
expect(result).toEqual({ data: 'cached' });
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it('returns null for cache miss', async () => {
|
|
161
|
-
const result = await withCacheSpan(
|
|
162
|
-
'get',
|
|
163
|
-
'memory',
|
|
164
|
-
async () => null,
|
|
165
|
-
enabledOptions
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
expect(result).toBeNull();
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('propagates errors from operation', async () => {
|
|
172
|
-
const error = new Error('Cache connection failed');
|
|
173
|
-
|
|
174
|
-
await expect(
|
|
175
|
-
withCacheSpan(
|
|
176
|
-
'get',
|
|
177
|
-
'external',
|
|
178
|
-
async () => {
|
|
179
|
-
throw error;
|
|
180
|
-
},
|
|
181
|
-
enabledOptions
|
|
182
|
-
)
|
|
183
|
-
).rejects.toThrow('Cache connection failed');
|
|
184
|
-
});
|
|
185
|
-
});
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import type { Span } from '@opentelemetry/api';
|
|
2
|
-
import { SpanKind, SpanStatusCode } from '@opentelemetry/api';
|
|
3
|
-
import type { C15TOptions } from '../types';
|
|
4
|
-
import {
|
|
5
|
-
getDefaultAttributes,
|
|
6
|
-
getTracer,
|
|
7
|
-
handleSpanError,
|
|
8
|
-
isTelemetryEnabled,
|
|
9
|
-
withSpanContext,
|
|
10
|
-
} from './create-telemetry-options';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Span attributes for database operations
|
|
14
|
-
*/
|
|
15
|
-
export interface DatabaseSpanAttributes {
|
|
16
|
-
/** The database operation type (find, create, update, delete) */
|
|
17
|
-
operation: 'find' | 'create' | 'update' | 'delete' | 'findOrCreate';
|
|
18
|
-
/** The entity type being operated on */
|
|
19
|
-
entity: string;
|
|
20
|
-
/** Optional additional attributes */
|
|
21
|
-
[key: string]: string | number | boolean | undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Span attributes for external API calls
|
|
26
|
-
*/
|
|
27
|
-
export interface ExternalSpanAttributes {
|
|
28
|
-
/** The URL being called */
|
|
29
|
-
url: string;
|
|
30
|
-
/** The HTTP method */
|
|
31
|
-
method: string;
|
|
32
|
-
/** Optional additional attributes */
|
|
33
|
-
[key: string]: string | number | boolean | undefined;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Execute an async operation within a span, handling status and error recording.
|
|
38
|
-
*
|
|
39
|
-
* Sets SpanStatusCode.OK on success, records error attributes and sets
|
|
40
|
-
* SpanStatusCode.ERROR on failure, and always ends the span.
|
|
41
|
-
*/
|
|
42
|
-
async function executeWithSpan<T>(
|
|
43
|
-
span: Span,
|
|
44
|
-
operation: () => Promise<T>
|
|
45
|
-
): Promise<T> {
|
|
46
|
-
try {
|
|
47
|
-
const result = await withSpanContext(span, operation);
|
|
48
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
49
|
-
return result;
|
|
50
|
-
} catch (error) {
|
|
51
|
-
handleSpanError(span, error);
|
|
52
|
-
throw error;
|
|
53
|
-
} finally {
|
|
54
|
-
span.end();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Resolves default attributes from explicit options or the cached config.
|
|
60
|
-
*/
|
|
61
|
-
function resolveDefaultAttributes(
|
|
62
|
-
options?: C15TOptions
|
|
63
|
-
): Record<string, string | number | boolean> {
|
|
64
|
-
return (
|
|
65
|
-
options?.advanced?.telemetry?.defaultAttributes || getDefaultAttributes()
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Wraps a database operation in a span for tracing.
|
|
71
|
-
*
|
|
72
|
-
* @param attributes - Span attributes describing the operation
|
|
73
|
-
* @param operation - The async operation to wrap
|
|
74
|
-
* @param options - C15T options for telemetry configuration
|
|
75
|
-
* @returns The result of the operation
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* ```typescript
|
|
79
|
-
* const subject = await withDatabaseSpan(
|
|
80
|
-
* { operation: 'find', entity: 'subject' },
|
|
81
|
-
* async () => db.subject.findUnique({ where: { id } }),
|
|
82
|
-
* options
|
|
83
|
-
* );
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
export async function withDatabaseSpan<T>(
|
|
87
|
-
attributes: DatabaseSpanAttributes,
|
|
88
|
-
operation: () => Promise<T>,
|
|
89
|
-
options?: C15TOptions
|
|
90
|
-
): Promise<T> {
|
|
91
|
-
if (!isTelemetryEnabled(options)) {
|
|
92
|
-
return operation();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const tracer = getTracer(options);
|
|
96
|
-
const spanName = `db.${attributes.entity}.${attributes.operation}`;
|
|
97
|
-
|
|
98
|
-
const span = tracer.startSpan(spanName, {
|
|
99
|
-
kind: SpanKind.CLIENT,
|
|
100
|
-
attributes: {
|
|
101
|
-
'db.system': 'c15t',
|
|
102
|
-
'db.operation': attributes.operation,
|
|
103
|
-
'db.entity': attributes.entity,
|
|
104
|
-
...resolveDefaultAttributes(options),
|
|
105
|
-
...Object.fromEntries(
|
|
106
|
-
Object.entries(attributes).filter(
|
|
107
|
-
([key]) => !['operation', 'entity'].includes(key)
|
|
108
|
-
)
|
|
109
|
-
),
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
return executeWithSpan(span, operation);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Wraps an external API call in a span for tracing.
|
|
118
|
-
*
|
|
119
|
-
* @param attributes - Span attributes describing the external call
|
|
120
|
-
* @param operation - The async operation to wrap
|
|
121
|
-
* @param options - C15T options for telemetry configuration
|
|
122
|
-
* @returns The result of the operation
|
|
123
|
-
*
|
|
124
|
-
* @example
|
|
125
|
-
* ```typescript
|
|
126
|
-
* const response = await withExternalSpan(
|
|
127
|
-
* { url: 'https://api.example.com/data', method: 'GET' },
|
|
128
|
-
* async () => fetch('https://api.example.com/data'),
|
|
129
|
-
* options
|
|
130
|
-
* );
|
|
131
|
-
* ```
|
|
132
|
-
*/
|
|
133
|
-
export async function withExternalSpan<T>(
|
|
134
|
-
attributes: ExternalSpanAttributes,
|
|
135
|
-
operation: () => Promise<T>,
|
|
136
|
-
options?: C15TOptions
|
|
137
|
-
): Promise<T> {
|
|
138
|
-
if (!isTelemetryEnabled(options)) {
|
|
139
|
-
return operation();
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const tracer = getTracer(options);
|
|
143
|
-
const url = new URL(attributes.url);
|
|
144
|
-
const spanName = `HTTP ${attributes.method} ${url.hostname}`;
|
|
145
|
-
|
|
146
|
-
const span = tracer.startSpan(spanName, {
|
|
147
|
-
kind: SpanKind.CLIENT,
|
|
148
|
-
attributes: {
|
|
149
|
-
'http.method': attributes.method,
|
|
150
|
-
'http.url': `${url.origin}${url.pathname}`,
|
|
151
|
-
'http.host': url.hostname,
|
|
152
|
-
...resolveDefaultAttributes(options),
|
|
153
|
-
...Object.fromEntries(
|
|
154
|
-
Object.entries(attributes).filter(
|
|
155
|
-
([key]) => !['url', 'method'].includes(key)
|
|
156
|
-
)
|
|
157
|
-
),
|
|
158
|
-
},
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
return executeWithSpan(span, operation);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Wraps a cache operation in a span for tracing.
|
|
166
|
-
*
|
|
167
|
-
* @param operation - The cache operation type
|
|
168
|
-
* @param layer - The cache layer (bundled, memory, external)
|
|
169
|
-
* @param fn - The async operation to wrap
|
|
170
|
-
* @param options - C15T options for telemetry configuration
|
|
171
|
-
* @returns The result of the operation
|
|
172
|
-
*/
|
|
173
|
-
export async function withCacheSpan<T>(
|
|
174
|
-
operation: 'get' | 'set' | 'delete',
|
|
175
|
-
layer: 'bundled' | 'memory' | 'external',
|
|
176
|
-
fn: () => Promise<T>,
|
|
177
|
-
options?: C15TOptions
|
|
178
|
-
): Promise<T> {
|
|
179
|
-
if (!isTelemetryEnabled(options)) {
|
|
180
|
-
return fn();
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const tracer = getTracer(options);
|
|
184
|
-
const spanName = `cache.${layer}.${operation}`;
|
|
185
|
-
|
|
186
|
-
const span = tracer.startSpan(spanName, {
|
|
187
|
-
kind: SpanKind.CLIENT,
|
|
188
|
-
attributes: {
|
|
189
|
-
'cache.operation': operation,
|
|
190
|
-
'cache.layer': layer,
|
|
191
|
-
...resolveDefaultAttributes(options),
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
return executeWithSpan(span, fn);
|
|
196
|
-
}
|