autotel-subscribers 56.0.0 → 56.1.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.
|
@@ -13,6 +13,33 @@ node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
|
13
13
|
* downstream consumers, so add fields rather than rename existing ones.
|
|
14
14
|
*/
|
|
15
15
|
const ARCHITECTURE_SNAPSHOT_SPEC = "autotel-architecture/v0.1.0";
|
|
16
|
+
/**
|
|
17
|
+
* Order two (producer, channel) pairs, comparing the fields rather than a
|
|
18
|
+
* joined key.
|
|
19
|
+
*
|
|
20
|
+
* Both come from caller-supplied `_autotel` metadata and may contain any
|
|
21
|
+
* character, so joining them with a separator is ambiguous: `('A|B', 'C')` and
|
|
22
|
+
* `('A', 'B|C')` produce the same string and would merge into one source.
|
|
23
|
+
*/
|
|
24
|
+
function compareSources(a, b) {
|
|
25
|
+
return (a.producer ?? "").localeCompare(b.producer ?? "") || (a.channel ?? "").localeCompare(b.channel ?? "");
|
|
26
|
+
}
|
|
27
|
+
function recordSource(observation, producer, channel, now) {
|
|
28
|
+
const sources = observation.sources ??= [];
|
|
29
|
+
const existing = sources.find((source) => source.producer === producer && source.channel === channel);
|
|
30
|
+
if (existing) {
|
|
31
|
+
existing.count += 1;
|
|
32
|
+
existing.lastSeen = now;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
sources.push({
|
|
36
|
+
...producer !== void 0 && { producer },
|
|
37
|
+
...channel !== void 0 && { channel },
|
|
38
|
+
count: 1,
|
|
39
|
+
firstSeen: now,
|
|
40
|
+
lastSeen: now
|
|
41
|
+
});
|
|
42
|
+
}
|
|
16
43
|
const DEFAULT_MAX_SAMPLES = 3;
|
|
17
44
|
var ArchitectureSnapshotSubscriber = class extends require_event_subscriber_base.EventSubscriber {
|
|
18
45
|
name = "ArchitectureSnapshotSubscriber";
|
|
@@ -50,7 +77,14 @@ var ArchitectureSnapshotSubscriber = class extends require_event_subscriber_base
|
|
|
50
77
|
source: payload.schema.source,
|
|
51
78
|
jsonSchema: payload.schema.jsonSchema,
|
|
52
79
|
hash: payload.schema.hash
|
|
53
|
-
} : void 0
|
|
80
|
+
} : void 0,
|
|
81
|
+
sources: [{
|
|
82
|
+
...autotelMeta.producer !== void 0 && { producer: autotelMeta.producer },
|
|
83
|
+
...autotelMeta.channel !== void 0 && { channel: autotelMeta.channel },
|
|
84
|
+
count: 1,
|
|
85
|
+
firstSeen: now,
|
|
86
|
+
lastSeen: now
|
|
87
|
+
}]
|
|
54
88
|
});
|
|
55
89
|
return;
|
|
56
90
|
}
|
|
@@ -61,6 +95,7 @@ var ArchitectureSnapshotSubscriber = class extends require_event_subscriber_base
|
|
|
61
95
|
if (traceId && !existing.sampleTraceIds.includes(traceId) && existing.sampleTraceIds.length < this.maxSampleTraceIds) existing.sampleTraceIds.push(traceId);
|
|
62
96
|
existing.channel ??= autotelMeta.channel;
|
|
63
97
|
existing.producer ??= autotelMeta.producer;
|
|
98
|
+
recordSource(existing, autotelMeta.producer, autotelMeta.channel, now);
|
|
64
99
|
existing.consumers = mergeUnique(existing.consumers ?? [], autotelMeta.consumers ?? []);
|
|
65
100
|
existing.schema ??= payload.schema ? {
|
|
66
101
|
source: payload.schema.source,
|
|
@@ -93,7 +128,12 @@ var ArchitectureSnapshotSubscriber = class extends require_event_subscriber_base
|
|
|
93
128
|
lastSeen: freezeTimestamps ?? obs.lastSeen,
|
|
94
129
|
fieldPaths: obs.fieldPaths.toSorted(),
|
|
95
130
|
sampleTraceIds: obs.sampleTraceIds.toSorted(),
|
|
96
|
-
fieldStats: sortFieldStats(obs.fieldStats)
|
|
131
|
+
fieldStats: sortFieldStats(obs.fieldStats),
|
|
132
|
+
...obs.sources && { sources: obs.sources.map((source) => ({
|
|
133
|
+
...source,
|
|
134
|
+
firstSeen: freezeTimestamps ?? source.firstSeen,
|
|
135
|
+
lastSeen: freezeTimestamps ?? source.lastSeen
|
|
136
|
+
})).toSorted(compareSources) }
|
|
97
137
|
};
|
|
98
138
|
}
|
|
99
139
|
return {
|
|
@@ -27,6 +27,17 @@ type EventObservation = {
|
|
|
27
27
|
producer?: string;
|
|
28
28
|
/** Services known to consume this event (optional metadata from _autotel.consumers). */
|
|
29
29
|
consumers?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* One entry per distinct (producer, channel) pair this event was seen on,
|
|
32
|
+
* with that pair's own count.
|
|
33
|
+
*
|
|
34
|
+
* `producer` and `channel` above are first-write-wins and `observedCount` is
|
|
35
|
+
* an event-level total, so two services publishing the same event name
|
|
36
|
+
* collapse into one: the second producer disappears and its observations are
|
|
37
|
+
* silently credited to the first. Anything attributing counts to a specific
|
|
38
|
+
* relationship must read this instead.
|
|
39
|
+
*/
|
|
40
|
+
sources?: EventSource[];
|
|
30
41
|
/** Observed runtime types and sample primitive values per field path. */
|
|
31
42
|
fieldStats?: Record<string, FieldStats>;
|
|
32
43
|
/** Optional contract schema metadata carried from track() call sites. */
|
|
@@ -36,6 +47,14 @@ type EventObservation = {
|
|
|
36
47
|
hash: string;
|
|
37
48
|
};
|
|
38
49
|
};
|
|
50
|
+
/** One (producer, channel) pair an event was observed on, with its own count. */
|
|
51
|
+
type EventSource = {
|
|
52
|
+
producer?: string;
|
|
53
|
+
channel?: string;
|
|
54
|
+
count: number;
|
|
55
|
+
firstSeen: string;
|
|
56
|
+
lastSeen: string;
|
|
57
|
+
};
|
|
39
58
|
type FieldStats = {
|
|
40
59
|
/** Runtime types observed for this field path (e.g. string, number). */
|
|
41
60
|
types: string[];
|
|
@@ -91,4 +110,4 @@ declare class ArchitectureSnapshotSubscriber extends EventSubscriber {
|
|
|
91
110
|
*/
|
|
92
111
|
declare function extractFieldPaths(value: unknown, prefix?: string): string[];
|
|
93
112
|
//#endregion
|
|
94
|
-
export { ARCHITECTURE_SNAPSHOT_SPEC, ArchitectureSnapshot, ArchitectureSnapshotConfig, ArchitectureSnapshotSubscriber, EventObservation, FieldStats, extractFieldPaths };
|
|
113
|
+
export { ARCHITECTURE_SNAPSHOT_SPEC, ArchitectureSnapshot, ArchitectureSnapshotConfig, ArchitectureSnapshotSubscriber, EventObservation, EventSource, FieldStats, extractFieldPaths };
|
|
@@ -27,6 +27,17 @@ type EventObservation = {
|
|
|
27
27
|
producer?: string;
|
|
28
28
|
/** Services known to consume this event (optional metadata from _autotel.consumers). */
|
|
29
29
|
consumers?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* One entry per distinct (producer, channel) pair this event was seen on,
|
|
32
|
+
* with that pair's own count.
|
|
33
|
+
*
|
|
34
|
+
* `producer` and `channel` above are first-write-wins and `observedCount` is
|
|
35
|
+
* an event-level total, so two services publishing the same event name
|
|
36
|
+
* collapse into one: the second producer disappears and its observations are
|
|
37
|
+
* silently credited to the first. Anything attributing counts to a specific
|
|
38
|
+
* relationship must read this instead.
|
|
39
|
+
*/
|
|
40
|
+
sources?: EventSource[];
|
|
30
41
|
/** Observed runtime types and sample primitive values per field path. */
|
|
31
42
|
fieldStats?: Record<string, FieldStats>;
|
|
32
43
|
/** Optional contract schema metadata carried from track() call sites. */
|
|
@@ -36,6 +47,14 @@ type EventObservation = {
|
|
|
36
47
|
hash: string;
|
|
37
48
|
};
|
|
38
49
|
};
|
|
50
|
+
/** One (producer, channel) pair an event was observed on, with its own count. */
|
|
51
|
+
type EventSource = {
|
|
52
|
+
producer?: string;
|
|
53
|
+
channel?: string;
|
|
54
|
+
count: number;
|
|
55
|
+
firstSeen: string;
|
|
56
|
+
lastSeen: string;
|
|
57
|
+
};
|
|
39
58
|
type FieldStats = {
|
|
40
59
|
/** Runtime types observed for this field path (e.g. string, number). */
|
|
41
60
|
types: string[];
|
|
@@ -91,4 +110,4 @@ declare class ArchitectureSnapshotSubscriber extends EventSubscriber {
|
|
|
91
110
|
*/
|
|
92
111
|
declare function extractFieldPaths(value: unknown, prefix?: string): string[];
|
|
93
112
|
//#endregion
|
|
94
|
-
export { ARCHITECTURE_SNAPSHOT_SPEC, ArchitectureSnapshot, ArchitectureSnapshotConfig, ArchitectureSnapshotSubscriber, EventObservation, FieldStats, extractFieldPaths };
|
|
113
|
+
export { ARCHITECTURE_SNAPSHOT_SPEC, ArchitectureSnapshot, ArchitectureSnapshotConfig, ArchitectureSnapshotSubscriber, EventObservation, EventSource, FieldStats, extractFieldPaths };
|
|
@@ -9,6 +9,33 @@ import path from "node:path";
|
|
|
9
9
|
* downstream consumers, so add fields rather than rename existing ones.
|
|
10
10
|
*/
|
|
11
11
|
const ARCHITECTURE_SNAPSHOT_SPEC = "autotel-architecture/v0.1.0";
|
|
12
|
+
/**
|
|
13
|
+
* Order two (producer, channel) pairs, comparing the fields rather than a
|
|
14
|
+
* joined key.
|
|
15
|
+
*
|
|
16
|
+
* Both come from caller-supplied `_autotel` metadata and may contain any
|
|
17
|
+
* character, so joining them with a separator is ambiguous: `('A|B', 'C')` and
|
|
18
|
+
* `('A', 'B|C')` produce the same string and would merge into one source.
|
|
19
|
+
*/
|
|
20
|
+
function compareSources(a, b) {
|
|
21
|
+
return (a.producer ?? "").localeCompare(b.producer ?? "") || (a.channel ?? "").localeCompare(b.channel ?? "");
|
|
22
|
+
}
|
|
23
|
+
function recordSource(observation, producer, channel, now) {
|
|
24
|
+
const sources = observation.sources ??= [];
|
|
25
|
+
const existing = sources.find((source) => source.producer === producer && source.channel === channel);
|
|
26
|
+
if (existing) {
|
|
27
|
+
existing.count += 1;
|
|
28
|
+
existing.lastSeen = now;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
sources.push({
|
|
32
|
+
...producer !== void 0 && { producer },
|
|
33
|
+
...channel !== void 0 && { channel },
|
|
34
|
+
count: 1,
|
|
35
|
+
firstSeen: now,
|
|
36
|
+
lastSeen: now
|
|
37
|
+
});
|
|
38
|
+
}
|
|
12
39
|
const DEFAULT_MAX_SAMPLES = 3;
|
|
13
40
|
var ArchitectureSnapshotSubscriber = class extends EventSubscriber {
|
|
14
41
|
name = "ArchitectureSnapshotSubscriber";
|
|
@@ -46,7 +73,14 @@ var ArchitectureSnapshotSubscriber = class extends EventSubscriber {
|
|
|
46
73
|
source: payload.schema.source,
|
|
47
74
|
jsonSchema: payload.schema.jsonSchema,
|
|
48
75
|
hash: payload.schema.hash
|
|
49
|
-
} : void 0
|
|
76
|
+
} : void 0,
|
|
77
|
+
sources: [{
|
|
78
|
+
...autotelMeta.producer !== void 0 && { producer: autotelMeta.producer },
|
|
79
|
+
...autotelMeta.channel !== void 0 && { channel: autotelMeta.channel },
|
|
80
|
+
count: 1,
|
|
81
|
+
firstSeen: now,
|
|
82
|
+
lastSeen: now
|
|
83
|
+
}]
|
|
50
84
|
});
|
|
51
85
|
return;
|
|
52
86
|
}
|
|
@@ -57,6 +91,7 @@ var ArchitectureSnapshotSubscriber = class extends EventSubscriber {
|
|
|
57
91
|
if (traceId && !existing.sampleTraceIds.includes(traceId) && existing.sampleTraceIds.length < this.maxSampleTraceIds) existing.sampleTraceIds.push(traceId);
|
|
58
92
|
existing.channel ??= autotelMeta.channel;
|
|
59
93
|
existing.producer ??= autotelMeta.producer;
|
|
94
|
+
recordSource(existing, autotelMeta.producer, autotelMeta.channel, now);
|
|
60
95
|
existing.consumers = mergeUnique(existing.consumers ?? [], autotelMeta.consumers ?? []);
|
|
61
96
|
existing.schema ??= payload.schema ? {
|
|
62
97
|
source: payload.schema.source,
|
|
@@ -89,7 +124,12 @@ var ArchitectureSnapshotSubscriber = class extends EventSubscriber {
|
|
|
89
124
|
lastSeen: freezeTimestamps ?? obs.lastSeen,
|
|
90
125
|
fieldPaths: obs.fieldPaths.toSorted(),
|
|
91
126
|
sampleTraceIds: obs.sampleTraceIds.toSorted(),
|
|
92
|
-
fieldStats: sortFieldStats(obs.fieldStats)
|
|
127
|
+
fieldStats: sortFieldStats(obs.fieldStats),
|
|
128
|
+
...obs.sources && { sources: obs.sources.map((source) => ({
|
|
129
|
+
...source,
|
|
130
|
+
firstSeen: freezeTimestamps ?? source.firstSeen,
|
|
131
|
+
lastSeen: freezeTimestamps ?? source.lastSeen
|
|
132
|
+
})).toSorted(compareSources) }
|
|
93
133
|
};
|
|
94
134
|
}
|
|
95
135
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autotel-subscribers",
|
|
3
|
-
"version": "56.
|
|
3
|
+
"version": "56.1.0",
|
|
4
4
|
"description": "Write Once, Observe Anywhere - Event subscribers for autotel (Mixpanel, Amplitude, Segment, Slack, webhooks, Loki, file)",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"slow-redact": "^0.3.2"
|
|
102
102
|
},
|
|
103
103
|
"peerDependencies": {
|
|
104
|
-
"autotel": "7.6.
|
|
104
|
+
"autotel": "7.6.1"
|
|
105
105
|
},
|
|
106
106
|
"peerDependenciesMeta": {
|
|
107
107
|
"posthog-node": {
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"@types/node": "^26.1.2",
|
|
127
127
|
"@typescript-eslint/eslint-plugin": "^8.65.0",
|
|
128
128
|
"@typescript-eslint/parser": "^8.65.0",
|
|
129
|
-
"autotel": "7.6.
|
|
129
|
+
"autotel": "7.6.1",
|
|
130
130
|
"drizzle-orm": "^0.45.2",
|
|
131
131
|
"eslint-config-prettier": "^10.1.8",
|
|
132
132
|
"eslint-plugin-unicorn": "^64.0.0",
|