autotel-subscribers 45.0.0 → 46.0.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.
Files changed (113) hide show
  1. package/dist/amplitude.cjs +1 -2
  2. package/dist/amplitude.d.cts +1 -2
  3. package/dist/amplitude.d.ts +1 -2
  4. package/dist/amplitude.js +1 -2
  5. package/dist/architecture-snapshot.cjs +1 -2
  6. package/dist/architecture-snapshot.d.cts +1 -2
  7. package/dist/architecture-snapshot.d.ts +1 -2
  8. package/dist/architecture-snapshot.js +1 -2
  9. package/dist/event-subscriber-base-C_F3Ycbe.cjs +1 -2
  10. package/dist/event-subscriber-base-Day2ml6V.js +1 -2
  11. package/dist/event-subscriber-base-DpZclJM4.d.cts +1 -2
  12. package/dist/event-subscriber-base-DpZclJM4.d.ts +1 -2
  13. package/dist/factories.cjs +1 -2
  14. package/dist/factories.d.cts +1 -2
  15. package/dist/factories.d.ts +1 -2
  16. package/dist/factories.js +1 -2
  17. package/dist/file.cjs +1 -2
  18. package/dist/file.d.cts +1 -2
  19. package/dist/file.d.ts +1 -2
  20. package/dist/file.js +1 -2
  21. package/dist/index.cjs +3 -2
  22. package/dist/index.d.cts +2 -2
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +2 -2
  25. package/dist/loki.cjs +229 -0
  26. package/dist/loki.d.cts +119 -0
  27. package/dist/loki.d.ts +119 -0
  28. package/dist/loki.js +221 -0
  29. package/dist/middleware.cjs +1 -2
  30. package/dist/middleware.d.cts +1 -2
  31. package/dist/middleware.d.ts +1 -2
  32. package/dist/middleware.js +1 -2
  33. package/dist/mixpanel.cjs +1 -2
  34. package/dist/mixpanel.d.cts +1 -2
  35. package/dist/mixpanel.d.ts +1 -2
  36. package/dist/mixpanel.js +1 -2
  37. package/dist/posthog-ByP8BmHb.js +1 -2
  38. package/dist/posthog-DOOBZanH.cjs +1 -2
  39. package/dist/posthog.d.cts +1 -2
  40. package/dist/posthog.d.ts +1 -2
  41. package/dist/security.cjs +1 -2
  42. package/dist/security.d.cts +1 -2
  43. package/dist/security.d.ts +1 -2
  44. package/dist/security.js +1 -2
  45. package/dist/segment.cjs +1 -2
  46. package/dist/segment.d.cts +1 -2
  47. package/dist/segment.d.ts +1 -2
  48. package/dist/segment.js +1 -2
  49. package/dist/slack.cjs +1 -2
  50. package/dist/slack.d.cts +1 -2
  51. package/dist/slack.d.ts +1 -2
  52. package/dist/slack.js +1 -2
  53. package/dist/webhook-delivery-D3v50C81.js +1 -2
  54. package/dist/webhook-delivery-DZeUlZhi.cjs +1 -2
  55. package/dist/webhook.cjs +1 -2
  56. package/dist/webhook.d.cts +1 -2
  57. package/dist/webhook.d.ts +1 -2
  58. package/dist/webhook.js +1 -2
  59. package/package.json +17 -10
  60. package/dist/amplitude.cjs.map +0 -1
  61. package/dist/amplitude.d.cts.map +0 -1
  62. package/dist/amplitude.d.ts.map +0 -1
  63. package/dist/amplitude.js.map +0 -1
  64. package/dist/architecture-snapshot.cjs.map +0 -1
  65. package/dist/architecture-snapshot.d.cts.map +0 -1
  66. package/dist/architecture-snapshot.d.ts.map +0 -1
  67. package/dist/architecture-snapshot.js.map +0 -1
  68. package/dist/event-subscriber-base-C_F3Ycbe.cjs.map +0 -1
  69. package/dist/event-subscriber-base-Day2ml6V.js.map +0 -1
  70. package/dist/event-subscriber-base-DpZclJM4.d.cts.map +0 -1
  71. package/dist/event-subscriber-base-DpZclJM4.d.ts.map +0 -1
  72. package/dist/factories.cjs.map +0 -1
  73. package/dist/factories.d.cts.map +0 -1
  74. package/dist/factories.d.ts.map +0 -1
  75. package/dist/factories.js.map +0 -1
  76. package/dist/file.cjs.map +0 -1
  77. package/dist/file.d.cts.map +0 -1
  78. package/dist/file.d.ts.map +0 -1
  79. package/dist/file.js.map +0 -1
  80. package/dist/index.cjs.map +0 -1
  81. package/dist/index.d.cts.map +0 -1
  82. package/dist/index.d.ts.map +0 -1
  83. package/dist/index.js.map +0 -1
  84. package/dist/middleware.cjs.map +0 -1
  85. package/dist/middleware.d.cts.map +0 -1
  86. package/dist/middleware.d.ts.map +0 -1
  87. package/dist/middleware.js.map +0 -1
  88. package/dist/mixpanel.cjs.map +0 -1
  89. package/dist/mixpanel.d.cts.map +0 -1
  90. package/dist/mixpanel.d.ts.map +0 -1
  91. package/dist/mixpanel.js.map +0 -1
  92. package/dist/posthog-ByP8BmHb.js.map +0 -1
  93. package/dist/posthog-DOOBZanH.cjs.map +0 -1
  94. package/dist/posthog.d.cts.map +0 -1
  95. package/dist/posthog.d.ts.map +0 -1
  96. package/dist/security.cjs.map +0 -1
  97. package/dist/security.d.cts.map +0 -1
  98. package/dist/security.d.ts.map +0 -1
  99. package/dist/security.js.map +0 -1
  100. package/dist/segment.cjs.map +0 -1
  101. package/dist/segment.d.cts.map +0 -1
  102. package/dist/segment.d.ts.map +0 -1
  103. package/dist/segment.js.map +0 -1
  104. package/dist/slack.cjs.map +0 -1
  105. package/dist/slack.d.cts.map +0 -1
  106. package/dist/slack.d.ts.map +0 -1
  107. package/dist/slack.js.map +0 -1
  108. package/dist/webhook-delivery-D3v50C81.js.map +0 -1
  109. package/dist/webhook-delivery-DZeUlZhi.cjs.map +0 -1
  110. package/dist/webhook.cjs.map +0 -1
  111. package/dist/webhook.d.cts.map +0 -1
  112. package/dist/webhook.d.ts.map +0 -1
  113. package/dist/webhook.js.map +0 -1
