@monocle.sh/adonisjs-agent 1.3.1 → 1.4.0

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/dist/index.d.mts CHANGED
@@ -4,4 +4,5 @@ import { configure } from "./configure.mjs";
4
4
  import { extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes } from "./helpers.mjs";
5
5
  import { span, spanAll } from "./decorators.mjs";
6
6
  import { destinations } from "@adonisjs/otel";
7
- export { Monocle, configure, defineConfig, destinations, extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes, span, spanAll };
7
+ import { Sample } from "@monocle.sh/otel-utils";
8
+ export { Monocle, Sample, configure, defineConfig, destinations, extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes, span, spanAll };
package/dist/index.mjs CHANGED
@@ -4,4 +4,5 @@ import { configure } from "./configure.mjs";
4
4
  import { extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes } from "./helpers.mjs";
5
5
  import { span, spanAll } from "./decorators.mjs";
6
6
  import { destinations } from "@adonisjs/otel";
7
- export { Monocle, configure, defineConfig, destinations, extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes, span, spanAll };
7
+ import { Sample } from "@monocle.sh/otel-utils";
8
+ export { Monocle, Sample, configure, defineConfig, destinations, extractTraceContext, getCurrentSpan, handleError, injectTraceContext, otelLoggingPreset, record, recordEvent, setAttributes, span, spanAll };
package/dist/init.mjs CHANGED
@@ -17,6 +17,17 @@ function setupHooks() {
17
17
  register("import-in-the-middle/hook.mjs", import.meta.url, registerOptions);
18
18
  return waitForAllMessagesAcknowledged;
19
19
  }
20
+ function moveSamplingProcessorLast(config) {
21
+ const processors = config.spanProcessors;
22
+ if (!processors) return;
23
+ const samplingProcessors = processors.filter((processor) => {
24
+ return processor.constructor.name === "SamplingSpanProcessor";
25
+ });
26
+ if (samplingProcessors.length === 0) return;
27
+ config.spanProcessors = [...processors.filter((processor) => {
28
+ return processor.constructor.name !== "SamplingSpanProcessor";
29
+ }), ...samplingProcessors];
30
+ }
20
31
  async function init(dirname) {
21
32
  const waitForAllMessagesAcknowledged = setupHooks();
22
33
  const { OtelManager } = await import("@adonisjs/otel/manager");
@@ -39,6 +50,25 @@ async function init(dirname) {
39
50
  }).enable();
40
51
  config.spanProcessors = [...config.spanProcessors ?? [], new VercelAiSpanProcessor()];
41
52
  } catch {}
53
+ /**
54
+ * Mastra Instrumentation
55
+ *
56
+ * Mastra already emits OpenTelemetry spans through @mastra/otel-bridge.
57
+ * This processor normalizes Mastra GenAI attributes to the fields consumed by
58
+ * Monocle AI monitoring.
59
+ */
60
+ if (config.mastra !== false) try {
61
+ const { MastraSpanProcessor } = await import("@monocle.sh/instrumentation-mastra");
62
+ const aiOpts = typeof config.ai === "object" ? config.ai : {};
63
+ const mastraOpts = typeof config.mastra === "object" ? config.mastra : {};
64
+ const mastraProcessorConfig = {
65
+ recordInputs: aiOpts.recordInputs,
66
+ recordOutputs: aiOpts.recordOutputs,
67
+ ...mastraOpts
68
+ };
69
+ config.spanProcessors = [...config.spanProcessors ?? [], new MastraSpanProcessor(mastraProcessorConfig)];
70
+ } catch {}
71
+ moveSamplingProcessorLast(config);
42
72
  const manager = OtelManager.create(config);
43
73
  manager?.start();
