@monocle.sh/adonisjs-agent 1.0.0-beta.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 ADDED
@@ -0,0 +1,133 @@
1
+ # @monocle.sh/adonisjs-agent
2
+
3
+ Monocle agent for AdonisJS - sends telemetry to Monocle cloud.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @monocle.sh/adonisjs-agent
9
+ # or
10
+ yarn add @monocle.sh/adonisjs-agent
11
+ # or
12
+ pnpm add @monocle.sh/adonisjs-agent
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ Run the configure command to set up the agent automatically:
18
+
19
+ ```bash
20
+ node ace configure @monocle.sh/adonisjs-agent
21
+ ```
22
+
23
+ This will:
24
+
25
+ 1. Create `config/monocle.ts` configuration file
26
+ 2. Create `otel.ts` initialization file at project root
27
+ 3. Add the otel.ts import as the first import in `bin/server.ts`
28
+ 4. Register the Monocle provider in `adonisrc.ts`
29
+ 5. Register the Monocle middleware as the first router middleware
30
+ 6. Add required environment variables to `.env` and `start/env.ts`
31
+
32
+ After configuration, add your API key to `.env`:
33
+
34
+ ```env
35
+ MONOCLE_API_KEY=mk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
36
+ ```
37
+
38
+ ## User Identification
39
+
40
+ To associate telemetry data with authenticated users, add `Monocle.setUser()` in your authentication middleware:
41
+
42
+ ```typescript
43
+ import type { NextFn } from '@adonisjs/core/types/http'
44
+ import type { HttpContext } from '@adonisjs/core/http'
45
+ import { Monocle } from '@monocle.sh/adonisjs-agent'
46
+
47
+ export default class SilentAuthMiddleware {
48
+ async handle(ctx: HttpContext, next: NextFn) {
49
+ await ctx.auth.check()
50
+
51
+ if (ctx.auth.user) Monocle.setUser(ctx.auth.user)
52
+
53
+ return next()
54
+ }
55
+ }
56
+ ```
57
+
58
+ ## Exception Tracking
59
+
60
+ Exceptions are automatically recorded in spans when thrown during a request. The agent hooks into AdonisJS's `ExceptionHandler.report()` method to capture exceptions with their stack traces.
61
+
62
+ If you want to manually capture exceptions in custom code:
63
+
64
+ ```typescript
65
+ import { Monocle } from '@monocle.sh/adonisjs-agent'
66
+
67
+ try {
68
+ // your code
69
+ } catch (error) {
70
+ Monocle.captureException(error, {
71
+ user: { id: '123', email: 'user@example.com' },
72
+ tags: { component: 'payment' },
73
+ extra: { orderId: 456 },
74
+ })
75
+ throw error
76
+ }
77
+ ```
78
+
79
+ ## Configuration Options
80
+
81
+ The `config/monocle.ts` file supports the following options:
82
+
83
+ ```typescript
84
+ import { defineConfig } from '@monocle.sh/adonisjs-agent'
85
+ import env from '#start/env'
86
+
87
+ export default defineConfig({
88
+ // Optional: Your Monocle API key
89
+ apiKey: env.get('MONOCLE_API_KEY'),
90
+
91
+ // Optional: Custom ingestion endpoint (for development)
92
+ // endpoint: 'http://localhost:4318',
93
+
94
+ // Service identification
95
+ serviceName: env.get('APP_NAME'),
96
+ serviceVersion: env.get('APP_VERSION'),
97
+ environment: env.get('APP_ENV'),
98
+
99
+ // Host metrics (CPU, Memory, Network, etc.)
100
+ // Set to false to disable
101
+ hostMetrics: {
102
+ enabled: true,
103
+ },
104
+
105
+ // CLI command tracing
106
+ cli: {
107
+ enabled: false,
108
+ exclude: ['make:*', 'generate:*', 'queue:work', 'queue:listen'],
109
+ },
110
+
111
+ // Trace batching configuration
112
+ batch: {
113
+ maxExportBatchSize: 512,
114
+ scheduledDelayMillis: 5000,
115
+ },
116
+
117
+ // Enable gzip compression (default: true)
118
+ compression: true,
119
+ })
120
+ ```
121
+
122
+ ## Environment Variables
123
+
124
+ | Variable | Description | Required |
125
+ | ----------------- | ------------------------------------------------------ | -------- |
126
+ | `MONOCLE_API_KEY` | Your Monocle API key | No |
127
+ | `APP_NAME` | Service name for identification | Yes |
128
+ | `APP_VERSION` | Service version (e.g., git sha, semver) | Yes |
129
+ | `APP_ENV` | Environment: `development`, `staging`, or `production` | Yes |
130
+
131
+ ## License
132
+
133
+ ISC
@@ -0,0 +1,6 @@
1
+ import ConfigureCommand from "@adonisjs/core/commands/configure";
2
+
3
+ //#region configure.d.ts
4
+ declare function configure(command: ConfigureCommand): Promise<void>;
5
+ //#endregion
6
+ export { configure };
@@ -0,0 +1,61 @@
1
+ import { stubsRoot } from "./stubs/main.mjs";
2
+
3
+ //#region configure.ts
4
+ async function configure(command) {
5
+ const codemods = await command.createCodemods();
6
+ /**
7
+ * Publish config/monocle.ts
8
+ */
9
+ await codemods.makeUsingStub(stubsRoot, "config.stub", {});
10
+ /**
11
+ * Publish otel.ts at project root
12
+ */
13
+ await codemods.makeUsingStub(stubsRoot, "otel.stub", {});
14
+ const serverFile = (await codemods.getTsMorphProject())?.getSourceFile(command.app.makePath("bin/server.ts"));
15
+ if (serverFile) {
16
+ const insertIndex = serverFile.getImportDeclarations()[0]?.getChildIndex() ?? 0;
17
+ serverFile.insertStatements(insertIndex, [
18
+ "/**",
19
+ " * OpenTelemetry initialization - MUST be the first import",
20
+ " * @see https://opentelemetry.io/docs/languages/js/getting-started/nodejs/",
21
+ " */",
22
+ `import '../otel.js'`,
23
+ ""
24
+ ]);
25
+ await serverFile.save();
26
+ }
27
+ /**
28
+ * Register the provider in adonisrc.ts
29
+ */
30
+ await codemods.updateRcFile((rcFile) => {
31
+ rcFile.addProvider("@monocle.sh/adonisjs-agent/monocle_provider");
32
+ });
33
+ /**
34
+ * Register the middleware as FIRST router middleware
35
+ */
36
+ await codemods.registerMiddleware("router", [{
37
+ path: "@monocle.sh/adonisjs-agent/monocle_middleware",
38
+ position: "before"
39
+ }]);
40
+ /**
41
+ * Define environment variables in .env
42
+ */
43
+ await codemods.defineEnvVariables({
44
+ APP_NAME: command.app.appName,
45
+ APP_VERSION: "0.0.1",
46
+ APP_ENV: "development",
47
+ MONOCLE_API_KEY: ""
48
+ });
49
+ /**
50
+ * Define environment validations in start/env.ts
51
+ */
52
+ await codemods.defineEnvValidations({ variables: {
53
+ APP_NAME: "Env.schema.string()",
54
+ APP_VERSION: "Env.schema.string()",
55
+ APP_ENV: `Env.schema.enum(['development', 'staging', 'production'] as const)`,
56
+ MONOCLE_API_KEY: "Env.schema.string.optional()"
57
+ } });
58
+ }
59
+
60
+ //#endregion
61
+ export { configure };
@@ -0,0 +1,83 @@
1
+ import { Attributes } from "@opentelemetry/api";
2
+
3
+ //#region src/decorators.d.ts
4
+ interface SpanOptions {
5
+ name?: string;
6
+ attributes?: Attributes;
7
+ }
8
+ interface SpanAllOptions {
9
+ prefix?: string;
10
+ attributes?: Attributes;
11
+ }
12
+ /**
13
+ * Decorator to create a span around a method.
14
+ *
15
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
16
+ * to capture exceptions with source context lines.
17
+ *
18
+ * Automatically handles:
19
+ * - Creating and closing the span
20
+ * - Capturing exceptions with context frames
21
+ * - Setting error status
22
+ * - Async/await support
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { span } from '@monocle.sh/adonisjs-agent'
27
+ *
28
+ * class UserService {
29
+ * @span()
30
+ * async findById(id: string) {
31
+ * // Span name: "UserService.findById"
32
+ * return db.users.find(id)
33
+ * }
34
+ *
35
+ * @span({ name: 'user.create', attributes: { operation: 'create' } })
36
+ * async create(data: UserData) {
37
+ * return db.users.create(data)
38
+ * }
39
+ * }
40
+ * ```
41
+ */
42
+ declare function span(options?: SpanOptions): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
43
+ /**
44
+ * Decorator to create spans around all methods of a class.
45
+ *
46
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
47
+ * to capture exceptions with source context lines.
48
+ *
49
+ * Automatically handles:
50
+ * - Creating and closing spans for each method
51
+ * - Capturing exceptions with context frames
52
+ * - Setting error status
53
+ * - Async/await support
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { spanAll } from '@monocle.sh/adonisjs-agent'
58
+ *
59
+ * @spanAll()
60
+ * class OrderService {
61
+ * async create(data: OrderData) {
62
+ * // Span name: "OrderService.create"
63
+ * return db.orders.create(data)
64
+ * }
65
+ *
66
+ * async findById(id: string) {
67
+ * // Span name: "OrderService.findById"
68
+ * return db.orders.find(id)
69
+ * }
70
+ * }
71
+ *
72
+ * @spanAll({ prefix: 'order' })
73
+ * class OrderService {
74
+ * async create(data: OrderData) {
75
+ * // Span name: "order.create"
76
+ * return db.orders.create(data)
77
+ * }
78
+ * }
79
+ * ```
80
+ */
81
+ declare function spanAll(options?: SpanAllOptions): <T extends new (...args: any[]) => any>(constructor: T) => T;
82
+ //#endregion
83
+ export { SpanAllOptions, SpanOptions, span, spanAll };
@@ -0,0 +1,110 @@
1
+ import { record } from "./helpers.mjs";
2
+
3
+ //#region src/decorators.ts
4
+ /**
5
+ * Wrap a method to create a span around its execution.
6
+ */
7
+ function wrapMethod(target, propertyKey, descriptor, options) {
8
+ const originalMethod = descriptor.value;
9
+ const className = target.constructor.name;
10
+ descriptor.value = function(...args) {
11
+ return record(options?.name ?? `${className}.${propertyKey}`, (activeSpan) => {
12
+ if (options?.attributes) activeSpan.setAttributes(options.attributes);
13
+ return originalMethod.apply(this, args);
14
+ });
15
+ };
16
+ return descriptor;
17
+ }
18
+ /**
19
+ * Decorator to create a span around a method.
20
+ *
21
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
22
+ * to capture exceptions with source context lines.
23
+ *
24
+ * Automatically handles:
25
+ * - Creating and closing the span
26
+ * - Capturing exceptions with context frames
27
+ * - Setting error status
28
+ * - Async/await support
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { span } from '@monocle.sh/adonisjs-agent'
33
+ *
34
+ * class UserService {
35
+ * @span()
36
+ * async findById(id: string) {
37
+ * // Span name: "UserService.findById"
38
+ * return db.users.find(id)
39
+ * }
40
+ *
41
+ * @span({ name: 'user.create', attributes: { operation: 'create' } })
42
+ * async create(data: UserData) {
43
+ * return db.users.create(data)
44
+ * }
45
+ * }
46
+ * ```
47
+ */
48
+ function span(options) {
49
+ return function(target, propertyKey, descriptor) {
50
+ return wrapMethod(target, propertyKey, descriptor, options);
51
+ };
52
+ }
53
+ /**
54
+ * Decorator to create spans around all methods of a class.
55
+ *
56
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
57
+ * to capture exceptions with source context lines.
58
+ *
59
+ * Automatically handles:
60
+ * - Creating and closing spans for each method
61
+ * - Capturing exceptions with context frames
62
+ * - Setting error status
63
+ * - Async/await support
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * import { spanAll } from '@monocle.sh/adonisjs-agent'
68
+ *
69
+ * @spanAll()
70
+ * class OrderService {
71
+ * async create(data: OrderData) {
72
+ * // Span name: "OrderService.create"
73
+ * return db.orders.create(data)
74
+ * }
75
+ *
76
+ * async findById(id: string) {
77
+ * // Span name: "OrderService.findById"
78
+ * return db.orders.find(id)
79
+ * }
80
+ * }
81
+ *
82
+ * @spanAll({ prefix: 'order' })
83
+ * class OrderService {
84
+ * async create(data: OrderData) {
85
+ * // Span name: "order.create"
86
+ * return db.orders.create(data)
87
+ * }
88
+ * }
89
+ * ```
90
+ */
91
+ function spanAll(options) {
92
+ return function(constructor) {
93
+ const prototype = constructor.prototype;
94
+ const propertyNames = Object.getOwnPropertyNames(prototype);
95
+ for (const propertyName of propertyNames) {
96
+ if (propertyName === "constructor") continue;
97
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, propertyName);
98
+ if (!descriptor || typeof descriptor.value !== "function") continue;
99
+ const wrappedDescriptor = wrapMethod(prototype, propertyName, descriptor, {
100
+ name: options?.prefix ? `${options.prefix}.${propertyName}` : void 0,
101
+ attributes: options?.attributes
102
+ });
103
+ Object.defineProperty(prototype, propertyName, wrappedDescriptor);
104
+ }
105
+ return constructor;
106
+ };
107
+ }
108
+
109
+ //#endregion
110
+ export { span, spanAll };
@@ -0,0 +1,49 @@
1
+ import { Span } from "@opentelemetry/api";
2
+ import { extractTraceContext, getCurrentSpan, injectTraceContext, otelLoggingPreset, recordEvent, setAttributes } from "@adonisjs/otel/helpers";
3
+
4
+ //#region src/helpers.d.ts
5
+ /**
6
+ * Handle an error by reporting it with context frames extraction.
7
+ *
8
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
9
+ * to extract source context lines from the stack trace.
10
+ */
11
+ declare function handleError(span: Span, error: Error): Promise<never>;
12
+ type RecordCallback<T> = (span: Span) => T | Promise<T>;
13
+ /**
14
+ * Record a code section as a span in your traces.
15
+ *
16
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
17
+ * to capture exceptions with source context lines (pre/post context around
18
+ * the error location).
19
+ *
20
+ * Always returns a Promise to ensure context lines are properly captured
21
+ * even for synchronous errors.
22
+ *
23
+ * Automatically handles:
24
+ * - Creating and closing the span
25
+ * - Capturing exceptions with context frames
26
+ * - Setting error status
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { record } from '@monocle.sh/adonisjs-agent'
31
+ *
32
+ * const result = await record('database.query', () => {
33
+ * return db.query('SELECT * FROM users')
34
+ * })
35
+ *
36
+ * const user = await record('user.fetch', async () => {
37
+ * return await userService.findById(id)
38
+ * })
39
+ *
40
+ * // With attributes
41
+ * const order = await record('order.process', async (span) => {
42
+ * span.setAttributes({ 'order.id': orderId })
43
+ * return await processOrder(orderId)
44
+ * })
45
+ * ```
46
+ */
47
+ declare function record<T>(name: string, callback: RecordCallback<T>): Promise<T>;
48
+ //#endregion
49
+ export { extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes };
@@ -0,0 +1,72 @@
1
+ import { ExceptionReporter } from "./src/exception_reporter.mjs";
2
+ import { SpanStatusCode, trace } from "@opentelemetry/api";
3
+ import { extractTraceContext, getCurrentSpan, injectTraceContext, otelLoggingPreset, recordEvent, setAttributes } from "@adonisjs/otel/helpers";
4
+
5
+ //#region src/helpers.ts
6
+ /**
7
+ * Handle an error by reporting it with context frames extraction.
8
+ *
9
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
10
+ * to extract source context lines from the stack trace.
11
+ */
12
+ async function handleError(span, error) {
13
+ await new ExceptionReporter().report({
14
+ span,
15
+ error,
16
+ shouldReport: true
17
+ });
18
+ span.setStatus({
19
+ code: SpanStatusCode.ERROR,
20
+ message: error?.message
21
+ });
22
+ span.end();
23
+ throw error;
24
+ }
25
+ /**
26
+ * Record a code section as a span in your traces.
27
+ *
28
+ * Unlike the @adonisjs/otel version, this uses Monocle's ExceptionReporter
29
+ * to capture exceptions with source context lines (pre/post context around
30
+ * the error location).
31
+ *
32
+ * Always returns a Promise to ensure context lines are properly captured
33
+ * even for synchronous errors.
34
+ *
35
+ * Automatically handles:
36
+ * - Creating and closing the span
37
+ * - Capturing exceptions with context frames
38
+ * - Setting error status
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { record } from '@monocle.sh/adonisjs-agent'
43
+ *
44
+ * const result = await record('database.query', () => {
45
+ * return db.query('SELECT * FROM users')
46
+ * })
47
+ *
48
+ * const user = await record('user.fetch', async () => {
49
+ * return await userService.findById(id)
50
+ * })
51
+ *
52
+ * // With attributes
53
+ * const order = await record('order.process', async (span) => {
54
+ * span.setAttributes({ 'order.id': orderId })
55
+ * return await processOrder(orderId)
56
+ * })
57
+ * ```
58
+ */
59
+ async function record(name, callback) {
60
+ return trace.getTracer("@monocle.sh/agent").startActiveSpan(name, async (span) => {
61
+ try {
62
+ const result = await callback(span);
63
+ span.end();
64
+ return result;
65
+ } catch (error) {
66
+ return handleError(span, error);
67
+ }
68
+ });
69
+ }
70
+
71
+ //#endregion
72
+ export { extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes };
@@ -0,0 +1,7 @@
1
+ import { BatchConfig, CliTracingConfig, HostMetricsConfig, MonocleConfig } from "./src/types.mjs";
2
+ import { defineConfig } from "./src/define_config.mjs";
3
+ import { Monocle } from "./src/monocle.mjs";
4
+ import { configure } from "./configure.mjs";
5
+ import { extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes } from "./helpers.mjs";
6
+ import { SpanAllOptions, SpanOptions, span, spanAll } from "./decorators.mjs";
7
+ export { type BatchConfig, type CliTracingConfig, type HostMetricsConfig, Monocle, type MonocleConfig, type SpanAllOptions, type SpanOptions, configure, defineConfig, extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes, span, spanAll };
package/dist/index.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from "./src/define_config.mjs";
2
+ import { Monocle } from "./src/monocle.mjs";
3
+ import { configure } from "./configure.mjs";
4
+ import { extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes } from "./helpers.mjs";
5
+ import { span, spanAll } from "./decorators.mjs";
6
+
7
+ export { Monocle, configure, defineConfig, extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes, span, spanAll };
@@ -0,0 +1,8 @@
1
+ //#region src/init.d.ts
2
+ /**
3
+ * Also stolen and tweaked from @adonisjs/otel in order to use our own config file.
4
+ * Need to be able to remove this file in the future.
5
+ */
6
+ declare function init(dirname: string): Promise<void>;
7
+ //#endregion
8
+ export { init };
package/dist/init.mjs ADDED
@@ -0,0 +1,123 @@
1
+ import { register } from "node:module";
2
+ import { pathToFileURL } from "node:url";
3
+ import { join } from "node:path";
4
+ import { createAddHookMessageChannel } from "import-in-the-middle";
5
+
6
+ //#region src/init.ts
7
+ /**
8
+ * Also stolen and tweaked from @adonisjs/otel in order to use our own config file.
9
+ * Need to be able to remove this file in the future.
10
+ */
11
+ const DEFAULT_BATCH_CONFIG = {
12
+ maxExportBatchSize: 512,
13
+ scheduledDelayMillis: 5e3,
14
+ exportTimeoutMillis: 3e4,
15
+ maxQueueSize: 2048
16
+ };
17
+ async function loadConfig(path) {
18
+ return await import(pathToFileURL(path).href).then((mod) => mod.default || mod).catch((error) => {
19
+ throw new Error(`Failed to load Monocle config file at "${path}"`, { cause: error });
20
+ });
21
+ }
22
+ function setupHooks() {
23
+ const { registerOptions, waitForAllMessagesAcknowledged } = createAddHookMessageChannel();
24
+ register("import-in-the-middle/hook.mjs", import.meta.url, registerOptions);
25
+ return waitForAllMessagesAcknowledged;
26
+ }
27
+ /**
28
+ * Create a metric reader for exporting metrics via OTLP
29
+ */
30
+ async function createMetricReader(config) {
31
+ const { PeriodicExportingMetricReader } = await import("@opentelemetry/sdk-metrics");
32
+ const { OTLPMetricExporter } = await import("@opentelemetry/exporter-metrics-otlp-http");
33
+ return new PeriodicExportingMetricReader({
34
+ exporter: new OTLPMetricExporter({ compression: config.compression !== false ? "gzip" : void 0 }),
35
+ exportIntervalMillis: 6e4
36
+ });
37
+ }
38
+ /**
39
+ * Create a BatchSpanProcessor for efficient trace export with compression
40
+ */
41
+ async function createSpanProcessor(config) {
42
+ const { BatchSpanProcessor } = await import("@opentelemetry/sdk-trace-base");
43
+ const { OTLPTraceExporter } = await import("@opentelemetry/exporter-trace-otlp-http");
44
+ const compression = config.compression !== false ? "gzip" : void 0;
45
+ const batchConfig = {
46
+ ...DEFAULT_BATCH_CONFIG,
47
+ ...config.batch
48
+ };
49
+ return new BatchSpanProcessor(new OTLPTraceExporter({ compression }), {
50
+ maxExportBatchSize: batchConfig.maxExportBatchSize,
51
+ scheduledDelayMillis: batchConfig.scheduledDelayMillis,
52
+ exportTimeoutMillis: batchConfig.exportTimeoutMillis,
53
+ maxQueueSize: batchConfig.maxQueueSize
54
+ });
55
+ }
56
+ async function init(dirname) {
57
+ const waitForAllMessagesAcknowledged = setupHooks();
58
+ const { OtelManager } = await import("@adonisjs/otel/manager");
59
+ const config = await loadConfig(join(dirname, "config/monocle.js"));
60
+ if (!config) return;
61
+ if (!OtelManager.isEnabled(config)) return;
62
+ const metricReader = await createMetricReader(config);
63
+ const spanProcessor = await createSpanProcessor(config);
64
+ const configWithProcessors = {
65
+ ...config,
66
+ metricReader,
67
+ spanProcessors: [spanProcessor, ...config.spanProcessors || []]
68
+ };
69
+ const manager = OtelManager.create(configWithProcessors);
70
+ manager?.start();
71
+ const shutdown = async () => {
72
+ await manager?.shutdown().catch(() => {});
73
+ };
74
+ process.on("beforeExit", shutdown);
75
+ process.on("SIGINT", async () => {
76
+ await shutdown();
77
+ process.exit(0);
78
+ });
79
+ process.on("SIGTERM", async () => {
80
+ await shutdown();
81
+ process.exit(0);
82
+ });
83
+ const hostMetricsConfig = config.hostMetrics;
84
+ if (hostMetricsConfig !== false) {
85
+ const { startHostMetrics } = await import("./src/host_metrics.mjs");
86
+ startHostMetrics(hostMetricsConfig === void 0 ? {} : hostMetricsConfig);
87
+ }
88
+ /**
89
+ * CLI Command Instrumentation
90
+ *
91
+ * When enabled, this patches AdonisJS Ace commands to create OTEL spans.
92
+ * The `dirname` parameter is passed so the instrumentation can resolve
93
+ * @adonisjs/core/ace from the app's node_modules (pnpm isolation).
94
+ *
95
+ * Prerequisites for this to work:
96
+ * 1. App's `bin/console.ts` must import `otel.ts` FIRST (before reflect-metadata)
97
+ * 2. Config must have `cli.enabled: true`
98
+ *
99
+ * @see ./cli_instrumentation.ts for implementation details
100
+ */
101
+ const cliConfig = config.cli;
102
+ if (cliConfig !== false && cliConfig?.enabled) {
103
+ const { instrumentCliCommands } = await import("./src/cli_instrumentation.mjs");
104
+ await instrumentCliCommands(cliConfig, dirname);
105
+ }
106
+ /**
107
+ * Mail Instrumentation
108
+ *
109
+ * Automatically instruments @adonisjs/mail if installed.
110
+ * Creates spans for email send operations with metadata attributes.
111
+ *
112
+ * @see ./instrumentations/mail/instrumentation.ts for implementation details
113
+ */
114
+ const mailConfig = config.mail;
115
+ if (mailConfig !== false) {
116
+ const { instrumentMail } = await import("./src/instrumentations/mail/instrumentation.mjs");
117
+ await instrumentMail(mailConfig ?? { enabled: true }, dirname);
118
+ }
119
+ await waitForAllMessagesAcknowledged();
120
+ }
121
+
122
+ //#endregion
123
+ export { init };
@@ -0,0 +1,2 @@
1
+ import OtelMiddleware from "@adonisjs/otel/otel_middleware";
2
+ export { OtelMiddleware as default };
@@ -0,0 +1,7 @@
1
+ import OtelMiddleware from "@adonisjs/otel/otel_middleware";
2
+
3
+ //#region middleware/monocle_middleware.ts
4
+ var monocle_middleware_default = OtelMiddleware;
5
+
6
+ //#endregion
7
+ export { monocle_middleware_default as default };