package/dist/loki.d.ts ADDED
@@ -0,0 +1,119 @@
1
+ import { EventAttributes, EventSubscriber, EventTrackingOptions, FunnelStatus, OutcomeStatus } from "autotel/event-subscriber";
2
+ //#region src/loki.d.ts
3
+ interface LokiConfig {
4
+ /**
5
+ * Base URL of the Loki instance, without the push path.
6
+ * Falls back to `LOKI_ENDPOINT`, `LOKI_URL`, then `LOKI_BASE_URL`.
7
+ *
8
+ * @example 'http://localhost:3100'
9
+ * @example 'https://logs-prod-eu-west-0.grafana.net'
10
+ */
11
+ endpoint?: string;
12
+ /**
13
+ * API token. Paired with {@link LokiConfig.user} it is sent as HTTP Basic,
14
+ * which is what Grafana Cloud expects. Alone it is sent as Bearer, which
15
+ * suits an instance behind an authenticating proxy.
16
+ * Falls back to `LOKI_API_KEY`, then `GRAFANA_API_KEY`.
17
+ */
18
+ apiKey?: string;
19
+ /**
20
+ * Grafana Cloud instance ID — the numeric user of the Loki datasource, not
21
+ * an account email. Supplying it switches authentication to Basic.
22
+ * Falls back to `LOKI_USER`, then `GRAFANA_USER`.
23
+ */
24
+ user?: string;
25
+ /**
26
+ * Tenant for multi-tenant self-hosted Loki, sent as `X-Scope-OrgID`.
27
+ * Independent of the auth mode. Falls back to `LOKI_TENANT_ID`.
28
+ */
29
+ tenantId?: string;
30
+ /**
31
+ * Event fields promoted to stream labels.
32
+ * Defaults to `['service', 'environment', 'level']`.
33
+ *
34
+ * Keep this short and bounded. Promoting `requestId` or `userId` creates one
35
+ * stream per value, which degrades and eventually breaks an instance.
36
+ */
37
+ labelFields?: string[];
38
+ /** Static labels merged into every stream, e.g. `{ cluster: 'prod-eu' }`. */
39
+ labels?: Record<string, string>;
40
+ /** Events buffered before a push. Default 100. */
41
+ batchSize?: number;
42
+ /** Milliseconds before a partial batch is pushed anyway. Default 5000. */
43
+ flushIntervalMs?: number;
44
+ /** Request timeout in milliseconds. Default 5000. */
45
+ timeoutMs?: number;
46
+ /** Attempts including the first. Default 3. */
47
+ maxRetries?: number;
48
+ /** Set false to construct the subscriber without sending anything. */
49
+ enabled?: boolean;
50
+ }
51
+ /** One event as it is written to the Loki line. */
52
+ type LokiEvent = Record<string, unknown> & {
53
+ timestamp?: string;
54
+ };
55
+ interface LokiStream {
56
+ stream: Record<string, string>;
57
+ values: [string, string][];
58
+ }
59
+ interface LokiPayload {
60
+ streams: LokiStream[];
61
+ }
62
+ /** Resolve the push URL, tolerating an endpoint that already carries the path. */
63
+ declare function resolveLokiPushUrl(endpoint: string): string;
64
+ /** Loki entry timestamps are nanosecond epoch strings. */
65
+ declare function toLokiTimestamp(timestamp?: string): string;
66
+ /**
67
+ * Build the stream labels for one event.
68
+ *
69
+ * Only configured fields holding a string, number or boolean become labels.
70
+ * Objects and arrays are skipped rather than stringified, because a serialised
71
+ * object is exactly the unbounded label value that wrecks a Loki instance.
72
+ */
73
+ declare function toLokiLabels(event: LokiEvent, config?: Pick<LokiConfig, 'labelFields' | 'labels'>): Record<string, string>;
74
+ /**
75
+ * Group events into streams by label set.
76
+ *
77
+ * Loki rejects a push whose entries run backwards within a stream, so each
78
+ * stream's values are sorted by timestamp before they go out.
79
+ */
80
+ declare function buildLokiPayload(events: LokiEvent[], config?: Pick<LokiConfig, 'labelFields' | 'labels'>): LokiPayload;
81
+ /** Auth and tenancy headers for a resolved config. */
82
+ declare function toLokiHeaders(config: Pick<LokiConfig, 'apiKey' | 'user' | 'tenantId'>): Record<string, string>;
83
+ /** Push a batch of events without going through a subscriber. */
84
+ declare function sendBatchToLoki(events: LokiEvent[], config?: LokiConfig): Promise<void>;
85
+ /** Push a single event without going through a subscriber. */
86
+ declare function sendToLoki(event: LokiEvent, config?: LokiConfig): Promise<void>;
87
+ /**
88
+ * Buffers events and pushes them to Loki as grouped streams.
89
+ *
90
+ * Batching is not an optimisation here so much as the shape Loki wants: one
91
+ * request carrying several streams costs far less than one request per event,
92
+ * and grouping is what lets entries be ordered within a stream.
93
+ */
94
+ declare class LokiSubscriber implements EventSubscriber {
95
+ readonly name = "LokiSubscriber";
96
+ readonly version = "1.0.0";
97
+ private readonly config;
98
+ private readonly endpoint;
99
+ private readonly enabled;
100
+ private readonly batchSize;
101
+ private readonly flushIntervalMs;
102
+ private readonly httpClient;
103
+ private buffer;
104
+ private timer;
105
+ private readonly pending;
106
+ private warnedMissingEndpoint;
107
+ constructor(config?: LokiConfig);
108
+ private record;
109
+ /** Push everything buffered so far. Safe to call when empty. */
110
+ flush(): Promise<void>;
111
+ trackEvent(name: string, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>;
112
+ trackFunnelStep(funnelName: string, step: FunnelStatus, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>;
113
+ trackOutcome(operationName: string, outcome: OutcomeStatus, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>;
114
+ trackValue(name: string, value: number, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>;
115
+ private track;
116
+ shutdown(): Promise<void>;
117
+ }
118
+ //#endregion
119
+ export { LokiConfig, LokiEvent, LokiPayload, LokiSubscriber, buildLokiPayload, resolveLokiPushUrl, sendBatchToLoki, sendToLoki, toLokiHeaders, toLokiLabels, toLokiTimestamp };
package/dist/loki.js ADDED
@@ -0,0 +1,221 @@
1
+ import { n as createHttpClient, t as postJsonWithRetry } from "./webhook-delivery-D3v50C81.js";
2
+
3
+ //#region src/loki.ts
4
+ /** Push path appended to {@link LokiConfig.endpoint}. */
5
+ const LOKI_PUSH_PATH = "/loki/api/v1/push";
6
+ /**
7
+ * Fields promoted to Loki labels when none are configured. Deliberately short:
8
+ * every distinct combination of label values is a separate stream.
9
+ */
10
+ const DEFAULT_LABEL_FIELDS = [
11
+ "service",
12
+ "environment",
13
+ "level"
14
+ ];
15
+ function firstEnv(...names) {
16
+ for (const name of names) {
17
+ const value = process.env[name];
18
+ if (value) return value;
19
+ }
20
+ }
21
+ /** Resolve the push URL, tolerating an endpoint that already carries the path. */
22
+ function resolveLokiPushUrl(endpoint) {
23
+ const trimmed = endpoint.replace(/\/+$/, "");
24
+ return trimmed.endsWith(LOKI_PUSH_PATH) ? trimmed : `${trimmed}${LOKI_PUSH_PATH}`;
25
+ }
26
+ /** Loki entry timestamps are nanosecond epoch strings. */
27
+ function toLokiTimestamp(timestamp) {
28
+ const parsed = timestamp ? Date.parse(timestamp) : NaN;
29
+ return `${Number.isFinite(parsed) ? parsed : Date.now()}000000`;
30
+ }
31
+ /**
32
+ * Build the stream labels for one event.
33
+ *
34
+ * Only configured fields holding a string, number or boolean become labels.
35
+ * Objects and arrays are skipped rather than stringified, because a serialised
36
+ * object is exactly the unbounded label value that wrecks a Loki instance.
37
+ */
38
+ function toLokiLabels(event, config = {}) {
39
+ const fields = config.labelFields ?? [...DEFAULT_LABEL_FIELDS];
40
+ const labels = { ...config.labels };
41
+ for (const field of fields) {
42
+ const value = event[field];
43
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") labels[field] = String(value);
44
+ }
45
+ return labels;
46
+ }
47
+ /**
48
+ * Group events into streams by label set.
49
+ *
50
+ * Loki rejects a push whose entries run backwards within a stream, so each
51
+ * stream's values are sorted by timestamp before they go out.
52
+ */
53
+ function buildLokiPayload(events, config = {}) {
54
+ const byLabels = /* @__PURE__ */ new Map();
55
+ for (const event of events) {
56
+ const labels = toLokiLabels(event, config);
57
+ const key = JSON.stringify(Object.entries(labels).toSorted(([a], [b]) => a.localeCompare(b)));
58
+ const entry = [toLokiTimestamp(typeof event.timestamp === "string" ? event.timestamp : void 0), JSON.stringify(event)];
59
+ const existing = byLabels.get(key);
60
+ if (existing) existing.values.push(entry);
61
+ else byLabels.set(key, {
62
+ stream: labels,
63
+ values: [entry]
64
+ });
65
+ }
66
+ for (const stream of byLabels.values()) stream.values = stream.values.toSorted(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
67
+ return { streams: [...byLabels.values()] };
68
+ }
69
+ /** Auth and tenancy headers for a resolved config. */
70
+ function toLokiHeaders(config) {
71
+ const headers = {};
72
+ if (config.user && config.apiKey) headers.Authorization = `Basic ${Buffer.from(`${config.user}:${config.apiKey}`).toString("base64")}`;
73
+ else if (config.apiKey) headers.Authorization = `Bearer ${config.apiKey}`;
74
+ if (config.tenantId) headers["X-Scope-OrgID"] = config.tenantId;
75
+ return headers;
76
+ }
77
+ /** Push a batch of events without going through a subscriber. */
78
+ async function sendBatchToLoki(events, config = {}) {
79
+ if (events.length === 0) return;
80
+ const endpoint = config.endpoint ?? firstEnv("LOKI_ENDPOINT", "LOKI_URL", "LOKI_BASE_URL");
81
+ if (!endpoint) throw new Error("Loki endpoint is not configured");
82
+ const resolved = {
83
+ ...config,
84
+ endpoint,
85
+ apiKey: config.apiKey ?? firstEnv("LOKI_API_KEY", "GRAFANA_API_KEY"),
86
+ user: config.user ?? firstEnv("LOKI_USER", "GRAFANA_USER"),
87
+ tenantId: config.tenantId ?? firstEnv("LOKI_TENANT_ID")
88
+ };
89
+ await postJsonWithRetry(createHttpClient({ timeoutMs: resolved.timeoutMs ?? 5e3 }), resolveLokiPushUrl(endpoint), buildLokiPayload(events, resolved), {
90
+ headers: toLokiHeaders(resolved),
91
+ maxRetries: resolved.maxRetries ?? 3,
92
+ label: "Loki"
93
+ });
94
+ }
95
+ /** Push a single event without going through a subscriber. */
96
+ async function sendToLoki(event, config = {}) {
97
+ await sendBatchToLoki([event], config);
98
+ }
99
+ /**
100
+ * Buffers events and pushes them to Loki as grouped streams.
101
+ *
102
+ * Batching is not an optimisation here so much as the shape Loki wants: one
103
+ * request carrying several streams costs far less than one request per event,
104
+ * and grouping is what lets entries be ordered within a stream.
105
+ */
106
+ var LokiSubscriber = class {
107
+ name = "LokiSubscriber";
108
+ version = "1.0.0";
109
+ config;
110
+ endpoint;
111
+ enabled;
112
+ batchSize;
113
+ flushIntervalMs;
114
+ httpClient;
115
+ buffer = [];
116
+ timer;
117
+ pending = /* @__PURE__ */ new Set();
118
+ warnedMissingEndpoint = false;
119
+ constructor(config = {}) {
120
+ this.endpoint = config.endpoint ?? firstEnv("LOKI_ENDPOINT", "LOKI_URL", "LOKI_BASE_URL");
121
+ this.config = {
122
+ ...config,
123
+ apiKey: config.apiKey ?? firstEnv("LOKI_API_KEY", "GRAFANA_API_KEY"),
124
+ user: config.user ?? firstEnv("LOKI_USER", "GRAFANA_USER"),
125
+ tenantId: config.tenantId ?? firstEnv("LOKI_TENANT_ID")
126
+ };
127
+ this.enabled = config.enabled ?? true;
128
+ this.batchSize = config.batchSize ?? 100;
129
+ this.flushIntervalMs = config.flushIntervalMs ?? 5e3;
130
+ this.httpClient = createHttpClient({ timeoutMs: config.timeoutMs ?? 5e3 });
131
+ }
132
+ record(event) {
133
+ if (!this.enabled) return;
134
+ if (!this.endpoint) {
135
+ if (!this.warnedMissingEndpoint) {
136
+ this.warnedMissingEndpoint = true;
137
+ console.warn("[autotel/loki] No endpoint configured; set LOKI_ENDPOINT or pass { endpoint }. Events are being dropped.");
138
+ }
139
+ return;
140
+ }
141
+ this.buffer.push(event);
142
+ if (this.buffer.length >= this.batchSize) {
143
+ this.track(this.flush());
144
+ return;
145
+ }
146
+ if (!this.timer) {
147
+ this.timer = setTimeout(() => {
148
+ this.timer = void 0;
149
+ this.track(this.flush());
150
+ }, this.flushIntervalMs);
151
+ this.timer.unref?.();
152
+ }
153
+ }
154
+ /** Push everything buffered so far. Safe to call when empty. */
155
+ async flush() {
156
+ if (this.buffer.length === 0 || !this.endpoint) return;
157
+ const batch = this.buffer;
158
+ this.buffer = [];
159
+ await postJsonWithRetry(this.httpClient, resolveLokiPushUrl(this.endpoint), buildLokiPayload(batch, this.config), {
160
+ headers: toLokiHeaders(this.config),
161
+ maxRetries: this.config.maxRetries ?? 3,
162
+ label: "Loki"
163
+ });
164
+ }
165
+ async trackEvent(name, attributes, options) {
166
+ this.record({
167
+ type: "event",
168
+ name,
169
+ ...attributes,
170
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
171
+ ...options?.autotel ? { autotel: options.autotel } : {}
172
+ });
173
+ }
174
+ async trackFunnelStep(funnelName, step, attributes, options) {
175
+ this.record({
176
+ type: "funnel",
177
+ funnel: funnelName,
178
+ step,
179
+ ...attributes,
180
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
181
+ ...options?.autotel ? { autotel: options.autotel } : {}
182
+ });
183
+ }
184
+ async trackOutcome(operationName, outcome, attributes, options) {
185
+ this.record({
186
+ type: "outcome",
187
+ operation: operationName,
188
+ outcome,
189
+ ...attributes,
190
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
191
+ ...options?.autotel ? { autotel: options.autotel } : {}
192
+ });
193
+ }
194
+ async trackValue(name, value, attributes, options) {
195
+ this.record({
196
+ type: "value",
197
+ name,
198
+ value,
199
+ ...attributes,
200
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
201
+ ...options?.autotel ? { autotel: options.autotel } : {}
202
+ });
203
+ }
204
+ track(request) {
205
+ this.pending.add(request);
206
+ request.catch(() => {}).finally(() => {
207
+ this.pending.delete(request);
208
+ });
209
+ }
210
+ async shutdown() {
211
+ if (this.timer) {
212
+ clearTimeout(this.timer);
213
+ this.timer = void 0;
214
+ }
215
+ if (this.pending.size > 0) await Promise.allSettled(this.pending);
216
+ await this.flush().catch(() => {});
217
+ }
218
+ };
219
+
220
+ //#endregion
221
+ export { LokiSubscriber, buildLokiPayload, resolveLokiPushUrl, sendBatchToLoki, sendToLoki, toLokiHeaders, toLokiLabels, toLokiTimestamp };
@@ -477,5 +477,4 @@ exports.timeoutMiddleware = timeoutMiddleware;
477
477
  exports.transformMiddleware = transformMiddleware;
478
478
  exports.withEventLogger = withEventLogger;
479
479
  exports.withIdempotency = withIdempotency;
480
- exports.withRateLimit = withRateLimit;
481
- //# sourceMappingURL=middleware.cjs.map
480
+ exports.withRateLimit = withRateLimit;
@@ -250,5 +250,4 @@ declare function withEventLogger(options: {
250
250
  sink: SendEventSink;
251
251
  }): SubscriberMiddleware;
252
252
  //#endregion
253
- export { EventsEvent, IdempotencyStore, RateLimitAlgorithm, RateLimitRecord, RateLimitStore, SendEventRecord, SendEventSink, SubscriberMiddleware, applyMiddleware, batchingMiddleware, circuitBreakerMiddleware, createIdempotencyStore, createMiddleware, createRateLimitStore, enrichmentMiddleware, filterMiddleware, inMemoryIdempotencyStore, inMemoryRateLimitStore, loggingMiddleware, rateLimitMiddleware, retryMiddleware, samplingMiddleware, timeoutMiddleware, transformMiddleware, withEventLogger, withIdempotency, withRateLimit };
254
- //# sourceMappingURL=middleware.d.cts.map
253
+ export { EventsEvent, IdempotencyStore, RateLimitAlgorithm, RateLimitRecord, RateLimitStore, SendEventRecord, SendEventSink, SubscriberMiddleware, applyMiddleware, batchingMiddleware, circuitBreakerMiddleware, createIdempotencyStore, createMiddleware, createRateLimitStore, enrichmentMiddleware, filterMiddleware, inMemoryIdempotencyStore, inMemoryRateLimitStore, loggingMiddleware, rateLimitMiddleware, retryMiddleware, samplingMiddleware, timeoutMiddleware, transformMiddleware, withEventLogger, withIdempotency, withRateLimit };
@@ -250,5 +250,4 @@ declare function withEventLogger(options: {
250
250
  sink: SendEventSink;
251
251
  }): SubscriberMiddleware;
252
252
  //#endregion
253
- export { EventsEvent, IdempotencyStore, RateLimitAlgorithm, RateLimitRecord, RateLimitStore, SendEventRecord, SendEventSink, SubscriberMiddleware, applyMiddleware, batchingMiddleware, circuitBreakerMiddleware, createIdempotencyStore, createMiddleware, createRateLimitStore, enrichmentMiddleware, filterMiddleware, inMemoryIdempotencyStore, inMemoryRateLimitStore, loggingMiddleware, rateLimitMiddleware, retryMiddleware, samplingMiddleware, timeoutMiddleware, transformMiddleware, withEventLogger, withIdempotency, withRateLimit };
254
- //# sourceMappingURL=middleware.d.ts.map
253
+ export { EventsEvent, IdempotencyStore, RateLimitAlgorithm, RateLimitRecord, RateLimitStore, SendEventRecord, SendEventSink, SubscriberMiddleware, applyMiddleware, batchingMiddleware, circuitBreakerMiddleware, createIdempotencyStore, createMiddleware, createRateLimitStore, enrichmentMiddleware, filterMiddleware, inMemoryIdempotencyStore, inMemoryRateLimitStore, loggingMiddleware, rateLimitMiddleware, retryMiddleware, samplingMiddleware, timeoutMiddleware, transformMiddleware, withEventLogger, withIdempotency, withRateLimit };
@@ -457,5 +457,4 @@ function withEventLogger(options) {
457
457
  }
458
458
 
459
459
  //#endregion
460
- export { applyMiddleware, batchingMiddleware, circuitBreakerMiddleware, createIdempotencyStore, createMiddleware, createRateLimitStore, enrichmentMiddleware, filterMiddleware, inMemoryIdempotencyStore, inMemoryRateLimitStore, loggingMiddleware, rateLimitMiddleware, retryMiddleware, samplingMiddleware, timeoutMiddleware, transformMiddleware, withEventLogger, withIdempotency, withRateLimit };
461
- //# sourceMappingURL=middleware.js.map
460
+ export { applyMiddleware, batchingMiddleware, circuitBreakerMiddleware, createIdempotencyStore, createMiddleware, createRateLimitStore, enrichmentMiddleware, filterMiddleware, inMemoryIdempotencyStore, inMemoryRateLimitStore, loggingMiddleware, rateLimitMiddleware, retryMiddleware, samplingMiddleware, timeoutMiddleware, transformMiddleware, withEventLogger, withIdempotency, withRateLimit };
package/dist/mixpanel.cjs CHANGED
@@ -102,5 +102,4 @@ var MixpanelSubscriber = class {
102
102
  };
103
103
 
104
104
  //#endregion
105
- exports.MixpanelSubscriber = MixpanelSubscriber;
106
- //# sourceMappingURL=mixpanel.cjs.map
105
+ exports.MixpanelSubscriber = MixpanelSubscriber;
@@ -31,5 +31,4 @@ declare class MixpanelSubscriber implements EventSubscriber {
31
31
  trackValue(name: string, value: number, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>;
32
32
  }
33
33
  //#endregion
34
- export { MixpanelConfig, MixpanelSubscriber };
35
- //# sourceMappingURL=mixpanel.d.cts.map
34
+ export { MixpanelConfig, MixpanelSubscriber };
@@ -31,5 +31,4 @@ declare class MixpanelSubscriber implements EventSubscriber {
31
31
  trackValue(name: string, value: number, attributes?: EventAttributes, options?: EventTrackingOptions): Promise<void>;
32
32
  }
33
33
  //#endregion
34
- export { MixpanelConfig, MixpanelSubscriber };
35
- //# sourceMappingURL=mixpanel.d.ts.map
34
+ export { MixpanelConfig, MixpanelSubscriber };
package/dist/mixpanel.js CHANGED
@@ -100,5 +100,4 @@ var MixpanelSubscriber = class {
100
100
  };
101
101
 
102
102
  //#endregion
103
- export { MixpanelSubscriber };
104
- //# sourceMappingURL=mixpanel.js.map
103
+ export { MixpanelSubscriber };
@@ -474,5 +474,4 @@ var PostHogSubscriber = class extends EventSubscriber {
474
474
  };
475
475
 
476
476
  //#endregion
477
- export { PostHogSubscriber as t };
478
- //# sourceMappingURL=posthog-ByP8BmHb.js.map
477
+ export { PostHogSubscriber as t };
@@ -481,5 +481,4 @@ Object.defineProperty(exports, 'PostHogSubscriber', {
481
481
  get: function () {
482
482
  return PostHogSubscriber;
483
483
  }
484
- });
485
- //# sourceMappingURL=posthog-DOOBZanH.cjs.map
484
+ });
@@ -328,5 +328,4 @@ declare class PostHogSubscriber extends EventSubscriber$1 {
328
328
  protected handleError(error: Error, payload: EventPayload): void;
329
329
  }
330
330
  //#endregion
331
- export { ErrorContext, FeatureFlagOptions, PersonProperties, PostHogConfig, PostHogSubscriber };
332
- //# sourceMappingURL=posthog.d.cts.map
331
+ export { ErrorContext, FeatureFlagOptions, PersonProperties, PostHogConfig, PostHogSubscriber };
package/dist/posthog.d.ts CHANGED
@@ -328,5 +328,4 @@ declare class PostHogSubscriber extends EventSubscriber$1 {
328
328
  protected handleError(error: Error, payload: EventPayload): void;
329
329
  }
330
330
  //#endregion
331
- export { ErrorContext, FeatureFlagOptions, PersonProperties, PostHogConfig, PostHogSubscriber };
332
- //# sourceMappingURL=posthog.d.ts.map
331
+ export { ErrorContext, FeatureFlagOptions, PersonProperties, PostHogConfig, PostHogSubscriber };
package/dist/security.cjs CHANGED
@@ -99,5 +99,4 @@ var SecuritySubscriber = class extends require_event_subscriber_base.EventSubscr
99
99
  };
100
100
 
101
101
  //#endregion
102
- exports.SecuritySubscriber = SecuritySubscriber;
103
- //# sourceMappingURL=security.cjs.map
102
+ exports.SecuritySubscriber = SecuritySubscriber;
@@ -53,5 +53,4 @@ declare class SecuritySubscriber extends EventSubscriber$1 {
53
53
  private toAlert;
54
54
  }
55
55
  //#endregion
56
- export { SecurityAlert, SecurityAlertSeverity, SecuritySubscriber, SecuritySubscriberConfig };
57
- //# sourceMappingURL=security.d.cts.map
56
+ export { SecurityAlert, SecurityAlertSeverity, SecuritySubscriber, SecuritySubscriberConfig };
@@ -53,5 +53,4 @@ declare class SecuritySubscriber extends EventSubscriber$1 {
53
53
  private toAlert;
54
54
  }
55
55
  //#endregion
56
- export { SecurityAlert, SecurityAlertSeverity, SecuritySubscriber, SecuritySubscriberConfig };
57
- //# sourceMappingURL=security.d.ts.map
56
+ export { SecurityAlert, SecurityAlertSeverity, SecuritySubscriber, SecuritySubscriberConfig };
package/dist/security.js CHANGED
@@ -98,5 +98,4 @@ var SecuritySubscriber = class extends EventSubscriber {
98
98
  };
99
99
 
100
100
  //#endregion
101
- export { SecuritySubscriber };
102
- //# sourceMappingURL=security.js.map
101
+ export { SecuritySubscriber };
package/dist/segment.cjs CHANGED
@@ -83,5 +83,4 @@ var SegmentSubscriber = class {
83
83
  };
84
84
 
85
85
  //#endregion
86
- exports.SegmentSubscriber = SegmentSubscriber;
87
- //# sourceMappingURL=segment.cjs.map
86
+ exports.SegmentSubscriber = SegmentSubscriber;
@@ -24,5 +24,4 @@ declare class SegmentSubscriber implements EventSubscriber {
24
24
  shutdown(): Promise<void>;
25
25
  }
26
26
  //#endregion
27
- export { SegmentConfig, SegmentSubscriber };
28
- //# sourceMappingURL=segment.d.cts.map
27
+ export { SegmentConfig, SegmentSubscriber };
package/dist/segment.d.ts CHANGED
@@ -24,5 +24,4 @@ declare class SegmentSubscriber implements EventSubscriber {
24
24
  shutdown(): Promise<void>;
25
25
  }
26
26
  //#endregion
27
- export { SegmentConfig, SegmentSubscriber };
28
- //# sourceMappingURL=segment.d.ts.map
27
+ export { SegmentConfig, SegmentSubscriber };
package/dist/segment.js CHANGED
@@ -81,5 +81,4 @@ var SegmentSubscriber = class {
81
81
  };
82
82
 
83
83
  //#endregion
84
- export { SegmentSubscriber };
85
- //# sourceMappingURL=segment.js.map
84
+ export { SegmentSubscriber };
package/dist/slack.cjs CHANGED
@@ -233,5 +233,4 @@ var SlackSubscriber = class extends require_event_subscriber_base.EventSubscribe
233
233
  };
234
234
 
235
235
  //#endregion
236
- exports.SlackSubscriber = SlackSubscriber;
237
- //# sourceMappingURL=slack.cjs.map
236
+ exports.SlackSubscriber = SlackSubscriber;
package/dist/slack.d.cts CHANGED
@@ -60,5 +60,4 @@ declare class SlackSubscriber extends EventSubscriber {
60
60
  protected handleError(error: Error, payload: EventPayload): void;
61
61
  }
62
62
  //#endregion
63
- export { SlackSubscriber, SlackSubscriberConfig };
64
- //# sourceMappingURL=slack.d.cts.map
63
+ export { SlackSubscriber, SlackSubscriberConfig };
package/dist/slack.d.ts CHANGED
@@ -60,5 +60,4 @@ declare class SlackSubscriber extends EventSubscriber {
60
60
  protected handleError(error: Error, payload: EventPayload): void;
61
61
  }
62
62
  //#endregion
63
- export { SlackSubscriber, SlackSubscriberConfig };
64
- //# sourceMappingURL=slack.d.ts.map
63
+ export { SlackSubscriber, SlackSubscriberConfig };
package/dist/slack.js CHANGED
@@ -232,5 +232,4 @@ var SlackSubscriber = class extends EventSubscriber {
232
232
  };
233
233
 
234
234
  //#endregion
235
- export { SlackSubscriber };
236
- //# sourceMappingURL=slack.js.map
235
+ export { SlackSubscriber };
@@ -181,5 +181,4 @@ async function postJsonWithRetry(client, url, payload, options = {}) {
181
181
  }
182
182
 
183
183
  //#endregion
184
- export { createHttpClient as n, postJsonWithRetry as t };
185
- //# sourceMappingURL=webhook-delivery-D3v50C81.js.map
184
+ export { createHttpClient as n, postJsonWithRetry as t };
@@ -193,5 +193,4 @@ Object.defineProperty(exports, 'postJsonWithRetry', {
193
193
  get: function () {
194
194
  return postJsonWithRetry;
195
195
  }
196
- });
197
- //# sourceMappingURL=webhook-delivery-DZeUlZhi.cjs.map
196
+ });
package/dist/webhook.cjs CHANGED
@@ -83,5 +83,4 @@ var WebhookSubscriber = class {
83
83
  };