44
74
  const shutdown = async () => {
@@ -112,7 +142,10 @@ async function init(dirname) {
112
142
  const bullmqConfig = config.bullmq;
113
143
  if (bullmqConfig !== false) {
114
144
  const { instrumentBullMQ } = await import("./src/instrumentations/bullmq/instrumentation.mjs");
115
- await instrumentBullMQ(bullmqConfig);
145
+ await instrumentBullMQ({
146
+ ...bullmqConfig,
147
+ sampling: config.sampling
148
+ });
116
149
  }
117
150
  /**
118
151
  * Cache Instrumentation
@@ -0,0 +1,2 @@
1
+ export * from "@monocle.sh/otel-utils/sampling";
2
+ export * from "@monocle.sh/otel-utils/types/sampling";
@@ -0,0 +1,2 @@
1
+ export * from "@monocle.sh/otel-utils/sampling";
2
+ export {};
@@ -1,5 +1,7 @@
1
1
  import { buildHttpInstrumentationConfig } from "./http_instrumentation_config.mjs";
2
+ import { AdonisSamplingDestinations } from "./sampling_destinations.mjs";
2
3
  import { destinations } from "@adonisjs/otel";
4
+ import { SamplingActivationSpanProcessor, defaultJobSamplingContextExtractor } from "@monocle.sh/otel-utils/sampling";
3
5
  //#region src/define_config.ts
4
6
  const DEFAULT_BATCH_CONFIG = {
5
7
  maxExportBatchSize: 512,
@@ -8,7 +10,7 @@ const DEFAULT_BATCH_CONFIG = {
8
10
  maxQueueSize: 2048
9
11
  };
10
12
  function resolveSdkVersion() {
11
- return "1.3.1";
13
+ return "1.4.0";
12
14
  }
13
15
  function buildNodejsResourceAttributes() {
14
16
  const attributes = {
@@ -19,6 +21,17 @@ function buildNodejsResourceAttributes() {
19
21
  if (sdkVersion) attributes["telemetry.sdk.version"] = sdkVersion;
20
22
  return attributes;
21
23
  }
24
+ function createSamplingActivationProcessor(config) {
25
+ return new SamplingActivationSpanProcessor({
26
+ sampling: config.sampling,
27
+ extractor(span) {
28
+ const context = defaultJobSamplingContextExtractor(span);
29
+ if (!context) return;
30
+ if (context.system === "bullmq" && config.bullmq !== false) return;
31
+ return context;
32
+ }
33
+ });
34
+ }
22
35
  /**
23
36
  * Define and validate Monocle agent configuration.
24
37
  * Returns undefined if no API key is provided (telemetry will be disabled).
@@ -59,16 +72,27 @@ function defineConfig(config) {
59
72
  exportTimeoutMillis: batchConfig.exportTimeoutMillis,
60
73
  maxQueueSize: batchConfig.maxQueueSize
61
74
  });
75
+ const destinationMap = {
76
+ ...config.destinations,
77
+ monocle: monocleDestination
78
+ };
79
+ const samplingDestinations = new AdonisSamplingDestinations(destinationMap);
80
+ const spanProcessors = config.sampling ? [
81
+ ...config.spanProcessors ?? [],
82
+ createSamplingActivationProcessor(config),
83
+ samplingDestinations.createSpanProcessor()
84
+ ] : config.spanProcessors;
85
+ const resolvedDestinations = config.sampling ? samplingDestinations.stripTraceSignals() : destinationMap;
86
+ const samplingRatio = config.sampling && !config.sampler ? 1 : config.samplingRatio;
62
87
  return {
63
88
  ...config,
64
89
  endpoint,
65
90
  environment,
91
+ samplingRatio,
66
92
  resourceAttributes,
67
93
  instrumentations,
68
- destinations: {
69
- ...config.destinations,
70
- monocle: monocleDestination
71
- }
94
+ spanProcessors,
95
+ destinations: resolvedDestinations
72
96
  };
73
97
  }
74
98
  //#endregion
@@ -0,0 +1,80 @@
1
+ import { SamplingSpanProcessor } from "@monocle.sh/otel-utils/sampling";
2
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
3
+ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
4
+ //#region src/sampling_destinations.ts
5
+ /**
6
+ * Normalizes Adonis OTEL destination signal declarations.
7
+ */
8
+ function signalSet(signals) {
9
+ if (signals === "all") return new Set([
10
+ "traces",
11
+ "metrics",
12
+ "logs"
13
+ ]);
14
+ return new Set(signals);
15
+ }
16
+ /**
17
+ * Builds sampling-aware processors from Adonis OTEL destinations.
18
+ *
19
+ * This stays in the Adonis agent because the destination schema comes from
20
+ * `@adonisjs/otel`. Other framework agents can provide their own adapter and
21
+ * still reuse `SamplingSpanProcessor` from `@monocle.sh/otel-utils/sampling`.
22
+ */
23
+ var AdonisSamplingDestinations = class {
24
+ #destinations;
25
+ constructor(destinations) {
26
+ this.#destinations = destinations;
27
+ }
28
+ /**
29
+ * Returns destinations with trace export removed.
30
+ */
31
+ stripTraceSignals() {
32
+ const result = {};
33
+ for (const [key, destination] of Object.entries(this.#destinations)) {
34
+ const stripped = this.#removeTraceSignal(destination);
35
+ if (stripped) result[key] = stripped;
36
+ }
37
+ return result;
38
+ }
39
+ /**
40
+ * Creates a sampling processor that forwards accepted traces to the original
41
+ * trace destinations.
42
+ */
43
+ createSpanProcessor() {
44
+ return new SamplingSpanProcessor(Object.values(this.#destinations).filter((destination) => destination.enabled && this.#hasTraceSignal(destination)).map((destination) => this.#createTraceProcessor(destination)));
45
+ }
46
+ #hasTraceSignal(destination) {
47
+ return signalSet(destination.signals).has("traces");
48
+ }
49
+ #resolveTraceEndpoint(destination) {
50
+ const traceEndpoint = destination.endpoints?.traces;
51
+ if (traceEndpoint) return traceEndpoint;
52
+ if (destination.endpoint) return `${destination.endpoint.replace(/\/$/, "")}/v1/traces`;
53
+ }
54
+ #createTraceProcessor(destination) {
55
+ const url = this.#resolveTraceEndpoint(destination);
56
+ return new BatchSpanProcessor(new OTLPTraceExporter({
57
+ ...url && { url },
58
+ ...destination.headers && { headers: destination.headers },
59
+ ...destination.timeoutMillis !== void 0 && { timeoutMillis: destination.timeoutMillis },
60
+ ...destination.concurrencyLimit !== void 0 && { concurrencyLimit: destination.concurrencyLimit },
61
+ ...destination.compression !== void 0 && { compression: destination.compression }
62
+ }), {
63
+ ...destination.maxExportBatchSize !== void 0 && { maxExportBatchSize: destination.maxExportBatchSize },
64
+ ...destination.scheduledDelayMillis !== void 0 && { scheduledDelayMillis: destination.scheduledDelayMillis },
65
+ ...destination.exportTimeoutMillis !== void 0 && { exportTimeoutMillis: destination.exportTimeoutMillis },
66
+ ...destination.maxQueueSize !== void 0 && { maxQueueSize: destination.maxQueueSize }
67
+ });
68
+ }
69
+ #removeTraceSignal(destination) {
70
+ if (!this.#hasTraceSignal(destination)) return destination;
71
+ const signals = [...signalSet(destination.signals)].filter((signal) => signal !== "traces");
72
+ if (signals.length === 0) return;
73
+ return {
74
+ ...destination,
75
+ signals
76
+ };
77
+ }
78
+ };
79
+ //#endregion
80
+ export { AdonisSamplingDestinations };
@@ -1,7 +1,8 @@
1
- import { HttpBodyCaptureConfig, HttpUrlSanitizationConfig } from "@monocle.sh/otel-utils";
1
+ import { HttpBodyCaptureConfig, HttpUrlSanitizationConfig, SamplingConfig } from "@monocle.sh/otel-utils";
2
2
  import { BentoCacheInstrumentationConfig } from "@bentocache/otel/types";
3
3
  import { DestinationMap, HttpInstrumentationConfig, InstrumentationsConfig, OtelConfig } from "@adonisjs/otel/types";
4
4
  import { BullMQInstrumentationConfig } from "@monocle.sh/instrumentation-bullmq";
5
+ import { MastraSpanProcessorConfig } from "@monocle.sh/instrumentation-mastra";
5
6
 
6
7
  //#region src/types/config.d.ts
7
8
  /**
@@ -104,6 +105,7 @@ interface AiInstrumentationConfig {
104
105
  recordOutputs?: boolean;
105
106
  }
106
107
  type BullMQAgentConfig = BullMQInstrumentationConfig;
108
+ type MastraAgentConfig = MastraSpanProcessorConfig;
107
109
  /**
108
110
  * Extended HTTP instrumentation config consumed by the Monocle agent.
109
111
  */
@@ -184,6 +186,15 @@ interface MonocleConfig extends Omit<OtelConfig, 'traceExporter' | 'metricExport
184
186
  * by grouping multiple spans into single requests.
185
187
  */
186
188
  batch?: BatchConfig;
189
+ /**
190
+ * Trace sampling callback. Use this to sample specific jobs, commands,
191
+ * or HTTP requests with Monocle's `Sample` helper.
192
+ *
193
+ * When enabled, the agent records traces locally before deciding whether to
194
+ * export them. Do not combine this option with head sampling unless you know
195
+ * errors dropped by the head sampler cannot be recovered.
196
+ */
197
+ sampling?: SamplingConfig;
187
198
  /**
188
199
  * Enable gzip compression for OTLP exports.
189
200
  * Reduces bandwidth usage significantly.
@@ -231,6 +242,13 @@ interface MonocleConfig extends Omit<OtelConfig, 'traceExporter' | 'metricExport
231
242
  * @default { enabled: true }
232
243
  */
233
244
  ai?: false | AiInstrumentationConfig;
245
+ /**
246
+ * Mastra instrumentation configuration.
247
+ * Normalizes spans emitted by Mastra's OtelBridge for Monocle AI monitoring.
248
+ * Set to `false` to disable.
249
+ * @default { enabled: true }
250
+ */
251
+ mastra?: false | MastraAgentConfig;
234
252
  }
235
253
  //#endregion
236
- export { AiInstrumentationConfig, BatchConfig, BullMQAgentConfig, CacheInstrumentationConfig, CliTracingConfig, HostMetricsConfig, MailInstrumentationConfig, MonocleConfig, MonocleHttpInstrumentationConfig, MonocleInstrumentationsConfig, QueueInstrumentationConfig };
254
+ export { AiInstrumentationConfig, BatchConfig, BullMQAgentConfig, CacheInstrumentationConfig, CliTracingConfig, HostMetricsConfig, MailInstrumentationConfig, MastraAgentConfig, MonocleConfig, MonocleHttpInstrumentationConfig, MonocleInstrumentationsConfig, QueueInstrumentationConfig };
@@ -1,11 +1,11 @@
1
- import { AiInstrumentationConfig, BatchConfig, BullMQAgentConfig, CacheInstrumentationConfig, CliTracingConfig, HostMetricsConfig, MailInstrumentationConfig, MonocleConfig, MonocleHttpInstrumentationConfig, MonocleInstrumentationsConfig, QueueInstrumentationConfig } from "./config.mjs";
1
+ import { AiInstrumentationConfig, BatchConfig, BullMQAgentConfig, CacheInstrumentationConfig, CliTracingConfig, HostMetricsConfig, MailInstrumentationConfig, MastraAgentConfig, MonocleConfig, MonocleHttpInstrumentationConfig, MonocleInstrumentationsConfig, QueueInstrumentationConfig } from "./config.mjs";
2
2
  import { CaptureContext, CaptureExceptionContext, CaptureMessageContext, MessageLevel, MonocleUser } from "./monocle.mjs";
3
3
  import { SpanAllOptions, SpanOptions } from "./decorators.mjs";
4
4
  export * from "@monocle.sh/otel-utils";
5
5
 
6
6
  //#region src/types/main.d.ts
7
7
  declare namespace main_d_exports {
8
- export { AiInstrumentationConfig, BatchConfig, BullMQAgentConfig, CacheInstrumentationConfig, CaptureContext, CaptureExceptionContext, CaptureMessageContext, CliTracingConfig, HostMetricsConfig, MailInstrumentationConfig, MessageLevel, MonocleConfig, MonocleHttpInstrumentationConfig, MonocleInstrumentationsConfig, MonocleUser, QueueInstrumentationConfig, SpanAllOptions, SpanOptions };
8
+ export { AiInstrumentationConfig, BatchConfig, BullMQAgentConfig, CacheInstrumentationConfig, CaptureContext, CaptureExceptionContext, CaptureMessageContext, CliTracingConfig, HostMetricsConfig, MailInstrumentationConfig, MastraAgentConfig, MessageLevel, MonocleConfig, MonocleHttpInstrumentationConfig, MonocleInstrumentationsConfig, MonocleUser, QueueInstrumentationConfig, SpanAllOptions, SpanOptions };
9
9
  }
10
10
  import * as import__monocle_sh_otel_utils from "@monocle.sh/otel-utils";
11
11
  //#endregion
@@ -0,0 +1,2 @@
1
+ import { CommandSamplingContext, HttpSamplingContext, JobSamplingContext, JobSamplingContextExtractor, KeepErrorsOptions, SamplingConfig, SamplingContext, SamplingDecision, SamplingKind, SamplingRule, SamplingRuleKind } from "@monocle.sh/otel-utils/types/sampling";
2
+ export { type CommandSamplingContext, type HttpSamplingContext, type JobSamplingContext, type JobSamplingContextExtractor, type KeepErrorsOptions, type SamplingConfig, type SamplingContext, type SamplingDecision, type SamplingKind, type SamplingRule, type SamplingRuleKind };
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.mts CHANGED
@@ -11,4 +11,8 @@ type HttpBodyRedactionConfig = main_d_exports.HttpBodyRedactionConfig;
11
11
  type HttpBodyRedactor = main_d_exports.HttpBodyRedactor;
12
12
  type HttpUrlSanitizationConfig = main_d_exports.HttpUrlSanitizationConfig;
13
13
  type HttpUrlSanitizerHook = main_d_exports.HttpUrlSanitizerHook;
14
- export { type BatchConfig, type CliTracingConfig, type DestinationConfig, type DestinationMap, type DestinationSignal, type DestinationSignals, type HeadersCarrier, type HostMetricsConfig, type HttpBodyCaptureConfig, type HttpBodyCaptureSideConfig, type HttpBodyInfo, type HttpBodyKind, type HttpBodyRedactionConfig, type HttpBodyRedactor, type HttpUrlSanitizationConfig, type HttpUrlSanitizerHook, type MonocleConfig, type MonocleHttpInstrumentationConfig, type MonocleInstrumentationsConfig, type MonocleUser, type OtelLoggingPresetOptions, type OtlpDestinationConfig, type OtlpDestinationOptions, type SpanAllOptions, type SpanOptions, type UserContextResult };
14
+ type SamplingConfig = main_d_exports.SamplingConfig;
15
+ type SamplingContext = main_d_exports.SamplingContext;
16
+ type SamplingDecision = main_d_exports.SamplingDecision;
17
+ type SamplingRule = main_d_exports.SamplingRule;
18
+ export { type BatchConfig, type CliTracingConfig, type DestinationConfig, type DestinationMap, type DestinationSignal, type DestinationSignals, type HeadersCarrier, type HostMetricsConfig, type HttpBodyCaptureConfig, type HttpBodyCaptureSideConfig, type HttpBodyInfo, type HttpBodyKind, type HttpBodyRedactionConfig, type HttpBodyRedactor, type HttpUrlSanitizationConfig, type HttpUrlSanitizerHook, type MonocleConfig, type MonocleHttpInstrumentationConfig, type MonocleInstrumentationsConfig, type MonocleUser, type OtelLoggingPresetOptions, type OtlpDestinationConfig, type OtlpDestinationOptions, type SamplingConfig, type SamplingContext, type SamplingDecision, type SamplingRule, type SpanAllOptions, type SpanOptions, type UserContextResult };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monocle.sh/adonisjs-agent",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Monocle agent for AdonisJS - sends telemetry to Monocle cloud",
5
5
  "keywords": [
6
6
  "adonisjs",
@@ -31,7 +31,9 @@
31
31
  "./mcp": "./dist/mcp.mjs",
32
32
  "./monocle_middleware": "./dist/monocle_middleware.mjs",
33
33
  "./monocle_provider": "./dist/monocle_provider.mjs",
34
+ "./sampling": "./dist/sampling.mjs",
34
35
  "./types": "./dist/types.mjs",
36
+ "./types/sampling": "./dist/types/sampling.mjs",
35
37
  "./package.json": "./package.json"
36
38
  },
37
39
  "publishConfig": {
@@ -42,32 +44,33 @@
42
44
  "@adonisjs/otel": "^1.2.3",
43
45
  "@bentocache/otel": "^0.1.2",
44
46
  "@opentelemetry/api": "^1.9.1",
45
- "@opentelemetry/api-logs": "^0.214.0",
46
- "@opentelemetry/core": "^2.6.1",
47
- "@opentelemetry/exporter-metrics-otlp-http": "^0.214.0",
48
- "@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
47
+ "@opentelemetry/api-logs": "^0.216.0",
48
+ "@opentelemetry/core": "^2.7.1",
49
+ "@opentelemetry/exporter-metrics-otlp-http": "^0.216.0",
50
+ "@opentelemetry/exporter-trace-otlp-http": "^0.216.0",
49
51
  "@opentelemetry/host-metrics": "^0.38.3",
50
- "@opentelemetry/instrumentation": "^0.214.0",
51
- "@opentelemetry/sdk-metrics": "^2.6.1",
52
- "@opentelemetry/sdk-trace-base": "^2.6.1",
52
+ "@opentelemetry/instrumentation": "^0.216.0",
53
+ "@opentelemetry/sdk-metrics": "^2.7.1",
54
+ "@opentelemetry/sdk-trace-base": "^2.7.1",
53
55
  "@opentelemetry/semantic-conventions": "^1.40.0",
54
56
  "@sindresorhus/is": "^7.2.0",
55
57
  "error-stack-parser-es": "^1.0.5",
56
- "import-in-the-middle": "^3.0.0",
57
- "@monocle.sh/instrumentation-bullmq": "^0.3.1",
58
+ "import-in-the-middle": "^3.0.1",
59
+ "@monocle.sh/instrumentation-bullmq": "^0.4.0",
60
+ "@monocle.sh/instrumentation-mastra": "^0.2.0",
58
61
  "@monocle.sh/instrumentation-mcp": "^1.0.1",
59
- "@monocle.sh/instrumentation-vercel-ai": "^1.1.2",
60
- "@monocle.sh/otel-utils": "^1.1.1"
62
+ "@monocle.sh/instrumentation-vercel-ai": "^1.1.3",
63
+ "@monocle.sh/otel-utils": "^1.2.0"
61
64
  },
62
65
  "devDependencies": {
63
- "@adonisjs/core": "^7.3.0",
66
+ "@adonisjs/core": "^7.3.2",
64
67
  "@adonisjs/tsconfig": "^2.0.0",
65
68
  "@japa/assert": "^4.2.0",
66
69
  "@japa/file-system": "^3.0.0",
67
70
  "@japa/runner": "^5.3.0",
68
71
  "@japa/snapshot": "^2.0.10",
69
72
  "@poppinss/ts-exec": "^1.4.4",
70
- "tsdown": "^0.21.7"
73
+ "tsdown": "^0.21.10"
71
74
  },
72
75
  "peerDependencies": {
73
76
  "@adonisjs/core": "^6.2.0 || ^7.0.0",
@@ -82,6 +85,6 @@
82
85
  "build": "tsdown",
83
86
  "dev": "tsdown",
84
87
  "typecheck": "tsgo --noEmit",
85
- "test": "node --import @poppinss/ts-exec bin/test.ts"
88
+ "test": "NODE_OPTIONS=--conditions=dev node --import @poppinss/ts-exec bin/test.ts"
86
89
  }
87
90
  }