apitally 0.25.7 → 1.0.0-alpha.1
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 +191 -184
- package/dist/activation.cjs +371 -0
- package/dist/activation.cjs.map +1 -0
- package/dist/activation.d.cts +41 -0
- package/dist/activation.d.ts +41 -0
- package/dist/activation.js +357 -0
- package/dist/activation.js.map +1 -0
- package/dist/adonisjs/configure.cjs +88 -31
- package/dist/adonisjs/configure.cjs.map +1 -1
- package/dist/adonisjs/configure.d.cts +0 -4
- package/dist/adonisjs/configure.d.ts +0 -4
- package/dist/adonisjs/configure.js +85 -30
- package/dist/adonisjs/configure.js.map +1 -1
- package/dist/adonisjs/index.cjs +4 -23
- package/dist/adonisjs/index.cjs.map +1 -1
- package/dist/adonisjs/index.d.cts +3 -15
- package/dist/adonisjs/index.d.ts +3 -15
- package/dist/adonisjs/index.js +3 -20
- package/dist/adonisjs/index.js.map +1 -1
- package/dist/adonisjs/middleware.cjs +43 -109
- package/dist/adonisjs/middleware.cjs.map +1 -1
- package/dist/adonisjs/middleware.d.cts +1 -16
- package/dist/adonisjs/middleware.d.ts +1 -16
- package/dist/adonisjs/middleware.js +43 -110
- package/dist/adonisjs/middleware.js.map +1 -1
- package/dist/adonisjs/provider.cjs +19 -87
- package/dist/adonisjs/provider.cjs.map +1 -1
- package/dist/adonisjs/provider.d.cts +0 -22
- package/dist/adonisjs/provider.d.ts +0 -22
- package/dist/adonisjs/provider.js +19 -88
- package/dist/adonisjs/provider.js.map +1 -1
- package/dist/adonisjs/stubs/config/apitally.stub +11 -15
- package/dist/bodyCapture.cjs +128 -0
- package/dist/bodyCapture.cjs.map +1 -0
- package/dist/bodyCapture.d.cts +31 -0
- package/dist/bodyCapture.d.ts +31 -0
- package/dist/bodyCapture.js +101 -0
- package/dist/bodyCapture.js.map +1 -0
- package/dist/config.cjs +209 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +42 -0
- package/dist/config.d.ts +42 -0
- package/dist/config.js +174 -0
- package/dist/config.js.map +1 -0
- package/dist/consumer.cjs +98 -0
- package/dist/consumer.cjs.map +1 -0
- package/dist/consumer.d.cts +13 -0
- package/dist/consumer.d.ts +13 -0
- package/dist/consumer.js +78 -0
- package/dist/consumer.js.map +1 -0
- package/dist/context.cjs +68 -0
- package/dist/context.cjs.map +1 -0
- package/dist/context.d.cts +29 -0
- package/dist/context.d.ts +29 -0
- package/dist/context.js +40 -0
- package/dist/context.js.map +1 -0
- package/dist/elysia/index.cjs +12 -13
- package/dist/elysia/index.cjs.map +1 -1
- package/dist/elysia/index.d.cts +7 -16
- package/dist/elysia/index.d.ts +7 -16
- package/dist/elysia/index.js +10 -2
- package/dist/elysia/index.js.map +1 -1
- package/dist/elysia/middleware.cjs +248 -0
- package/dist/elysia/middleware.cjs.map +1 -0
- package/dist/elysia/middleware.d.cts +13 -0
- package/dist/elysia/middleware.d.ts +13 -0
- package/dist/elysia/middleware.js +237 -0
- package/dist/elysia/middleware.js.map +1 -0
- package/dist/{loggers/index.cjs → elysia/routes.cjs} +16 -19
- package/dist/elysia/routes.cjs.map +1 -0
- package/dist/elysia/routes.d.cts +7 -0
- package/dist/elysia/routes.d.ts +7 -0
- package/dist/elysia/routes.js +14 -0
- package/dist/elysia/routes.js.map +1 -0
- package/dist/exceptions.cjs +75 -0
- package/dist/exceptions.cjs.map +1 -0
- package/dist/exceptions.d.cts +7 -0
- package/dist/exceptions.d.ts +7 -0
- package/dist/exceptions.js +49 -0
- package/dist/exceptions.js.map +1 -0
- package/dist/exportSerialization.cjs +56 -0
- package/dist/exportSerialization.cjs.map +1 -0
- package/dist/exportSerialization.d.cts +7 -0
- package/dist/exportSerialization.d.ts +7 -0
- package/dist/exportSerialization.js +32 -0
- package/dist/exportSerialization.js.map +1 -0
- package/dist/exportWorker.cjs +305 -0
- package/dist/exportWorker.cjs.map +1 -0
- package/dist/exportWorker.d.cts +46 -0
- package/dist/exportWorker.d.ts +46 -0
- package/dist/exportWorker.js +279 -0
- package/dist/exportWorker.js.map +1 -0
- package/dist/express/index.cjs +9 -4
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.d.cts +6 -10
- package/dist/express/index.d.ts +6 -10
- package/dist/express/index.js +8 -2
- package/dist/express/index.js.map +1 -1
- package/dist/express/install.cjs +45 -0
- package/dist/express/install.cjs.map +1 -0
- package/dist/express/install.d.cts +9 -0
- package/dist/express/install.d.ts +9 -0
- package/dist/express/install.js +21 -0
- package/dist/express/install.js.map +1 -0
- package/dist/express/middleware.cjs +80 -331
- package/dist/express/middleware.cjs.map +1 -1
- package/dist/express/middleware.d.cts +3 -21
- package/dist/express/middleware.d.ts +3 -21
- package/dist/express/middleware.js +81 -328
- package/dist/express/middleware.js.map +1 -1
- package/dist/express/register.cjs +20 -0
- package/dist/express/register.cjs.map +1 -0
- package/dist/express/register.d.cts +2 -0
- package/dist/express/register.d.ts +2 -0
- package/dist/express/register.js +19 -0
- package/dist/express/register.js.map +1 -0
- package/dist/express/routes.cjs +419 -0
- package/dist/express/routes.cjs.map +1 -0
- package/dist/express/routes.d.cts +14 -0
- package/dist/express/routes.d.ts +14 -0
- package/dist/express/routes.js +391 -0
- package/dist/express/routes.js.map +1 -0
- package/dist/fastify/index.cjs +10 -15
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.d.cts +6 -11
- package/dist/fastify/index.d.ts +6 -11
- package/dist/fastify/index.js +9 -3
- package/dist/fastify/index.js.map +1 -1
- package/dist/{common/logging.cjs → fastify/install.cjs} +15 -16
- package/dist/fastify/install.cjs.map +1 -0
- package/dist/fastify/install.d.cts +9 -0
- package/dist/fastify/install.d.ts +9 -0
- package/dist/fastify/install.js +15 -0
- package/dist/fastify/install.js.map +1 -0
- package/dist/fastify/middleware.cjs +118 -0
- package/dist/fastify/middleware.cjs.map +1 -0
- package/dist/fastify/middleware.d.cts +7 -0
- package/dist/fastify/middleware.d.ts +7 -0
- package/dist/fastify/middleware.js +97 -0
- package/dist/fastify/middleware.js.map +1 -0
- package/dist/{common/paramValidation.cjs → fastify/routes.cjs} +15 -17
- package/dist/fastify/routes.cjs.map +1 -0
- package/dist/fastify/routes.d.cts +8 -0
- package/dist/fastify/routes.d.ts +8 -0
- package/dist/fastify/routes.js +14 -0
- package/dist/fastify/routes.js.map +1 -0
- package/dist/h3/index.cjs +28 -4
- package/dist/h3/index.cjs.map +1 -1
- package/dist/h3/index.d.cts +7 -10
- package/dist/h3/index.d.ts +7 -10
- package/dist/h3/index.js +26 -2
- package/dist/h3/index.js.map +1 -1
- package/dist/h3/middleware.cjs +204 -0
- package/dist/h3/middleware.cjs.map +1 -0
- package/dist/h3/middleware.d.cts +5 -0
- package/dist/h3/middleware.d.ts +5 -0
- package/dist/h3/middleware.js +188 -0
- package/dist/h3/middleware.js.map +1 -0
- package/dist/h3/routes.cjs +66 -0
- package/dist/h3/routes.cjs.map +1 -0
- package/dist/h3/routes.d.cts +8 -0
- package/dist/h3/routes.d.ts +8 -0
- package/dist/h3/routes.js +41 -0
- package/dist/h3/routes.js.map +1 -0
- package/dist/hapi/index.cjs +15 -14
- package/dist/hapi/index.cjs.map +1 -1
- package/dist/hapi/index.d.cts +7 -10
- package/dist/hapi/index.d.ts +7 -10
- package/dist/hapi/index.js +14 -3
- package/dist/hapi/index.js.map +1 -1
- package/dist/{loggers/hapi.cjs → hapi/install.cjs} +20 -26
- package/dist/hapi/install.cjs.map +1 -0
- package/dist/hapi/install.d.cts +7 -0
- package/dist/hapi/install.d.ts +7 -0
- package/dist/hapi/install.js +22 -0
- package/dist/hapi/install.js.map +1 -0
- package/dist/hapi/middleware.cjs +158 -0
- package/dist/hapi/middleware.cjs.map +1 -0
- package/dist/hapi/middleware.d.cts +5 -0
- package/dist/hapi/middleware.d.ts +5 -0
- package/dist/hapi/middleware.js +137 -0
- package/dist/hapi/middleware.js.map +1 -0
- package/dist/hapi/routes.cjs +37 -0
- package/dist/hapi/routes.cjs.map +1 -0
- package/dist/hapi/routes.d.cts +8 -0
- package/dist/hapi/routes.d.ts +8 -0
- package/dist/hapi/routes.js +12 -0
- package/dist/hapi/routes.js.map +1 -0
- package/dist/hono/index.cjs +13 -3
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.d.cts +6 -10
- package/dist/hono/index.d.ts +6 -10
- package/dist/hono/index.js +13 -2
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/middleware.cjs +211 -127
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.d.cts +3 -18
- package/dist/hono/middleware.d.ts +3 -18
- package/dist/hono/middleware.js +216 -125
- package/dist/hono/middleware.js.map +1 -1
- package/dist/hono/routes.cjs +74 -0
- package/dist/hono/routes.cjs.map +1 -0
- package/dist/hono/routes.d.cts +8 -0
- package/dist/hono/routes.d.ts +8 -0
- package/dist/hono/routes.js +49 -0
- package/dist/hono/routes.js.map +1 -0
- package/dist/index.cjs +108 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -1
- package/dist/koa/index.cjs +13 -3
- package/dist/koa/index.cjs.map +1 -1
- package/dist/koa/index.d.cts +6 -10
- package/dist/koa/index.d.ts +6 -10
- package/dist/koa/index.js +13 -2
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/middleware.cjs +75 -184
- package/dist/koa/middleware.cjs.map +1 -1
- package/dist/koa/middleware.d.cts +3 -13
- package/dist/koa/middleware.d.ts +3 -13
- package/dist/koa/middleware.js +78 -183
- package/dist/koa/middleware.js.map +1 -1
- package/dist/koa/routes.cjs +71 -0
- package/dist/koa/routes.cjs.map +1 -0
- package/dist/koa/routes.d.cts +8 -0
- package/dist/koa/routes.d.ts +8 -0
- package/dist/koa/routes.js +46 -0
- package/dist/koa/routes.js.map +1 -0
- package/dist/logCapture.cjs +410 -0
- package/dist/logCapture.cjs.map +1 -0
- package/dist/logCapture.d.cts +16 -0
- package/dist/logCapture.d.ts +16 -0
- package/dist/logCapture.js +383 -0
- package/dist/logCapture.js.map +1 -0
- package/dist/logRecordExporter.cjs +83 -0
- package/dist/logRecordExporter.cjs.map +1 -0
- package/dist/logRecordExporter.d.cts +14 -0
- package/dist/logRecordExporter.d.ts +14 -0
- package/dist/logRecordExporter.js +59 -0
- package/dist/logRecordExporter.js.map +1 -0
- package/dist/logRecordProcessor.cjs +120 -0
- package/dist/logRecordProcessor.cjs.map +1 -0
- package/dist/logRecordProcessor.d.cts +23 -0
- package/dist/logRecordProcessor.d.ts +23 -0
- package/dist/logRecordProcessor.js +96 -0
- package/dist/logRecordProcessor.js.map +1 -0
- package/dist/{otel/index.cjs → logRecordTruncation.cjs} +10 -7
- package/dist/logRecordTruncation.cjs.map +1 -0
- package/dist/logRecordTruncation.d.cts +6 -0
- package/dist/logRecordTruncation.d.ts +6 -0
- package/dist/logRecordTruncation.js +8 -0
- package/dist/logRecordTruncation.js.map +1 -0
- package/dist/logger.cjs +62 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +7 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +34 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.cjs +171 -0
- package/dist/metrics.cjs.map +1 -0
- package/dist/metrics.d.cts +24 -0
- package/dist/metrics.d.ts +24 -0
- package/dist/metrics.js +153 -0
- package/dist/metrics.js.map +1 -0
- package/dist/nestjs/index.cjs +61 -71
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.d.cts +3 -11
- package/dist/nestjs/index.d.ts +3 -11
- package/dist/nestjs/index.js +61 -61
- package/dist/nestjs/index.js.map +1 -1
- package/dist/packageVersion.cjs +67 -0
- package/dist/packageVersion.cjs.map +1 -0
- package/dist/packageVersion.d.cts +5 -0
- package/dist/packageVersion.d.ts +5 -0
- package/dist/packageVersion.js +39 -0
- package/dist/packageVersion.js.map +1 -0
- package/dist/providers.cjs +149 -0
- package/dist/providers.cjs.map +1 -0
- package/dist/providers.d.cts +15 -0
- package/dist/providers.d.ts +15 -0
- package/dist/providers.js +136 -0
- package/dist/providers.js.map +1 -0
- package/dist/redaction.cjs +116 -0
- package/dist/redaction.cjs.map +1 -0
- package/dist/redaction.d.cts +17 -0
- package/dist/redaction.d.ts +17 -0
- package/dist/redaction.js +98 -0
- package/dist/redaction.js.map +1 -0
- package/dist/{common/packageVersions.cjs → requestAttributes.cjs} +21 -19
- package/dist/requestAttributes.cjs.map +1 -0
- package/dist/requestAttributes.d.cts +8 -0
- package/dist/requestAttributes.d.ts +8 -0
- package/dist/requestAttributes.js +22 -0
- package/dist/requestAttributes.js.map +1 -0
- package/dist/requestObservation.cjs +228 -0
- package/dist/requestObservation.cjs.map +1 -0
- package/dist/requestObservation.d.cts +60 -0
- package/dist/requestObservation.d.ts +60 -0
- package/dist/requestObservation.js +208 -0
- package/dist/requestObservation.js.map +1 -0
- package/dist/requestObservationNode.cjs +193 -0
- package/dist/requestObservationNode.cjs.map +1 -0
- package/dist/requestObservationNode.d.cts +29 -0
- package/dist/requestObservationNode.d.ts +29 -0
- package/dist/requestObservationNode.js +170 -0
- package/dist/requestObservationNode.js.map +1 -0
- package/dist/requestObservationWeb.cjs +202 -0
- package/dist/requestObservationWeb.cjs.map +1 -0
- package/dist/requestObservationWeb.d.cts +32 -0
- package/dist/requestObservationWeb.d.ts +32 -0
- package/dist/requestObservationWeb.js +182 -0
- package/dist/requestObservationWeb.js.map +1 -0
- package/dist/sentry.cjs +103 -0
- package/dist/sentry.cjs.map +1 -0
- package/dist/sentry.d.cts +3 -0
- package/dist/sentry.d.ts +3 -0
- package/dist/sentry.js +79 -0
- package/dist/sentry.js.map +1 -0
- package/dist/spanExporter.cjs +218 -0
- package/dist/spanExporter.cjs.map +1 -0
- package/dist/spanExporter.d.cts +33 -0
- package/dist/spanExporter.d.ts +33 -0
- package/dist/spanExporter.js +194 -0
- package/dist/spanExporter.js.map +1 -0
- package/dist/spanProcessor.cjs +523 -0
- package/dist/spanProcessor.cjs.map +1 -0
- package/dist/spanProcessor.d.cts +67 -0
- package/dist/spanProcessor.d.ts +67 -0
- package/dist/spanProcessor.js +501 -0
- package/dist/spanProcessor.js.map +1 -0
- package/dist/spool.cjs +314 -0
- package/dist/spool.cjs.map +1 -0
- package/dist/spool.d.cts +49 -0
- package/dist/spool.d.ts +49 -0
- package/dist/spool.js +297 -0
- package/dist/spool.js.map +1 -0
- package/dist/startup.cjs +93 -0
- package/dist/startup.cjs.map +1 -0
- package/dist/startup.d.cts +15 -0
- package/dist/startup.d.ts +15 -0
- package/dist/startup.js +68 -0
- package/dist/startup.js.map +1 -0
- package/dist/tracing.cjs +116 -0
- package/dist/tracing.cjs.map +1 -0
- package/dist/tracing.d.cts +5 -0
- package/dist/tracing.d.ts +5 -0
- package/dist/tracing.js +96 -0
- package/dist/tracing.js.map +1 -0
- package/package.json +113 -155
- package/dist/common/client.cjs +0 -335
- package/dist/common/client.cjs.map +0 -1
- package/dist/common/client.d.cts +0 -50
- package/dist/common/client.d.ts +0 -50
- package/dist/common/client.js +0 -302
- package/dist/common/client.js.map +0 -1
- package/dist/common/consumerRegistry.cjs +0 -84
- package/dist/common/consumerRegistry.cjs.map +0 -1
- package/dist/common/consumerRegistry.d.cts +0 -20
- package/dist/common/consumerRegistry.d.ts +0 -20
- package/dist/common/consumerRegistry.js +0 -61
- package/dist/common/consumerRegistry.js.map +0 -1
- package/dist/common/headers.cjs +0 -55
- package/dist/common/headers.cjs.map +0 -1
- package/dist/common/headers.d.cts +0 -6
- package/dist/common/headers.d.ts +0 -6
- package/dist/common/headers.js +0 -31
- package/dist/common/headers.js.map +0 -1
- package/dist/common/instance.cjs +0 -158
- package/dist/common/instance.cjs.map +0 -1
- package/dist/common/instance.d.cts +0 -4
- package/dist/common/instance.d.ts +0 -4
- package/dist/common/instance.js +0 -134
- package/dist/common/instance.js.map +0 -1
- package/dist/common/logging.cjs.map +0 -1
- package/dist/common/logging.d.cts +0 -11
- package/dist/common/logging.d.ts +0 -11
- package/dist/common/logging.js +0 -17
- package/dist/common/logging.js.map +0 -1
- package/dist/common/packageVersions.cjs.map +0 -1
- package/dist/common/packageVersions.d.cts +0 -3
- package/dist/common/packageVersions.d.ts +0 -3
- package/dist/common/packageVersions.js +0 -21
- package/dist/common/packageVersions.js.map +0 -1
- package/dist/common/paramValidation.cjs.map +0 -1
- package/dist/common/paramValidation.d.cts +0 -4
- package/dist/common/paramValidation.d.ts +0 -4
- package/dist/common/paramValidation.js +0 -17
- package/dist/common/paramValidation.js.map +0 -1
- package/dist/common/requestCounter.cjs +0 -109
- package/dist/common/requestCounter.cjs.map +0 -1
- package/dist/common/requestCounter.d.cts +0 -24
- package/dist/common/requestCounter.d.ts +0 -24
- package/dist/common/requestCounter.js +0 -90
- package/dist/common/requestCounter.js.map +0 -1
- package/dist/common/requestLogger.cjs +0 -541
- package/dist/common/requestLogger.cjs.map +0 -1
- package/dist/common/requestLogger.d.cts +0 -85
- package/dist/common/requestLogger.d.ts +0 -85
- package/dist/common/requestLogger.js +0 -507
- package/dist/common/requestLogger.js.map +0 -1
- package/dist/common/resources.cjs +0 -49
- package/dist/common/resources.cjs.map +0 -1
- package/dist/common/resources.d.cts +0 -6
- package/dist/common/resources.d.ts +0 -6
- package/dist/common/resources.js +0 -26
- package/dist/common/resources.js.map +0 -1
- package/dist/common/response.cjs +0 -104
- package/dist/common/response.cjs.map +0 -1
- package/dist/common/response.d.cts +0 -15
- package/dist/common/response.d.ts +0 -15
- package/dist/common/response.js +0 -80
- package/dist/common/response.js.map +0 -1
- package/dist/common/sentry.cjs +0 -56
- package/dist/common/sentry.cjs.map +0 -1
- package/dist/common/sentry.d.cts +0 -6
- package/dist/common/sentry.d.ts +0 -6
- package/dist/common/sentry.js +0 -23
- package/dist/common/sentry.js.map +0 -1
- package/dist/common/serverErrorCounter.cjs +0 -121
- package/dist/common/serverErrorCounter.cjs.map +0 -1
- package/dist/common/serverErrorCounter.d.cts +0 -23
- package/dist/common/serverErrorCounter.d.ts +0 -23
- package/dist/common/serverErrorCounter.js +0 -97
- package/dist/common/serverErrorCounter.js.map +0 -1
- package/dist/common/spanCollector.cjs +0 -199
- package/dist/common/spanCollector.cjs.map +0 -1
- package/dist/common/spanCollector.d.cts +0 -45
- package/dist/common/spanCollector.d.ts +0 -45
- package/dist/common/spanCollector.js +0 -176
- package/dist/common/spanCollector.js.map +0 -1
- package/dist/common/tempGzipFile.cjs +0 -125
- package/dist/common/tempGzipFile.cjs.map +0 -1
- package/dist/common/tempGzipFile.d.cts +0 -19
- package/dist/common/tempGzipFile.d.ts +0 -19
- package/dist/common/tempGzipFile.js +0 -102
- package/dist/common/tempGzipFile.js.map +0 -1
- package/dist/common/types.cjs +0 -17
- package/dist/common/types.cjs.map +0 -1
- package/dist/common/types.d.cts +0 -95
- package/dist/common/types.d.ts +0 -95
- package/dist/common/types.js +0 -1
- package/dist/common/types.js.map +0 -1
- package/dist/common/validationErrorCounter.cjs +0 -74
- package/dist/common/validationErrorCounter.cjs.map +0 -1
- package/dist/common/validationErrorCounter.d.cts +0 -20
- package/dist/common/validationErrorCounter.d.ts +0 -20
- package/dist/common/validationErrorCounter.js +0 -55
- package/dist/common/validationErrorCounter.js.map +0 -1
- package/dist/elysia/plugin.cjs +0 -237
- package/dist/elysia/plugin.cjs.map +0 -1
- package/dist/elysia/plugin.d.cts +0 -70
- package/dist/elysia/plugin.d.ts +0 -70
- package/dist/elysia/plugin.js +0 -218
- package/dist/elysia/plugin.js.map +0 -1
- package/dist/elysia/utils.cjs +0 -77
- package/dist/elysia/utils.cjs.map +0 -1
- package/dist/elysia/utils.d.cts +0 -14
- package/dist/elysia/utils.d.ts +0 -14
- package/dist/elysia/utils.js +0 -54
- package/dist/elysia/utils.js.map +0 -1
- package/dist/express/utils.cjs +0 -217
- package/dist/express/utils.cjs.map +0 -1
- package/dist/express/utils.d.cts +0 -37
- package/dist/express/utils.d.ts +0 -37
- package/dist/express/utils.js +0 -189
- package/dist/express/utils.js.map +0 -1
- package/dist/fastify/plugin.cjs +0 -316
- package/dist/fastify/plugin.cjs.map +0 -1
- package/dist/fastify/plugin.d.cts +0 -34
- package/dist/fastify/plugin.d.ts +0 -34
- package/dist/fastify/plugin.js +0 -282
- package/dist/fastify/plugin.js.map +0 -1
- package/dist/h3/plugin.cjs +0 -183
- package/dist/h3/plugin.cjs.map +0 -1
- package/dist/h3/plugin.d.cts +0 -27
- package/dist/h3/plugin.d.ts +0 -27
- package/dist/h3/plugin.js +0 -159
- package/dist/h3/plugin.js.map +0 -1
- package/dist/h3/utils.cjs +0 -77
- package/dist/h3/utils.cjs.map +0 -1
- package/dist/h3/utils.d.cts +0 -14
- package/dist/h3/utils.d.ts +0 -14
- package/dist/h3/utils.js +0 -54
- package/dist/h3/utils.js.map +0 -1
- package/dist/hapi/plugin.cjs +0 -210
- package/dist/hapi/plugin.cjs.map +0 -1
- package/dist/hapi/plugin.d.cts +0 -40
- package/dist/hapi/plugin.d.ts +0 -40
- package/dist/hapi/plugin.js +0 -187
- package/dist/hapi/plugin.js.map +0 -1
- package/dist/hapi/utils.cjs +0 -77
- package/dist/hapi/utils.cjs.map +0 -1
- package/dist/hapi/utils.d.cts +0 -16
- package/dist/hapi/utils.d.ts +0 -16
- package/dist/hapi/utils.js +0 -53
- package/dist/hapi/utils.js.map +0 -1
- package/dist/hono/utils.cjs +0 -113
- package/dist/hono/utils.cjs.map +0 -1
- package/dist/hono/utils.d.cts +0 -16
- package/dist/hono/utils.d.ts +0 -16
- package/dist/hono/utils.js +0 -88
- package/dist/hono/utils.js.map +0 -1
- package/dist/loggers/console.cjs +0 -67
- package/dist/loggers/console.cjs.map +0 -1
- package/dist/loggers/console.d.cts +0 -11
- package/dist/loggers/console.d.ts +0 -11
- package/dist/loggers/console.js +0 -44
- package/dist/loggers/console.js.map +0 -1
- package/dist/loggers/hapi.cjs.map +0 -1
- package/dist/loggers/hapi.d.cts +0 -12
- package/dist/loggers/hapi.d.ts +0 -12
- package/dist/loggers/hapi.js +0 -29
- package/dist/loggers/hapi.js.map +0 -1
- package/dist/loggers/index.cjs.map +0 -1
- package/dist/loggers/index.d.cts +0 -13
- package/dist/loggers/index.d.ts +0 -13
- package/dist/loggers/index.js +0 -13
- package/dist/loggers/index.js.map +0 -1
- package/dist/loggers/nestjs.cjs +0 -104
- package/dist/loggers/nestjs.cjs.map +0 -1
- package/dist/loggers/nestjs.d.cts +0 -11
- package/dist/loggers/nestjs.d.ts +0 -11
- package/dist/loggers/nestjs.js +0 -71
- package/dist/loggers/nestjs.js.map +0 -1
- package/dist/loggers/pino.cjs +0 -152
- package/dist/loggers/pino.cjs.map +0 -1
- package/dist/loggers/pino.d.cts +0 -11
- package/dist/loggers/pino.d.ts +0 -11
- package/dist/loggers/pino.js +0 -119
- package/dist/loggers/pino.js.map +0 -1
- package/dist/loggers/utils.cjs +0 -64
- package/dist/loggers/utils.cjs.map +0 -1
- package/dist/loggers/utils.d.cts +0 -6
- package/dist/loggers/utils.d.ts +0 -6
- package/dist/loggers/utils.js +0 -40
- package/dist/loggers/utils.js.map +0 -1
- package/dist/loggers/winston.cjs +0 -101
- package/dist/loggers/winston.cjs.map +0 -1
- package/dist/loggers/winston.d.cts +0 -11
- package/dist/loggers/winston.d.ts +0 -11
- package/dist/loggers/winston.js +0 -68
- package/dist/loggers/winston.js.map +0 -1
- package/dist/otel/index.cjs.map +0 -1
- package/dist/otel/index.d.cts +0 -2
- package/dist/otel/index.d.ts +0 -2
- package/dist/otel/index.js +0 -5
- package/dist/otel/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/requestObservation.ts"],"sourcesContent":["import { type Attributes, type Context, SpanKind, SpanStatusCode, trace } from \"@opentelemetry/api\";\nimport { getRPCMetadata, type RPCMetadata, RPCType, setRPCMetadata } from \"@opentelemetry/core\";\nimport type { BodyCapture, CapturedBody } from \"./bodyCapture.js\";\nimport { getConfig } from \"./config.js\";\nimport {\n attachRequestRecordToRpcMetadata,\n getConsumerHolder,\n type RequestRecord,\n type SpanHandle,\n withRequestHolders,\n} from \"./context.js\";\nimport { coerceToException } from \"./exceptions.js\";\nimport { logWarning } from \"./logger.js\";\nimport { writeRequestAttribute } from \"./requestAttributes.js\";\nimport {\n getActiveSpanPipeline,\n isApitallySpanProcessorDeclared,\n type RequestStash,\n} from \"./spanProcessor.js\";\n\ninterface StartRequestObservationOptions {\n activeContext: Context;\n extractedContext: Context;\n tracerName: string;\n method: string;\n startAttributes: Attributes;\n requestBodyCapture: BodyCapture;\n}\n\nexport interface StartedRequestObservation {\n requestRecord: RequestRecord;\n requestContext: Context;\n spanHandle: SpanHandle;\n rpcMetadata?: RPCMetadata;\n}\n\nexport interface HttpRequestStartAttributeInput {\n method: string;\n path?: string;\n query?: string;\n scheme?: string;\n serverAddress?: string;\n fullUrl?: string;\n clientAddress?: string;\n userAgent?: string;\n requestBodySize?: number;\n}\n\nexport function resolveHttpRequestStartAttributes(\n input: HttpRequestStartAttributeInput,\n): Attributes {\n const attributes: Attributes = { \"http.request.method\": input.method };\n const optionalAttributes: [string, string | number | undefined][] = [\n [\"url.path\", input.path],\n [\"url.query\", input.query],\n [\"url.scheme\", input.scheme],\n [\"url.full\", input.fullUrl],\n [\"server.address\", input.serverAddress],\n [\"client.address\", input.clientAddress],\n [\"user_agent.original\", input.userAgent],\n [\"http.request.body.size\", input.requestBodySize],\n ];\n for (const [name, value] of optionalAttributes) {\n if (value !== undefined) {\n attributes[name] = value;\n }\n }\n return attributes;\n}\n\nexport function startRequestObservation(\n options: StartRequestObservationOptions,\n): StartedRequestObservation {\n const {\n activeContext,\n extractedContext,\n tracerName,\n method,\n startAttributes,\n requestBodyCapture,\n } = options;\n const requestRecord: RequestRecord = { attributes: {} };\n const spanHandle: SpanHandle = {};\n const consumerHolder = getConsumerHolder(activeContext) ?? {};\n // Metrics and the exported span copy read from the request record, so the\n // start attributes are mirrored into it on every path, span or no span.\n Object.assign(requestRecord.attributes, startAttributes);\n const activeSpan = trace.getSpan(activeContext);\n const resolveUnavailableSpanDropReason = (): RequestRecord[\"dropReason\"] =>\n getActiveSpanPipeline()?.resolveRequestDropReasonBeforeSampling(startAttributes) ??\n \"sampled-out\";\n let requestContext: Context;\n // Span kind is not part of the OTel API surface, so read the SDK-level\n // property from whichever package copy produced the span.\n if (activeSpan?.isRecording() && (activeSpan as { kind?: unknown }).kind === SpanKind.SERVER) {\n // A SERVER span produced by the user's own instrumentation is adopted:\n // no second span, and the request runs under the user's context.\n spanHandle.span = activeSpan;\n requestRecord.serverSpanId = activeSpan.spanContext().spanId;\n if (getActiveSpanPipeline()?.isRequestInFlight(requestRecord.serverSpanId) !== true) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n }\n requestContext = withRequestHolders(activeContext, spanHandle, requestRecord, consumerHolder);\n } else if (activeSpan && !activeSpan.isRecording()) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n if (requestRecord.dropReason === \"sampled-out\") {\n warnAboutNonRecordingServerSpan();\n }\n requestContext = withRequestHolders(activeContext, spanHandle, requestRecord, consumerHolder);\n } else {\n requestContext = withRequestHolders(\n extractedContext,\n spanHandle,\n requestRecord,\n consumerHolder,\n );\n const ownSpan = trace\n .getTracer(tracerName)\n .startSpan(method, { kind: SpanKind.SERVER, attributes: startAttributes }, requestContext);\n if (!ownSpan.isRecording()) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n if (requestRecord.dropReason === \"sampled-out\") {\n warnAboutNonRecordingServerSpan();\n }\n } else {\n spanHandle.span = ownSpan;\n spanHandle.ownSpan = ownSpan;\n if (isApitallySpanProcessorDeclared() && requestRecord.serverSpanId === undefined) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n if (requestRecord.dropReason === \"sampled-out\") {\n warnAboutUnattachedSpanProcessor();\n }\n }\n }\n // A non-recording span still carries a valid span context, so user child\n // spans parent to it and parent-based samplers drop them consistently.\n requestContext = trace.setSpan(requestContext, ownSpan);\n }\n\n // Middleware-based span producers inspect OTel RPC metadata to demote duplicate\n // transport spans; completion adds the route.\n let rpcMetadata = getRPCMetadata(requestContext);\n if (!rpcMetadata && spanHandle.span) {\n rpcMetadata = { type: RPCType.HTTP, span: spanHandle.span };\n requestContext = setRPCMetadata(requestContext, rpcMetadata);\n }\n attachRequestRecordToRpcMetadata(rpcMetadata, requestRecord);\n if (requestRecord.dropReason !== undefined) {\n requestBodyCapture.stopBuffering();\n }\n return { requestRecord, requestContext, spanHandle, rpcMetadata };\n}\n\nexport interface RequestObservation {\n requestRecord: RequestRecord;\n spanHandle: SpanHandle;\n rpcMetadata?: RPCMetadata;\n method: string;\n startTimeMillis: number;\n}\n\nexport interface FinalizeRequestObservationOptions {\n observation: RequestObservation;\n completedAtMillis: number;\n statusCode: number;\n route?: string;\n clientAddress?: string;\n requestHeaders: Headers | Record<string, string | string[] | undefined>;\n responseHeaders: Headers | Record<string, string | number | string[] | undefined>;\n capturedRequestBody?: CapturedBody;\n capturedResponseBody?: CapturedBody;\n}\n\nexport function finalizeRequestObservation(options: FinalizeRequestObservationOptions): void {\n const { observation, statusCode, route } = options;\n const { requestRecord, spanHandle, rpcMetadata, method } = observation;\n requestRecord.durationSeconds = (options.completedAtMillis - observation.startTimeMillis) / 1000;\n const { span, ownSpan } = spanHandle;\n if (options.clientAddress !== undefined) {\n writeRequestAttribute(span, requestRecord, \"client.address\", options.clientAddress);\n }\n writeRequestAttribute(span, requestRecord, \"http.response.status_code\", statusCode);\n const requestBodySize = options.capturedRequestBody?.size;\n if (requestBodySize !== undefined) {\n writeRequestAttribute(span, requestRecord, \"http.request.body.size\", requestBodySize);\n }\n const responseBodySize = options.capturedResponseBody?.size;\n if (responseBodySize !== undefined) {\n writeRequestAttribute(span, requestRecord, \"http.response.body.size\", responseBodySize);\n }\n if (route !== undefined) {\n writeRequestAttribute(span, requestRecord, \"http.route\", route);\n if (rpcMetadata) {\n rpcMetadata.route = route;\n }\n if (ownSpan?.isRecording()) {\n ownSpan.updateName(`${method} ${route}`);\n }\n } else {\n // An empty route clears one set by the producing instrumentation; request\n // metrics omit empty routes.\n requestRecord.attributes[\"http.route\"] = \"\";\n }\n if (ownSpan && statusCode >= 500) {\n ownSpan.setStatus({ code: SpanStatusCode.ERROR });\n }\n // A dropped request's spans are never released, so a stash entry for it\n // would sit unconsumed until the cap evicts it.\n if (requestRecord.serverSpanId !== undefined && requestRecord.dropReason === undefined) {\n const config = getConfig();\n const stash: RequestStash = {};\n if (config.captureRequestHeaders) {\n stash.requestHeaders = normalizeHeaders(options.requestHeaders);\n }\n if (config.captureResponseHeaders) {\n stash.responseHeaders = normalizeHeaders(options.responseHeaders);\n }\n const requestBody = options.capturedRequestBody?.body;\n if (requestBody) {\n stash.requestBody = requestBody;\n }\n const responseBody = options.capturedResponseBody?.body;\n if (responseBody) {\n stash.responseBody = responseBody;\n }\n if (Object.keys(stash).length > 0) {\n getActiveSpanPipeline()?.updateStash(requestRecord.serverSpanId, stash);\n }\n }\n ownSpan?.end(options.completedAtMillis);\n getActiveSpanPipeline()?.handleTransportCompletion(requestRecord);\n}\n\nexport interface FinalizeRequestObservationWithErrorOptions {\n requestRecord: RequestRecord;\n spanHandle: SpanHandle;\n error: unknown;\n durationSeconds: number;\n}\n\nexport function finalizeRequestObservationWithError(\n options: FinalizeRequestObservationWithErrorOptions,\n): void {\n const { requestRecord, spanHandle, error, durationSeconds } = options;\n requestRecord.durationSeconds = durationSeconds;\n if (spanHandle.span?.isRecording()) {\n spanHandle.span.recordException(coerceToException(error));\n }\n if (spanHandle.ownSpan) {\n spanHandle.ownSpan.setStatus({ code: SpanStatusCode.ERROR });\n spanHandle.ownSpan.end();\n }\n getActiveSpanPipeline()?.handleTransportCompletion(requestRecord);\n}\n\n// Values remain raw so all redaction happens at the export boundary.\nfunction normalizeHeaders(\n headers: Headers | Record<string, string | number | string[] | undefined>,\n): Record<string, string | string[]> {\n const normalized: Record<string, string | string[]> = {};\n if (isWebHeaders(headers)) {\n // The Headers API combines repeated values except Set-Cookie.\n for (const [name, value] of headers) {\n const existing = normalized[name];\n if (existing === undefined) {\n normalized[name] = value;\n } else if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n normalized[name] = [existing, value];\n }\n }\n return normalized;\n }\n for (const [name, value] of Object.entries(headers)) {\n if (value !== undefined) {\n normalized[name.toLowerCase()] = Array.isArray(value) ? value : String(value);\n }\n }\n return normalized;\n}\n\n// Duck-typed on iterability: a plain header record has no Symbol.iterator, and\n// the Headers instance may come from another realm's implementation.\nfunction isWebHeaders(headers: object): headers is Headers {\n return typeof (headers as Headers)[Symbol.iterator] === \"function\";\n}\n\nfunction warnAboutNonRecordingServerSpan(): void {\n logWarning(\n \"The OpenTelemetry sampler did not sample the SERVER span of a request. Only sampled requests are exported to Apitally as traces and request logs. Request metrics include all requests.\",\n );\n}\n\nfunction warnAboutUnattachedSpanProcessor(): void {\n logWarning(\n \"The recording OpenTelemetry SERVER span created for a request did not reach ApitallySpanProcessor. Traces and request logs are unavailable while request metrics continue. To resolve this, add the ApitallySpanProcessor instance to your tracer provider's spanProcessors constructor option or the NodeSDK spanProcessors option.\",\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Context, Attributes } from '@opentelemetry/api';
|
|
2
|
+
import { RPCMetadata } from '@opentelemetry/core';
|
|
3
|
+
import { CapturedBody, BodyCapture } from './bodyCapture.cjs';
|
|
4
|
+
import { RequestRecord, SpanHandle } from './context.cjs';
|
|
5
|
+
|
|
6
|
+
interface StartRequestObservationOptions {
|
|
7
|
+
activeContext: Context;
|
|
8
|
+
extractedContext: Context;
|
|
9
|
+
tracerName: string;
|
|
10
|
+
method: string;
|
|
11
|
+
startAttributes: Attributes;
|
|
12
|
+
requestBodyCapture: BodyCapture;
|
|
13
|
+
}
|
|
14
|
+
interface StartedRequestObservation {
|
|
15
|
+
requestRecord: RequestRecord;
|
|
16
|
+
requestContext: Context;
|
|
17
|
+
spanHandle: SpanHandle;
|
|
18
|
+
rpcMetadata?: RPCMetadata;
|
|
19
|
+
}
|
|
20
|
+
interface HttpRequestStartAttributeInput {
|
|
21
|
+
method: string;
|
|
22
|
+
path?: string;
|
|
23
|
+
query?: string;
|
|
24
|
+
scheme?: string;
|
|
25
|
+
serverAddress?: string;
|
|
26
|
+
fullUrl?: string;
|
|
27
|
+
clientAddress?: string;
|
|
28
|
+
userAgent?: string;
|
|
29
|
+
requestBodySize?: number;
|
|
30
|
+
}
|
|
31
|
+
declare function resolveHttpRequestStartAttributes(input: HttpRequestStartAttributeInput): Attributes;
|
|
32
|
+
declare function startRequestObservation(options: StartRequestObservationOptions): StartedRequestObservation;
|
|
33
|
+
interface RequestObservation {
|
|
34
|
+
requestRecord: RequestRecord;
|
|
35
|
+
spanHandle: SpanHandle;
|
|
36
|
+
rpcMetadata?: RPCMetadata;
|
|
37
|
+
method: string;
|
|
38
|
+
startTimeMillis: number;
|
|
39
|
+
}
|
|
40
|
+
interface FinalizeRequestObservationOptions {
|
|
41
|
+
observation: RequestObservation;
|
|
42
|
+
completedAtMillis: number;
|
|
43
|
+
statusCode: number;
|
|
44
|
+
route?: string;
|
|
45
|
+
clientAddress?: string;
|
|
46
|
+
requestHeaders: Headers | Record<string, string | string[] | undefined>;
|
|
47
|
+
responseHeaders: Headers | Record<string, string | number | string[] | undefined>;
|
|
48
|
+
capturedRequestBody?: CapturedBody;
|
|
49
|
+
capturedResponseBody?: CapturedBody;
|
|
50
|
+
}
|
|
51
|
+
declare function finalizeRequestObservation(options: FinalizeRequestObservationOptions): void;
|
|
52
|
+
interface FinalizeRequestObservationWithErrorOptions {
|
|
53
|
+
requestRecord: RequestRecord;
|
|
54
|
+
spanHandle: SpanHandle;
|
|
55
|
+
error: unknown;
|
|
56
|
+
durationSeconds: number;
|
|
57
|
+
}
|
|
58
|
+
declare function finalizeRequestObservationWithError(options: FinalizeRequestObservationWithErrorOptions): void;
|
|
59
|
+
|
|
60
|
+
export { type FinalizeRequestObservationOptions, type FinalizeRequestObservationWithErrorOptions, type HttpRequestStartAttributeInput, type RequestObservation, type StartedRequestObservation, finalizeRequestObservation, finalizeRequestObservationWithError, resolveHttpRequestStartAttributes, startRequestObservation };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Context, Attributes } from '@opentelemetry/api';
|
|
2
|
+
import { RPCMetadata } from '@opentelemetry/core';
|
|
3
|
+
import { CapturedBody, BodyCapture } from './bodyCapture.js';
|
|
4
|
+
import { RequestRecord, SpanHandle } from './context.js';
|
|
5
|
+
|
|
6
|
+
interface StartRequestObservationOptions {
|
|
7
|
+
activeContext: Context;
|
|
8
|
+
extractedContext: Context;
|
|
9
|
+
tracerName: string;
|
|
10
|
+
method: string;
|
|
11
|
+
startAttributes: Attributes;
|
|
12
|
+
requestBodyCapture: BodyCapture;
|
|
13
|
+
}
|
|
14
|
+
interface StartedRequestObservation {
|
|
15
|
+
requestRecord: RequestRecord;
|
|
16
|
+
requestContext: Context;
|
|
17
|
+
spanHandle: SpanHandle;
|
|
18
|
+
rpcMetadata?: RPCMetadata;
|
|
19
|
+
}
|
|
20
|
+
interface HttpRequestStartAttributeInput {
|
|
21
|
+
method: string;
|
|
22
|
+
path?: string;
|
|
23
|
+
query?: string;
|
|
24
|
+
scheme?: string;
|
|
25
|
+
serverAddress?: string;
|
|
26
|
+
fullUrl?: string;
|
|
27
|
+
clientAddress?: string;
|
|
28
|
+
userAgent?: string;
|
|
29
|
+
requestBodySize?: number;
|
|
30
|
+
}
|
|
31
|
+
declare function resolveHttpRequestStartAttributes(input: HttpRequestStartAttributeInput): Attributes;
|
|
32
|
+
declare function startRequestObservation(options: StartRequestObservationOptions): StartedRequestObservation;
|
|
33
|
+
interface RequestObservation {
|
|
34
|
+
requestRecord: RequestRecord;
|
|
35
|
+
spanHandle: SpanHandle;
|
|
36
|
+
rpcMetadata?: RPCMetadata;
|
|
37
|
+
method: string;
|
|
38
|
+
startTimeMillis: number;
|
|
39
|
+
}
|
|
40
|
+
interface FinalizeRequestObservationOptions {
|
|
41
|
+
observation: RequestObservation;
|
|
42
|
+
completedAtMillis: number;
|
|
43
|
+
statusCode: number;
|
|
44
|
+
route?: string;
|
|
45
|
+
clientAddress?: string;
|
|
46
|
+
requestHeaders: Headers | Record<string, string | string[] | undefined>;
|
|
47
|
+
responseHeaders: Headers | Record<string, string | number | string[] | undefined>;
|
|
48
|
+
capturedRequestBody?: CapturedBody;
|
|
49
|
+
capturedResponseBody?: CapturedBody;
|
|
50
|
+
}
|
|
51
|
+
declare function finalizeRequestObservation(options: FinalizeRequestObservationOptions): void;
|
|
52
|
+
interface FinalizeRequestObservationWithErrorOptions {
|
|
53
|
+
requestRecord: RequestRecord;
|
|
54
|
+
spanHandle: SpanHandle;
|
|
55
|
+
error: unknown;
|
|
56
|
+
durationSeconds: number;
|
|
57
|
+
}
|
|
58
|
+
declare function finalizeRequestObservationWithError(options: FinalizeRequestObservationWithErrorOptions): void;
|
|
59
|
+
|
|
60
|
+
export { type FinalizeRequestObservationOptions, type FinalizeRequestObservationWithErrorOptions, type HttpRequestStartAttributeInput, type RequestObservation, type StartedRequestObservation, finalizeRequestObservation, finalizeRequestObservationWithError, resolveHttpRequestStartAttributes, startRequestObservation };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
2
|
+
import { getRPCMetadata, RPCType, setRPCMetadata } from "@opentelemetry/core";
|
|
3
|
+
import { getConfig } from "./config.js";
|
|
4
|
+
import {
|
|
5
|
+
attachRequestRecordToRpcMetadata,
|
|
6
|
+
getConsumerHolder,
|
|
7
|
+
withRequestHolders
|
|
8
|
+
} from "./context.js";
|
|
9
|
+
import { coerceToException } from "./exceptions.js";
|
|
10
|
+
import { logWarning } from "./logger.js";
|
|
11
|
+
import { writeRequestAttribute } from "./requestAttributes.js";
|
|
12
|
+
import {
|
|
13
|
+
getActiveSpanPipeline,
|
|
14
|
+
isApitallySpanProcessorDeclared
|
|
15
|
+
} from "./spanProcessor.js";
|
|
16
|
+
function resolveHttpRequestStartAttributes(input) {
|
|
17
|
+
const attributes = { "http.request.method": input.method };
|
|
18
|
+
const optionalAttributes = [
|
|
19
|
+
["url.path", input.path],
|
|
20
|
+
["url.query", input.query],
|
|
21
|
+
["url.scheme", input.scheme],
|
|
22
|
+
["url.full", input.fullUrl],
|
|
23
|
+
["server.address", input.serverAddress],
|
|
24
|
+
["client.address", input.clientAddress],
|
|
25
|
+
["user_agent.original", input.userAgent],
|
|
26
|
+
["http.request.body.size", input.requestBodySize]
|
|
27
|
+
];
|
|
28
|
+
for (const [name, value] of optionalAttributes) {
|
|
29
|
+
if (value !== void 0) {
|
|
30
|
+
attributes[name] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return attributes;
|
|
34
|
+
}
|
|
35
|
+
function startRequestObservation(options) {
|
|
36
|
+
const {
|
|
37
|
+
activeContext,
|
|
38
|
+
extractedContext,
|
|
39
|
+
tracerName,
|
|
40
|
+
method,
|
|
41
|
+
startAttributes,
|
|
42
|
+
requestBodyCapture
|
|
43
|
+
} = options;
|
|
44
|
+
const requestRecord = { attributes: {} };
|
|
45
|
+
const spanHandle = {};
|
|
46
|
+
const consumerHolder = getConsumerHolder(activeContext) ?? {};
|
|
47
|
+
Object.assign(requestRecord.attributes, startAttributes);
|
|
48
|
+
const activeSpan = trace.getSpan(activeContext);
|
|
49
|
+
const resolveUnavailableSpanDropReason = () => getActiveSpanPipeline()?.resolveRequestDropReasonBeforeSampling(startAttributes) ?? "sampled-out";
|
|
50
|
+
let requestContext;
|
|
51
|
+
if (activeSpan?.isRecording() && activeSpan.kind === SpanKind.SERVER) {
|
|
52
|
+
spanHandle.span = activeSpan;
|
|
53
|
+
requestRecord.serverSpanId = activeSpan.spanContext().spanId;
|
|
54
|
+
if (getActiveSpanPipeline()?.isRequestInFlight(requestRecord.serverSpanId) !== true) {
|
|
55
|
+
requestRecord.dropReason = resolveUnavailableSpanDropReason();
|
|
56
|
+
}
|
|
57
|
+
requestContext = withRequestHolders(activeContext, spanHandle, requestRecord, consumerHolder);
|
|
58
|
+
} else if (activeSpan && !activeSpan.isRecording()) {
|
|
59
|
+
requestRecord.dropReason = resolveUnavailableSpanDropReason();
|
|
60
|
+
if (requestRecord.dropReason === "sampled-out") {
|
|
61
|
+
warnAboutNonRecordingServerSpan();
|
|
62
|
+
}
|
|
63
|
+
requestContext = withRequestHolders(activeContext, spanHandle, requestRecord, consumerHolder);
|
|
64
|
+
} else {
|
|
65
|
+
requestContext = withRequestHolders(
|
|
66
|
+
extractedContext,
|
|
67
|
+
spanHandle,
|
|
68
|
+
requestRecord,
|
|
69
|
+
consumerHolder
|
|
70
|
+
);
|
|
71
|
+
const ownSpan = trace.getTracer(tracerName).startSpan(method, { kind: SpanKind.SERVER, attributes: startAttributes }, requestContext);
|
|
72
|
+
if (!ownSpan.isRecording()) {
|
|
73
|
+
requestRecord.dropReason = resolveUnavailableSpanDropReason();
|
|
74
|
+
if (requestRecord.dropReason === "sampled-out") {
|
|
75
|
+
warnAboutNonRecordingServerSpan();
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
spanHandle.span = ownSpan;
|
|
79
|
+
spanHandle.ownSpan = ownSpan;
|
|
80
|
+
if (isApitallySpanProcessorDeclared() && requestRecord.serverSpanId === void 0) {
|
|
81
|
+
requestRecord.dropReason = resolveUnavailableSpanDropReason();
|
|
82
|
+
if (requestRecord.dropReason === "sampled-out") {
|
|
83
|
+
warnAboutUnattachedSpanProcessor();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
requestContext = trace.setSpan(requestContext, ownSpan);
|
|
88
|
+
}
|
|
89
|
+
let rpcMetadata = getRPCMetadata(requestContext);
|
|
90
|
+
if (!rpcMetadata && spanHandle.span) {
|
|
91
|
+
rpcMetadata = { type: RPCType.HTTP, span: spanHandle.span };
|
|
92
|
+
requestContext = setRPCMetadata(requestContext, rpcMetadata);
|
|
93
|
+
}
|
|
94
|
+
attachRequestRecordToRpcMetadata(rpcMetadata, requestRecord);
|
|
95
|
+
if (requestRecord.dropReason !== void 0) {
|
|
96
|
+
requestBodyCapture.stopBuffering();
|
|
97
|
+
}
|
|
98
|
+
return { requestRecord, requestContext, spanHandle, rpcMetadata };
|
|
99
|
+
}
|
|
100
|
+
function finalizeRequestObservation(options) {
|
|
101
|
+
const { observation, statusCode, route } = options;
|
|
102
|
+
const { requestRecord, spanHandle, rpcMetadata, method } = observation;
|
|
103
|
+
requestRecord.durationSeconds = (options.completedAtMillis - observation.startTimeMillis) / 1e3;
|
|
104
|
+
const { span, ownSpan } = spanHandle;
|
|
105
|
+
if (options.clientAddress !== void 0) {
|
|
106
|
+
writeRequestAttribute(span, requestRecord, "client.address", options.clientAddress);
|
|
107
|
+
}
|
|
108
|
+
writeRequestAttribute(span, requestRecord, "http.response.status_code", statusCode);
|
|
109
|
+
const requestBodySize = options.capturedRequestBody?.size;
|
|
110
|
+
if (requestBodySize !== void 0) {
|
|
111
|
+
writeRequestAttribute(span, requestRecord, "http.request.body.size", requestBodySize);
|
|
112
|
+
}
|
|
113
|
+
const responseBodySize = options.capturedResponseBody?.size;
|
|
114
|
+
if (responseBodySize !== void 0) {
|
|
115
|
+
writeRequestAttribute(span, requestRecord, "http.response.body.size", responseBodySize);
|
|
116
|
+
}
|
|
117
|
+
if (route !== void 0) {
|
|
118
|
+
writeRequestAttribute(span, requestRecord, "http.route", route);
|
|
119
|
+
if (rpcMetadata) {
|
|
120
|
+
rpcMetadata.route = route;
|
|
121
|
+
}
|
|
122
|
+
if (ownSpan?.isRecording()) {
|
|
123
|
+
ownSpan.updateName(`${method} ${route}`);
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
requestRecord.attributes["http.route"] = "";
|
|
127
|
+
}
|
|
128
|
+
if (ownSpan && statusCode >= 500) {
|
|
129
|
+
ownSpan.setStatus({ code: SpanStatusCode.ERROR });
|
|
130
|
+
}
|
|
131
|
+
if (requestRecord.serverSpanId !== void 0 && requestRecord.dropReason === void 0) {
|
|
132
|
+
const config = getConfig();
|
|
133
|
+
const stash = {};
|
|
134
|
+
if (config.captureRequestHeaders) {
|
|
135
|
+
stash.requestHeaders = normalizeHeaders(options.requestHeaders);
|
|
136
|
+
}
|
|
137
|
+
if (config.captureResponseHeaders) {
|
|
138
|
+
stash.responseHeaders = normalizeHeaders(options.responseHeaders);
|
|
139
|
+
}
|
|
140
|
+
const requestBody = options.capturedRequestBody?.body;
|
|
141
|
+
if (requestBody) {
|
|
142
|
+
stash.requestBody = requestBody;
|
|
143
|
+
}
|
|
144
|
+
const responseBody = options.capturedResponseBody?.body;
|
|
145
|
+
if (responseBody) {
|
|
146
|
+
stash.responseBody = responseBody;
|
|
147
|
+
}
|
|
148
|
+
if (Object.keys(stash).length > 0) {
|
|
149
|
+
getActiveSpanPipeline()?.updateStash(requestRecord.serverSpanId, stash);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
ownSpan?.end(options.completedAtMillis);
|
|
153
|
+
getActiveSpanPipeline()?.handleTransportCompletion(requestRecord);
|
|
154
|
+
}
|
|
155
|
+
function finalizeRequestObservationWithError(options) {
|
|
156
|
+
const { requestRecord, spanHandle, error, durationSeconds } = options;
|
|
157
|
+
requestRecord.durationSeconds = durationSeconds;
|
|
158
|
+
if (spanHandle.span?.isRecording()) {
|
|
159
|
+
spanHandle.span.recordException(coerceToException(error));
|
|
160
|
+
}
|
|
161
|
+
if (spanHandle.ownSpan) {
|
|
162
|
+
spanHandle.ownSpan.setStatus({ code: SpanStatusCode.ERROR });
|
|
163
|
+
spanHandle.ownSpan.end();
|
|
164
|
+
}
|
|
165
|
+
getActiveSpanPipeline()?.handleTransportCompletion(requestRecord);
|
|
166
|
+
}
|
|
167
|
+
function normalizeHeaders(headers) {
|
|
168
|
+
const normalized = {};
|
|
169
|
+
if (isWebHeaders(headers)) {
|
|
170
|
+
for (const [name, value] of headers) {
|
|
171
|
+
const existing = normalized[name];
|
|
172
|
+
if (existing === void 0) {
|
|
173
|
+
normalized[name] = value;
|
|
174
|
+
} else if (Array.isArray(existing)) {
|
|
175
|
+
existing.push(value);
|
|
176
|
+
} else {
|
|
177
|
+
normalized[name] = [existing, value];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return normalized;
|
|
181
|
+
}
|
|
182
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
183
|
+
if (value !== void 0) {
|
|
184
|
+
normalized[name.toLowerCase()] = Array.isArray(value) ? value : String(value);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return normalized;
|
|
188
|
+
}
|
|
189
|
+
function isWebHeaders(headers) {
|
|
190
|
+
return typeof headers[Symbol.iterator] === "function";
|
|
191
|
+
}
|
|
192
|
+
function warnAboutNonRecordingServerSpan() {
|
|
193
|
+
logWarning(
|
|
194
|
+
"The OpenTelemetry sampler did not sample the SERVER span of a request. Only sampled requests are exported to Apitally as traces and request logs. Request metrics include all requests."
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
function warnAboutUnattachedSpanProcessor() {
|
|
198
|
+
logWarning(
|
|
199
|
+
"The recording OpenTelemetry SERVER span created for a request did not reach ApitallySpanProcessor. Traces and request logs are unavailable while request metrics continue. To resolve this, add the ApitallySpanProcessor instance to your tracer provider's spanProcessors constructor option or the NodeSDK spanProcessors option."
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
export {
|
|
203
|
+
finalizeRequestObservation,
|
|
204
|
+
finalizeRequestObservationWithError,
|
|
205
|
+
resolveHttpRequestStartAttributes,
|
|
206
|
+
startRequestObservation
|
|
207
|
+
};
|
|
208
|
+
//# sourceMappingURL=requestObservation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/requestObservation.ts"],"sourcesContent":["import { type Attributes, type Context, SpanKind, SpanStatusCode, trace } from \"@opentelemetry/api\";\nimport { getRPCMetadata, type RPCMetadata, RPCType, setRPCMetadata } from \"@opentelemetry/core\";\nimport type { BodyCapture, CapturedBody } from \"./bodyCapture.js\";\nimport { getConfig } from \"./config.js\";\nimport {\n attachRequestRecordToRpcMetadata,\n getConsumerHolder,\n type RequestRecord,\n type SpanHandle,\n withRequestHolders,\n} from \"./context.js\";\nimport { coerceToException } from \"./exceptions.js\";\nimport { logWarning } from \"./logger.js\";\nimport { writeRequestAttribute } from \"./requestAttributes.js\";\nimport {\n getActiveSpanPipeline,\n isApitallySpanProcessorDeclared,\n type RequestStash,\n} from \"./spanProcessor.js\";\n\ninterface StartRequestObservationOptions {\n activeContext: Context;\n extractedContext: Context;\n tracerName: string;\n method: string;\n startAttributes: Attributes;\n requestBodyCapture: BodyCapture;\n}\n\nexport interface StartedRequestObservation {\n requestRecord: RequestRecord;\n requestContext: Context;\n spanHandle: SpanHandle;\n rpcMetadata?: RPCMetadata;\n}\n\nexport interface HttpRequestStartAttributeInput {\n method: string;\n path?: string;\n query?: string;\n scheme?: string;\n serverAddress?: string;\n fullUrl?: string;\n clientAddress?: string;\n userAgent?: string;\n requestBodySize?: number;\n}\n\nexport function resolveHttpRequestStartAttributes(\n input: HttpRequestStartAttributeInput,\n): Attributes {\n const attributes: Attributes = { \"http.request.method\": input.method };\n const optionalAttributes: [string, string | number | undefined][] = [\n [\"url.path\", input.path],\n [\"url.query\", input.query],\n [\"url.scheme\", input.scheme],\n [\"url.full\", input.fullUrl],\n [\"server.address\", input.serverAddress],\n [\"client.address\", input.clientAddress],\n [\"user_agent.original\", input.userAgent],\n [\"http.request.body.size\", input.requestBodySize],\n ];\n for (const [name, value] of optionalAttributes) {\n if (value !== undefined) {\n attributes[name] = value;\n }\n }\n return attributes;\n}\n\nexport function startRequestObservation(\n options: StartRequestObservationOptions,\n): StartedRequestObservation {\n const {\n activeContext,\n extractedContext,\n tracerName,\n method,\n startAttributes,\n requestBodyCapture,\n } = options;\n const requestRecord: RequestRecord = { attributes: {} };\n const spanHandle: SpanHandle = {};\n const consumerHolder = getConsumerHolder(activeContext) ?? {};\n // Metrics and the exported span copy read from the request record, so the\n // start attributes are mirrored into it on every path, span or no span.\n Object.assign(requestRecord.attributes, startAttributes);\n const activeSpan = trace.getSpan(activeContext);\n const resolveUnavailableSpanDropReason = (): RequestRecord[\"dropReason\"] =>\n getActiveSpanPipeline()?.resolveRequestDropReasonBeforeSampling(startAttributes) ??\n \"sampled-out\";\n let requestContext: Context;\n // Span kind is not part of the OTel API surface, so read the SDK-level\n // property from whichever package copy produced the span.\n if (activeSpan?.isRecording() && (activeSpan as { kind?: unknown }).kind === SpanKind.SERVER) {\n // A SERVER span produced by the user's own instrumentation is adopted:\n // no second span, and the request runs under the user's context.\n spanHandle.span = activeSpan;\n requestRecord.serverSpanId = activeSpan.spanContext().spanId;\n if (getActiveSpanPipeline()?.isRequestInFlight(requestRecord.serverSpanId) !== true) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n }\n requestContext = withRequestHolders(activeContext, spanHandle, requestRecord, consumerHolder);\n } else if (activeSpan && !activeSpan.isRecording()) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n if (requestRecord.dropReason === \"sampled-out\") {\n warnAboutNonRecordingServerSpan();\n }\n requestContext = withRequestHolders(activeContext, spanHandle, requestRecord, consumerHolder);\n } else {\n requestContext = withRequestHolders(\n extractedContext,\n spanHandle,\n requestRecord,\n consumerHolder,\n );\n const ownSpan = trace\n .getTracer(tracerName)\n .startSpan(method, { kind: SpanKind.SERVER, attributes: startAttributes }, requestContext);\n if (!ownSpan.isRecording()) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n if (requestRecord.dropReason === \"sampled-out\") {\n warnAboutNonRecordingServerSpan();\n }\n } else {\n spanHandle.span = ownSpan;\n spanHandle.ownSpan = ownSpan;\n if (isApitallySpanProcessorDeclared() && requestRecord.serverSpanId === undefined) {\n requestRecord.dropReason = resolveUnavailableSpanDropReason();\n if (requestRecord.dropReason === \"sampled-out\") {\n warnAboutUnattachedSpanProcessor();\n }\n }\n }\n // A non-recording span still carries a valid span context, so user child\n // spans parent to it and parent-based samplers drop them consistently.\n requestContext = trace.setSpan(requestContext, ownSpan);\n }\n\n // Middleware-based span producers inspect OTel RPC metadata to demote duplicate\n // transport spans; completion adds the route.\n let rpcMetadata = getRPCMetadata(requestContext);\n if (!rpcMetadata && spanHandle.span) {\n rpcMetadata = { type: RPCType.HTTP, span: spanHandle.span };\n requestContext = setRPCMetadata(requestContext, rpcMetadata);\n }\n attachRequestRecordToRpcMetadata(rpcMetadata, requestRecord);\n if (requestRecord.dropReason !== undefined) {\n requestBodyCapture.stopBuffering();\n }\n return { requestRecord, requestContext, spanHandle, rpcMetadata };\n}\n\nexport interface RequestObservation {\n requestRecord: RequestRecord;\n spanHandle: SpanHandle;\n rpcMetadata?: RPCMetadata;\n method: string;\n startTimeMillis: number;\n}\n\nexport interface FinalizeRequestObservationOptions {\n observation: RequestObservation;\n completedAtMillis: number;\n statusCode: number;\n route?: string;\n clientAddress?: string;\n requestHeaders: Headers | Record<string, string | string[] | undefined>;\n responseHeaders: Headers | Record<string, string | number | string[] | undefined>;\n capturedRequestBody?: CapturedBody;\n capturedResponseBody?: CapturedBody;\n}\n\nexport function finalizeRequestObservation(options: FinalizeRequestObservationOptions): void {\n const { observation, statusCode, route } = options;\n const { requestRecord, spanHandle, rpcMetadata, method } = observation;\n requestRecord.durationSeconds = (options.completedAtMillis - observation.startTimeMillis) / 1000;\n const { span, ownSpan } = spanHandle;\n if (options.clientAddress !== undefined) {\n writeRequestAttribute(span, requestRecord, \"client.address\", options.clientAddress);\n }\n writeRequestAttribute(span, requestRecord, \"http.response.status_code\", statusCode);\n const requestBodySize = options.capturedRequestBody?.size;\n if (requestBodySize !== undefined) {\n writeRequestAttribute(span, requestRecord, \"http.request.body.size\", requestBodySize);\n }\n const responseBodySize = options.capturedResponseBody?.size;\n if (responseBodySize !== undefined) {\n writeRequestAttribute(span, requestRecord, \"http.response.body.size\", responseBodySize);\n }\n if (route !== undefined) {\n writeRequestAttribute(span, requestRecord, \"http.route\", route);\n if (rpcMetadata) {\n rpcMetadata.route = route;\n }\n if (ownSpan?.isRecording()) {\n ownSpan.updateName(`${method} ${route}`);\n }\n } else {\n // An empty route clears one set by the producing instrumentation; request\n // metrics omit empty routes.\n requestRecord.attributes[\"http.route\"] = \"\";\n }\n if (ownSpan && statusCode >= 500) {\n ownSpan.setStatus({ code: SpanStatusCode.ERROR });\n }\n // A dropped request's spans are never released, so a stash entry for it\n // would sit unconsumed until the cap evicts it.\n if (requestRecord.serverSpanId !== undefined && requestRecord.dropReason === undefined) {\n const config = getConfig();\n const stash: RequestStash = {};\n if (config.captureRequestHeaders) {\n stash.requestHeaders = normalizeHeaders(options.requestHeaders);\n }\n if (config.captureResponseHeaders) {\n stash.responseHeaders = normalizeHeaders(options.responseHeaders);\n }\n const requestBody = options.capturedRequestBody?.body;\n if (requestBody) {\n stash.requestBody = requestBody;\n }\n const responseBody = options.capturedResponseBody?.body;\n if (responseBody) {\n stash.responseBody = responseBody;\n }\n if (Object.keys(stash).length > 0) {\n getActiveSpanPipeline()?.updateStash(requestRecord.serverSpanId, stash);\n }\n }\n ownSpan?.end(options.completedAtMillis);\n getActiveSpanPipeline()?.handleTransportCompletion(requestRecord);\n}\n\nexport interface FinalizeRequestObservationWithErrorOptions {\n requestRecord: RequestRecord;\n spanHandle: SpanHandle;\n error: unknown;\n durationSeconds: number;\n}\n\nexport function finalizeRequestObservationWithError(\n options: FinalizeRequestObservationWithErrorOptions,\n): void {\n const { requestRecord, spanHandle, error, durationSeconds } = options;\n requestRecord.durationSeconds = durationSeconds;\n if (spanHandle.span?.isRecording()) {\n spanHandle.span.recordException(coerceToException(error));\n }\n if (spanHandle.ownSpan) {\n spanHandle.ownSpan.setStatus({ code: SpanStatusCode.ERROR });\n spanHandle.ownSpan.end();\n }\n getActiveSpanPipeline()?.handleTransportCompletion(requestRecord);\n}\n\n// Values remain raw so all redaction happens at the export boundary.\nfunction normalizeHeaders(\n headers: Headers | Record<string, string | number | string[] | undefined>,\n): Record<string, string | string[]> {\n const normalized: Record<string, string | string[]> = {};\n if (isWebHeaders(headers)) {\n // The Headers API combines repeated values except Set-Cookie.\n for (const [name, value] of headers) {\n const existing = normalized[name];\n if (existing === undefined) {\n normalized[name] = value;\n } else if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n normalized[name] = [existing, value];\n }\n }\n return normalized;\n }\n for (const [name, value] of Object.entries(headers)) {\n if (value !== undefined) {\n normalized[name.toLowerCase()] = Array.isArray(value) ? value : String(value);\n }\n }\n return normalized;\n}\n\n// Duck-typed on iterability: a plain header record has no Symbol.iterator, and\n// the Headers instance may come from another realm's implementation.\nfunction isWebHeaders(headers: object): headers is Headers {\n return typeof (headers as Headers)[Symbol.iterator] === \"function\";\n}\n\nfunction warnAboutNonRecordingServerSpan(): void {\n logWarning(\n \"The OpenTelemetry sampler did not sample the SERVER span of a request. Only sampled requests are exported to Apitally as traces and request logs. Request metrics include all requests.\",\n );\n}\n\nfunction warnAboutUnattachedSpanProcessor(): void {\n logWarning(\n \"The recording OpenTelemetry SERVER span created for a request did not reach ApitallySpanProcessor. Traces and request logs are unavailable while request metrics continue. To resolve this, add the ApitallySpanProcessor instance to your tracer provider's spanProcessors constructor option or the NodeSDK spanProcessors option.\",\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var requestObservationNode_exports = {};
|
|
20
|
+
__export(requestObservationNode_exports, {
|
|
21
|
+
captureNodeResponse: () => captureNodeResponse,
|
|
22
|
+
registerServerCloseFlush: () => registerServerCloseFlush,
|
|
23
|
+
startNodeRequestObservation: () => startNodeRequestObservation
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(requestObservationNode_exports);
|
|
26
|
+
var import_api = require("@opentelemetry/api");
|
|
27
|
+
var import_activation = require('./activation.cjs');
|
|
28
|
+
var import_bodyCapture = require('./bodyCapture.cjs');
|
|
29
|
+
var import_config = require('./config.cjs');
|
|
30
|
+
var import_logger = require('./logger.cjs');
|
|
31
|
+
var import_requestObservation = require('./requestObservation.cjs');
|
|
32
|
+
const flushOnCloseServers = /* @__PURE__ */ new WeakSet();
|
|
33
|
+
function startNodeRequestObservation(options) {
|
|
34
|
+
const { request } = options;
|
|
35
|
+
const startTimeMillis = performance.now();
|
|
36
|
+
const method = (request.method ?? "GET").toUpperCase();
|
|
37
|
+
const requestUrl = request.url ?? "/";
|
|
38
|
+
const requestBodyCapture = new import_bodyCapture.BodyCapture({
|
|
39
|
+
captureBody: (0, import_config.getConfig)().captureRequestBody,
|
|
40
|
+
contentType: request.headers["content-type"],
|
|
41
|
+
contentLength: request.headers["content-length"],
|
|
42
|
+
transferEncoding: request.headers["transfer-encoding"]
|
|
43
|
+
});
|
|
44
|
+
observeRequestBody(request, requestBodyCapture);
|
|
45
|
+
const queryIndex = requestUrl.indexOf("?");
|
|
46
|
+
const scheme = request.socket?.encrypted ? "https" : "http";
|
|
47
|
+
const host = request.headers.host;
|
|
48
|
+
let serverAddress;
|
|
49
|
+
if (host) {
|
|
50
|
+
try {
|
|
51
|
+
serverAddress = new URL(`${scheme}://${host}`).hostname;
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const startAttributes = (0, import_requestObservation.resolveHttpRequestStartAttributes)({
|
|
56
|
+
method,
|
|
57
|
+
path: queryIndex === -1 ? requestUrl : requestUrl.slice(0, queryIndex),
|
|
58
|
+
query: queryIndex === -1 ? void 0 : requestUrl.slice(queryIndex + 1) || void 0,
|
|
59
|
+
scheme,
|
|
60
|
+
serverAddress,
|
|
61
|
+
fullUrl: host ? `${scheme}://${host}${requestUrl}` : void 0,
|
|
62
|
+
clientAddress: request.socket?.remoteAddress || void 0,
|
|
63
|
+
userAgent: typeof request.headers["user-agent"] === "string" ? request.headers["user-agent"] : void 0,
|
|
64
|
+
requestBodySize: requestBodyCapture.size
|
|
65
|
+
});
|
|
66
|
+
const { requestRecord, requestContext, spanHandle, rpcMetadata } = (0, import_requestObservation.startRequestObservation)({
|
|
67
|
+
activeContext: import_api.context.active(),
|
|
68
|
+
extractedContext: import_api.propagation.extract(import_api.ROOT_CONTEXT, request.headers),
|
|
69
|
+
tracerName: options.tracerName,
|
|
70
|
+
method,
|
|
71
|
+
startAttributes,
|
|
72
|
+
requestBodyCapture
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
observation: {
|
|
76
|
+
requestRecord,
|
|
77
|
+
spanHandle,
|
|
78
|
+
rpcMetadata,
|
|
79
|
+
requestBodyCapture,
|
|
80
|
+
startTimeMillis,
|
|
81
|
+
method,
|
|
82
|
+
requestUrl
|
|
83
|
+
},
|
|
84
|
+
requestContext
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function captureNodeResponse(response, shouldCaptureBody, requestBodyCapture, resolveResponseHeader = (name) => response.getHeader(name)) {
|
|
88
|
+
let responseBodyCapture;
|
|
89
|
+
const ensureResponseBodyCapture = () => {
|
|
90
|
+
responseBodyCapture ??= new import_bodyCapture.BodyCapture({
|
|
91
|
+
captureBody: shouldCaptureBody,
|
|
92
|
+
contentType: firstStringValue(resolveResponseHeader("content-type")),
|
|
93
|
+
contentLength: resolveResponseHeader("content-length"),
|
|
94
|
+
transferEncoding: resolveResponseHeader("transfer-encoding")
|
|
95
|
+
});
|
|
96
|
+
return responseBodyCapture;
|
|
97
|
+
};
|
|
98
|
+
const recordResponseChunk = (args) => {
|
|
99
|
+
try {
|
|
100
|
+
const chunk = args[0];
|
|
101
|
+
if (typeof chunk === "string" || Buffer.isBuffer(chunk) || chunk instanceof Uint8Array) {
|
|
102
|
+
ensureResponseBodyCapture().addChunk(
|
|
103
|
+
chunk,
|
|
104
|
+
typeof args[1] === "string" ? args[1] : void 0
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
(0, import_logger.logDebug)(`Error observing a response chunk: ${String(error)}`);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const originalWrite = response.write;
|
|
112
|
+
response.write = function(...args) {
|
|
113
|
+
recordResponseChunk(args);
|
|
114
|
+
return originalWrite.apply(this, args);
|
|
115
|
+
};
|
|
116
|
+
const originalEnd = response.end;
|
|
117
|
+
response.end = function(...args) {
|
|
118
|
+
recordResponseChunk(args);
|
|
119
|
+
return originalEnd.apply(this, args);
|
|
120
|
+
};
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
let completed = false;
|
|
123
|
+
const complete = (responseFinished) => {
|
|
124
|
+
if (completed) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
completed = true;
|
|
128
|
+
const completedAtMillis = performance.now();
|
|
129
|
+
const capture = ensureResponseBodyCapture();
|
|
130
|
+
if (responseFinished) {
|
|
131
|
+
capture.markComplete();
|
|
132
|
+
}
|
|
133
|
+
resolve({
|
|
134
|
+
body: capture.body,
|
|
135
|
+
size: capture.size,
|
|
136
|
+
completedAtMillis,
|
|
137
|
+
responseFinished,
|
|
138
|
+
requestBody: {
|
|
139
|
+
body: requestBodyCapture?.body,
|
|
140
|
+
size: requestBodyCapture?.size
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
response.on("finish", () => complete(true));
|
|
145
|
+
response.on("close", () => complete(false));
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function registerServerCloseFlush(request) {
|
|
149
|
+
const server = request.socket?.server;
|
|
150
|
+
if (!server || typeof server.on !== "function" || flushOnCloseServers.has(server)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
flushOnCloseServers.add(server);
|
|
154
|
+
server.on("close", () => {
|
|
155
|
+
(0, import_activation.flushTelemetry)().catch((error) => {
|
|
156
|
+
(0, import_logger.logDebug)(`Error flushing telemetry on server close: ${String(error)}`);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function observeRequestBody(request, requestBodyCapture) {
|
|
161
|
+
const originalEmit = request.emit;
|
|
162
|
+
request.emit = function(event, ...args) {
|
|
163
|
+
try {
|
|
164
|
+
if (event === "data") {
|
|
165
|
+
const chunk = args[0];
|
|
166
|
+
if (typeof chunk === "string" || Buffer.isBuffer(chunk) || chunk instanceof Uint8Array) {
|
|
167
|
+
requestBodyCapture.addChunk(chunk);
|
|
168
|
+
}
|
|
169
|
+
} else if (event === "end") {
|
|
170
|
+
requestBodyCapture.markComplete();
|
|
171
|
+
}
|
|
172
|
+
} catch (error) {
|
|
173
|
+
(0, import_logger.logDebug)(`Error observing a request body chunk: ${String(error)}`);
|
|
174
|
+
}
|
|
175
|
+
return originalEmit.call(this, event, ...args);
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function firstStringValue(value) {
|
|
179
|
+
if (typeof value === "string") {
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
if (Array.isArray(value)) {
|
|
183
|
+
return value[0];
|
|
184
|
+
}
|
|
185
|
+
return void 0;
|
|
186
|
+
}
|
|
187
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
188
|
+
0 && (module.exports = {
|
|
189
|
+
captureNodeResponse,
|
|
190
|
+
registerServerCloseFlush,
|
|
191
|
+
startNodeRequestObservation
|
|
192
|
+
});
|
|
193
|
+
//# sourceMappingURL=requestObservationNode.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/requestObservationNode.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { type Context, context, propagation, ROOT_CONTEXT } from \"@opentelemetry/api\";\nimport { flushTelemetry } from \"./activation.js\";\nimport { BodyCapture, type CapturedBody } from \"./bodyCapture.js\";\nimport { getConfig } from \"./config.js\";\nimport { logDebug } from \"./logger.js\";\nimport {\n type RequestObservation,\n resolveHttpRequestStartAttributes,\n startRequestObservation,\n} from \"./requestObservation.js\";\n\nconst flushOnCloseServers = new WeakSet<object>();\n\nexport interface StartNodeRequestObservationOptions {\n request: IncomingMessage;\n tracerName: string;\n}\n\nexport interface NodeRequestObservation extends RequestObservation {\n requestBodyCapture: BodyCapture;\n requestUrl: string;\n}\n\nexport interface StartedNodeRequestObservation {\n observation: NodeRequestObservation;\n requestContext: Context;\n}\n\nexport function startNodeRequestObservation(\n options: StartNodeRequestObservationOptions,\n): StartedNodeRequestObservation {\n const { request } = options;\n const startTimeMillis = performance.now();\n const method = (request.method ?? \"GET\").toUpperCase();\n const requestUrl = request.url ?? \"/\";\n const requestBodyCapture = new BodyCapture({\n captureBody: getConfig().captureRequestBody,\n contentType: request.headers[\"content-type\"],\n contentLength: request.headers[\"content-length\"],\n transferEncoding: request.headers[\"transfer-encoding\"],\n });\n observeRequestBody(request, requestBodyCapture);\n\n const queryIndex = requestUrl.indexOf(\"?\");\n const scheme = (request.socket as { encrypted?: boolean } | undefined)?.encrypted\n ? \"https\"\n : \"http\";\n const host = request.headers.host;\n let serverAddress: string | undefined;\n if (host) {\n try {\n serverAddress = new URL(`${scheme}://${host}`).hostname;\n } catch {\n // An invalid Host header leaves the server address unset.\n }\n }\n const startAttributes = resolveHttpRequestStartAttributes({\n method,\n path: queryIndex === -1 ? requestUrl : requestUrl.slice(0, queryIndex),\n query: queryIndex === -1 ? undefined : requestUrl.slice(queryIndex + 1) || undefined,\n scheme,\n serverAddress,\n fullUrl: host ? `${scheme}://${host}${requestUrl}` : undefined,\n clientAddress: request.socket?.remoteAddress || undefined,\n userAgent:\n typeof request.headers[\"user-agent\"] === \"string\" ? request.headers[\"user-agent\"] : undefined,\n requestBodySize: requestBodyCapture.size,\n });\n const { requestRecord, requestContext, spanHandle, rpcMetadata } = startRequestObservation({\n activeContext: context.active(),\n extractedContext: propagation.extract(ROOT_CONTEXT, request.headers),\n tracerName: options.tracerName,\n method,\n startAttributes,\n requestBodyCapture,\n });\n return {\n observation: {\n requestRecord,\n spanHandle,\n rpcMetadata,\n requestBodyCapture,\n startTimeMillis,\n method,\n requestUrl,\n },\n requestContext,\n };\n}\n\nexport interface NodeResponseCompletion extends CapturedBody {\n completedAtMillis: number;\n responseFinished: boolean;\n requestBody: CapturedBody;\n}\n\n// Patching write and end before framework dispatch lets compression wrappers\n// feed their final wire bytes through capture.\nexport function captureNodeResponse(\n response: ServerResponse,\n shouldCaptureBody: boolean,\n requestBodyCapture?: BodyCapture,\n resolveResponseHeader: (name: string) => string | number | string[] | undefined = (name) =>\n response.getHeader(name),\n): Promise<NodeResponseCompletion> {\n let responseBodyCapture: BodyCapture | undefined;\n const ensureResponseBodyCapture = (): BodyCapture => {\n responseBodyCapture ??= new BodyCapture({\n captureBody: shouldCaptureBody,\n contentType: firstStringValue(resolveResponseHeader(\"content-type\")),\n contentLength: resolveResponseHeader(\"content-length\"),\n transferEncoding: resolveResponseHeader(\"transfer-encoding\") as string | string[] | undefined,\n });\n return responseBodyCapture;\n };\n const recordResponseChunk = (args: unknown[]): void => {\n try {\n const chunk = args[0];\n if (typeof chunk === \"string\" || Buffer.isBuffer(chunk) || chunk instanceof Uint8Array) {\n ensureResponseBodyCapture().addChunk(\n chunk,\n typeof args[1] === \"string\" ? (args[1] as BufferEncoding) : undefined,\n );\n }\n } catch (error) {\n logDebug(`Error observing a response chunk: ${String(error)}`);\n }\n };\n const originalWrite = response.write as (...args: unknown[]) => boolean;\n response.write = function (this: ServerResponse, ...args: unknown[]): boolean {\n recordResponseChunk(args);\n return originalWrite.apply(this, args);\n } as typeof response.write;\n const originalEnd = response.end as (...args: unknown[]) => ServerResponse;\n response.end = function (this: ServerResponse, ...args: unknown[]): ServerResponse {\n recordResponseChunk(args);\n return originalEnd.apply(this, args);\n } as typeof response.end;\n\n return new Promise((resolve) => {\n let completed = false;\n const complete = (responseFinished: boolean): void => {\n if (completed) {\n return;\n }\n completed = true;\n const completedAtMillis = performance.now();\n const capture = ensureResponseBodyCapture();\n if (responseFinished) {\n capture.markComplete();\n }\n resolve({\n body: capture.body,\n size: capture.size,\n completedAtMillis,\n responseFinished,\n requestBody: {\n body: requestBodyCapture?.body,\n size: requestBodyCapture?.size,\n },\n });\n };\n response.on(\"finish\", () => complete(true));\n response.on(\"close\", () => complete(false));\n });\n}\n\n// Closing a server triggers a flush of buffered telemetry, never a teardown:\n// an app bound to several servers keeps exporting on the still-open ones.\nexport function registerServerCloseFlush(request: IncomingMessage): void {\n const server = (request.socket as { server?: unknown } | undefined)?.server;\n if (\n !server ||\n typeof (server as { on?: unknown }).on !== \"function\" ||\n flushOnCloseServers.has(server as object)\n ) {\n return;\n }\n flushOnCloseServers.add(server as object);\n (server as { on: (event: string, listener: () => void) => void }).on(\"close\", () => {\n flushTelemetry().catch((error: unknown) => {\n logDebug(`Error flushing telemetry on server close: ${String(error)}`);\n });\n });\n}\n\n// Wrapping emit observes only bytes delivered to application consumers and does\n// not change the stream's flow state.\nfunction observeRequestBody(request: IncomingMessage, requestBodyCapture: BodyCapture): void {\n const originalEmit = request.emit as (...args: unknown[]) => boolean;\n (request as { emit: unknown }).emit = function (\n this: IncomingMessage,\n event: string | symbol,\n ...args: unknown[]\n ): boolean {\n try {\n if (event === \"data\") {\n const chunk = args[0];\n if (typeof chunk === \"string\" || Buffer.isBuffer(chunk) || chunk instanceof Uint8Array) {\n requestBodyCapture.addChunk(chunk);\n }\n } else if (event === \"end\") {\n requestBodyCapture.markComplete();\n }\n } catch (error) {\n logDebug(`Error observing a request body chunk: ${String(error)}`);\n }\n return originalEmit.call(this, event, ...args);\n };\n}\n\nfunction firstStringValue(value: string | number | string[] | undefined): string | undefined {\n if (typeof value === \"string\") {\n return value;\n }\n if (Array.isArray(value)) {\n return value[0];\n }\n return undefined;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { Context } from '@opentelemetry/api';
|
|
3
|
+
import { BodyCapture, CapturedBody } from './bodyCapture.cjs';
|
|
4
|
+
import { RequestObservation } from './requestObservation.cjs';
|
|
5
|
+
import '@opentelemetry/core';
|
|
6
|
+
import './context.cjs';
|
|
7
|
+
|
|
8
|
+
interface StartNodeRequestObservationOptions {
|
|
9
|
+
request: IncomingMessage;
|
|
10
|
+
tracerName: string;
|
|
11
|
+
}
|
|
12
|
+
interface NodeRequestObservation extends RequestObservation {
|
|
13
|
+
requestBodyCapture: BodyCapture;
|
|
14
|
+
requestUrl: string;
|
|
15
|
+
}
|
|
16
|
+
interface StartedNodeRequestObservation {
|
|
17
|
+
observation: NodeRequestObservation;
|
|
18
|
+
requestContext: Context;
|
|
19
|
+
}
|
|
20
|
+
declare function startNodeRequestObservation(options: StartNodeRequestObservationOptions): StartedNodeRequestObservation;
|
|
21
|
+
interface NodeResponseCompletion extends CapturedBody {
|
|
22
|
+
completedAtMillis: number;
|
|
23
|
+
responseFinished: boolean;
|
|
24
|
+
requestBody: CapturedBody;
|
|
25
|
+
}
|
|
26
|
+
declare function captureNodeResponse(response: ServerResponse, shouldCaptureBody: boolean, requestBodyCapture?: BodyCapture, resolveResponseHeader?: (name: string) => string | number | string[] | undefined): Promise<NodeResponseCompletion>;
|
|
27
|
+
declare function registerServerCloseFlush(request: IncomingMessage): void;
|
|
28
|
+
|
|
29
|
+
export { type NodeRequestObservation, type NodeResponseCompletion, type StartNodeRequestObservationOptions, type StartedNodeRequestObservation, captureNodeResponse, registerServerCloseFlush, startNodeRequestObservation };
|