84
84
 
85
85
  //#endregion
86
- exports.WebhookSubscriber = WebhookSubscriber;
87
- //# sourceMappingURL=webhook.cjs.map
86
+ exports.WebhookSubscriber = WebhookSubscriber;
@@ -26,5 +26,4 @@ declare class WebhookSubscriber implements EventSubscriber {
26
26
  shutdown(): Promise<void>;
27
27
  }
28
28
  //#endregion
29
- export { WebhookConfig, WebhookSubscriber };
30
- //# sourceMappingURL=webhook.d.cts.map
29
+ export { WebhookConfig, WebhookSubscriber };
package/dist/webhook.d.ts CHANGED
@@ -26,5 +26,4 @@ declare class WebhookSubscriber implements EventSubscriber {
26
26
  shutdown(): Promise<void>;
27
27
  }
28
28
  //#endregion
29
- export { WebhookConfig, WebhookSubscriber };
30
- //# sourceMappingURL=webhook.d.ts.map
29
+ export { WebhookConfig, WebhookSubscriber };
package/dist/webhook.js CHANGED
@@ -82,5 +82,4 @@ var WebhookSubscriber = class {
82
82
  };
83
83
 
84
84
  //#endregion
85
- export { WebhookSubscriber };
86
- //# sourceMappingURL=webhook.js.map
85
+ export { WebhookSubscriber };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autotel-subscribers",
3
- "version": "45.0.0",
3
+ "version": "46.0.0",
4
4
  "description": "Write Once, Observe Anywhere - Event subscribers for autotel (PostHog, Mixpanel, Amplitude, Segment)",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -71,6 +71,11 @@
71
71
  "types": "./dist/testing/index.d.ts",
72
72
  "import": "./dist/testing/index.js",
73
73
  "require": "./dist/testing/index.cjs"
74
+ },
75
+ "./loki": {
76
+ "types": "./dist/loki.d.ts",
77
+ "import": "./dist/loki.js",
78
+ "require": "./dist/loki.cjs"
74
79
  }
75
80
  },
76
81
  "files": [
@@ -87,6 +92,8 @@
87
92
  "amplitude",
88
93
  "segment",
89
94
  "webhook",
95
+ "loki",
96
+ "grafana",
90
97
  "adapters",
91
98
  "business-metrics",
92
99
  "product-analytics",
@@ -99,7 +106,7 @@
99
106
  "slow-redact": "^0.3.2"
100
107
  },
101
108
  "peerDependencies": {
102
- "autotel": "6.1.0"
109
+ "autotel": "6.2.0"
103
110
  },
104
111
  "peerDependenciesMeta": {
105
112
  "posthog-node": {
@@ -116,27 +123,27 @@
116
123
  }
117
124
  },
118
125
  "devDependencies": {
119
- "@amplitude/analytics-node": "^1.5.67",
126
+ "@amplitude/analytics-node": "^1.5.69",
120
127
  "@arethetypeswrong/cli": "^0.18.5",
121
- "@cloudflare/workers-types": "^5.20260721.1",
122
- "@prisma/client": "^7.9.0",
128
+ "@cloudflare/workers-types": "^5.20260728.1",
129
+ "@prisma/client": "^7.9.1",
123
130
  "@segment/analytics-node": "^3.1.0",
124
- "@types/node": "^26.1.1",
131
+ "@types/node": "^26.1.2",
125
132
  "@typescript-eslint/eslint-plugin": "^8.65.0",
126
133
  "@typescript-eslint/parser": "^8.65.0",
127
134
  "drizzle-orm": "^0.45.2",
128
135
  "eslint-config-prettier": "^10.1.8",
129
136
  "eslint-plugin-unicorn": "^64.0.0",
130
137
  "mixpanel": "^0.22.0",
131
- "mongoose": "^9.8.0",
132
- "posthog-node": "^5.46.0",
138
+ "mongoose": "^9.8.1",
139
+ "posthog-node": "^5.46.1",
133
140
  "prettier": "^3.9.6",
134
141
  "rimraf": "^6.1.3",
135
- "tsdown": "^0.22.12",
142
+ "tsdown": "^0.22.14",
136
143
  "typescript": "^6.0.3",
137
144
  "typescript-eslint": "^8.65.0",
138
145
  "vitest": "^4.1.10",
139
- "autotel": "6.1.0"
146
+ "autotel": "6.2.0"
140
147
  },
141
148
  "repository": {
142
149
  "type": "git",