@friggframework/core 2.0.0--canary.622.eb2c9bd.0 → 2.0.0--canary.622.faffe5f.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/application/commands/usage-commands.js +5 -4
- package/application/index.js +2 -2
- package/core/create-handler.js +2 -2
- package/handlers/integration-event-dispatcher.js +1 -1
- package/index.js +1 -1
- package/integrations/integration-base.js +5 -5
- package/modules/requester/requester.js +2 -2
- package/package.json +5 -5
- package/reporting/reporting-router.js +1 -1
- package/reporting/use-cases/list-integrations-report.js +2 -2
- package/telemetry/bind-telemetry-context.js +1 -1
- package/telemetry/canonical-counters.js +1 -1
- package/telemetry/exporters/exporter-factory.js +2 -2
- package/telemetry/instrument-handler.js +1 -1
- package/telemetry/no-op-telemetry.js +1 -1
- package/telemetry/north-star.js +1 -1
- package/telemetry/otel-telemetry.js +1 -1
- package/telemetry/plugin-subscribers-singleton.js +2 -2
- package/telemetry/plugin-subscribers.js +1 -1
- package/telemetry/telemetry-config.js +1 -1
- package/telemetry/telemetry-context.js +1 -1
- package/telemetry/telemetry-event-bus.js +2 -2
- package/telemetry/telemetry-service.js +3 -3
- package/telemetry/telemetry-singleton.js +1 -1
- package/telemetry/usage-rollup-singleton.js +1 -1
- package/telemetry/usage-rollup-subscriber.js +3 -3
- package/telemetry/usage-windows.js +1 -1
- package/usage/repositories/usage-repository-interface.js +1 -1
- package/usage/repositories/usage-repository-postgres.js +1 -1
- package/usage/tracked-metrics.js +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Usage Commands
|
|
3
3
|
*
|
|
4
|
-
* Application Layer — the read/write surface over the durable usage store
|
|
5
|
-
*
|
|
4
|
+
* Application Layer — the read/write surface over the durable usage store.
|
|
5
|
+
* Exposed as `frigg.usage.*` on the unified command object so
|
|
6
6
|
* reports and integration code query usage without touching the repository.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
@@ -33,7 +33,8 @@ function createUsageCommands({ usageRepository, northStar = null } = {}) {
|
|
|
33
33
|
value = 1,
|
|
34
34
|
at = new Date(),
|
|
35
35
|
}) {
|
|
36
|
-
|
|
36
|
+
const windows = computeUsageWindows(at);
|
|
37
|
+
for (const window of windows) {
|
|
37
38
|
await repository.increment({
|
|
38
39
|
integrationId,
|
|
39
40
|
integrationType,
|
|
@@ -53,7 +54,7 @@ function createUsageCommands({ usageRepository, northStar = null } = {}) {
|
|
|
53
54
|
},
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
|
-
* First-class North Star read
|
|
57
|
+
* First-class North Star read. Resolves the
|
|
57
58
|
* configured counter for an integration type (byType wins over default),
|
|
58
59
|
* then returns its totals from the durable usage store. Returns `null`
|
|
59
60
|
* when no North Star is configured, so callers can branch without
|
package/application/index.js
CHANGED
|
@@ -19,7 +19,7 @@ const { createUsageCommands } = require('./commands/usage-commands');
|
|
|
19
19
|
* @param {Object} params.integrationClass - Integration class (required)
|
|
20
20
|
* @param {Object} [params.northStar] - Resolved North Star config
|
|
21
21
|
* (`Definition.telemetry.northStar`) so `frigg.usage.northStar(...)` can read
|
|
22
|
-
* it
|
|
22
|
+
* it. Injected by the caller that owns the app definition
|
|
23
23
|
* (the handler/report runner) — the application layer never reaches up to load
|
|
24
24
|
* it. Omitted → usage reads report no North Star.
|
|
25
25
|
* @returns {Object} Unified commands object with all CRUD operations
|
|
@@ -57,7 +57,7 @@ function createFriggCommands({ integrationClass, northStar = null }) {
|
|
|
57
57
|
// Process commands
|
|
58
58
|
...processCommands,
|
|
59
59
|
|
|
60
|
-
// Usage read/write
|
|
60
|
+
// Usage read/write — nested to match `frigg.usage.*`.
|
|
61
61
|
// northStar injected by the caller (composition root), not loaded here.
|
|
62
62
|
usage: createUsageCommands({ northStar }),
|
|
63
63
|
};
|
package/core/create-handler.js
CHANGED
|
@@ -153,8 +153,8 @@ const createHandler = (optionByName = {}) => {
|
|
|
153
153
|
? usageRollup
|
|
154
154
|
: getUsageRollupSubscriber();
|
|
155
155
|
|
|
156
|
-
// Wire adopter-declared telemetry subscribers once per cold start
|
|
157
|
-
//
|
|
156
|
+
// Wire adopter-declared telemetry subscribers once per cold start.
|
|
157
|
+
// Memoized in the singleton, so this is a cheap
|
|
158
158
|
// no-op after the first invocation.
|
|
159
159
|
getPluginTelemetrySubscribers();
|
|
160
160
|
|
|
@@ -25,7 +25,7 @@ class IntegrationEventDispatcher {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Resolve + invoke a handler, auto-instrumented
|
|
28
|
+
* Resolve + invoke a handler, auto-instrumented. This
|
|
29
29
|
* is the seam for queue/webhook/defined-route dispatch; the `this.on` path
|
|
30
30
|
* (user actions, lifecycle) is instrumented in IntegrationBase.send().
|
|
31
31
|
*/
|
package/index.js
CHANGED
|
@@ -79,7 +79,7 @@ class IntegrationBase {
|
|
|
79
79
|
// Tier 3 Integration Extensions — see packages/core/integrations/EXTENSIONS.md
|
|
80
80
|
// Shape: { [bindingName]: { extension, handlers?: { [eventName]: methodName } } }
|
|
81
81
|
extensions: {},
|
|
82
|
-
// Usage-counter opt-in
|
|
82
|
+
// Usage-counter opt-in. Declaring a canonical key opts into the
|
|
83
83
|
// cross-integration comparison report + durable rollup; custom keys are
|
|
84
84
|
// comparable within this integration type. Shape:
|
|
85
85
|
// usage: { canonical: ['records.synced', ...], custom: { 'deals.enriched': { unit, label } } }
|
|
@@ -108,7 +108,7 @@ class IntegrationBase {
|
|
|
108
108
|
this.messages = { errors: [], warnings: [] };
|
|
109
109
|
this._isHydrated = false;
|
|
110
110
|
|
|
111
|
-
// Telemetry
|
|
111
|
+
// Telemetry: every instance carries the service so integration
|
|
112
112
|
// code can call `this.telemetry.*`. Extracted before the record check so
|
|
113
113
|
// passing only `telemetry` never triggers a hollow hydration. Bound to
|
|
114
114
|
// this instance so emissions auto-carry `integration_type` for the usage
|
|
@@ -223,7 +223,7 @@ class IntegrationBase {
|
|
|
223
223
|
|
|
224
224
|
this._isHydrated = Boolean(this.id);
|
|
225
225
|
|
|
226
|
-
//
|
|
226
|
+
// Log the instance-open exactly once per hydrated
|
|
227
227
|
// instance, carrying the standard identifier set — so an integration is
|
|
228
228
|
// visible in telemetry even on a path that never dispatches a handler.
|
|
229
229
|
// High-cardinality ids ride the bus context (3rd arg), never metric
|
|
@@ -249,7 +249,7 @@ class IntegrationBase {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
/**
|
|
252
|
-
* Standard telemetry identifier set
|
|
252
|
+
* Standard telemetry identifier set. Assembled from the
|
|
253
253
|
* hydrated record (integrationId, userId, version), the static Definition
|
|
254
254
|
* (integrationType, version fallback), and the environment (stage, appName).
|
|
255
255
|
* High-cardinality ids (integrationId, userId) ride span baggage only — never
|
|
@@ -812,7 +812,7 @@ class IntegrationBase {
|
|
|
812
812
|
`Event ${event} is not defined in the Integration event object`
|
|
813
813
|
);
|
|
814
814
|
}
|
|
815
|
-
// Auto-instrument
|
|
815
|
+
// Auto-instrument. This is the seam for user
|
|
816
816
|
// actions, config-options, and lifecycle events dispatched via `this.on`
|
|
817
817
|
// (the queue/webhook/route paths go through IntegrationEventDispatcher).
|
|
818
818
|
return instrumentHandler(
|
|
@@ -44,7 +44,7 @@ class Requester extends Delegate {
|
|
|
44
44
|
// Instance methods can use this.fetch without differentiating
|
|
45
45
|
this.fetch = get(params, 'fetch', fetch);
|
|
46
46
|
|
|
47
|
-
// Telemetry
|
|
47
|
+
// Telemetry. Defaults to the process singleton; overridable
|
|
48
48
|
// for tests. Outbound requests are instrumented in `_request`.
|
|
49
49
|
//
|
|
50
50
|
// Attribution boundary: the `frigg.apimodule.requests` OTel metric fires
|
|
@@ -103,7 +103,7 @@ class Requester extends Delegate {
|
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
|
-
* Instrumenting entry point
|
|
106
|
+
* Instrumenting entry point. Wraps the whole logical request —
|
|
107
107
|
* including retry/refresh recursion — in a single span + one
|
|
108
108
|
* `frigg.apimodule.requests` counter, emitted on the `i === 0` boundary so
|
|
109
109
|
* retries are never double-counted. The full URL rides the span only; the
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/core",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.622.
|
|
4
|
+
"version": "2.0.0--canary.622.faffe5f.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.588.0",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@friggframework/eslint-config": "2.0.0--canary.622.
|
|
49
|
-
"@friggframework/prettier-config": "2.0.0--canary.622.
|
|
50
|
-
"@friggframework/test": "2.0.0--canary.622.
|
|
48
|
+
"@friggframework/eslint-config": "2.0.0--canary.622.faffe5f.0",
|
|
49
|
+
"@friggframework/prettier-config": "2.0.0--canary.622.faffe5f.0",
|
|
50
|
+
"@friggframework/test": "2.0.0--canary.622.faffe5f.0",
|
|
51
51
|
"@prisma/client": "^6.19.3",
|
|
52
52
|
"@types/lodash": "4.17.15",
|
|
53
53
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"publishConfig": {
|
|
88
88
|
"access": "public"
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "faffe5ff8b3fea6bbb46a52502cbd5b5ecb35559"
|
|
91
91
|
}
|
|
@@ -40,7 +40,7 @@ function buildTypeLabels() {
|
|
|
40
40
|
|
|
41
41
|
function createReportingRouter() {
|
|
42
42
|
const reportingRepository = createReportingRepository();
|
|
43
|
-
//
|
|
43
|
+
// Enrich the report with feature-usage columns read from
|
|
44
44
|
// the Frigg-owned usage store. Best-effort — a failure to construct it never
|
|
45
45
|
// blocks the structural report.
|
|
46
46
|
let usageRepository = null;
|
|
@@ -26,7 +26,7 @@ class ListIntegrationsReport {
|
|
|
26
26
|
throw new Error('reportingRepository is required');
|
|
27
27
|
}
|
|
28
28
|
this.reportingRepository = reportingRepository;
|
|
29
|
-
// Optional
|
|
29
|
+
// Optional usage store (the ADR-010 hand-off). When present, the
|
|
30
30
|
// report's byType buckets are enriched with feature-usage columns read
|
|
31
31
|
// ONLY from this store — never an external APM.
|
|
32
32
|
this.usageRepository = usageRepository || null;
|
|
@@ -87,7 +87,7 @@ class ListIntegrationsReport {
|
|
|
87
87
|
bucket.byStatus[statusKey] = (bucket.byStatus[statusKey] ?? 0) + 1;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
// Additive usage columns
|
|
90
|
+
// Additive usage columns. Read per-type totals for each
|
|
91
91
|
// canonical counter; a type with no rows reads as 0. Guarded so a usage
|
|
92
92
|
// store failure never breaks the structural report.
|
|
93
93
|
if (this.usageRepository) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wrap a telemetry service so an integration instance's emissions automatically
|
|
3
|
-
* carry its `integration_type
|
|
3
|
+
* carry its `integration_type`. This lets developers write
|
|
4
4
|
* `this.telemetry.count('records.synced', n, { entity })` with no per-call
|
|
5
5
|
* boilerplate, while the usage rollup still attributes the counter to the right
|
|
6
6
|
* integration type.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Canonical usage-counter vocabulary
|
|
2
|
+
* Canonical usage-counter vocabulary.
|
|
3
3
|
*
|
|
4
4
|
* These core-owned, versioned keys are the ONLY metrics guaranteed comparable
|
|
5
5
|
* *across* integration types — they power ADR-010's apples-to-apples comparison
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Builds OpenTelemetry span/metric exporters from an app-definition descriptor
|
|
3
|
-
*
|
|
2
|
+
* Builds OpenTelemetry span/metric exporters from an app-definition descriptor.
|
|
3
|
+
* All OTel packages are lazy-`require`d here so the no-op
|
|
4
4
|
* path (which never calls this) loads zero OTel modules.
|
|
5
5
|
*
|
|
6
6
|
* Supported descriptor `type`s:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wraps a single integration handler invocation with a span + the
|
|
3
|
-
* `frigg.handler.invocations` counter
|
|
3
|
+
* `frigg.handler.invocations` counter. Shared by the two
|
|
4
4
|
* dispatch seams — `IntegrationBase.send()` and `IntegrationEventDispatcher` —
|
|
5
5
|
* so both paths are instrumented identically.
|
|
6
6
|
*
|
|
@@ -8,7 +8,7 @@ const {
|
|
|
8
8
|
* No-op telemetry implementation.
|
|
9
9
|
*
|
|
10
10
|
* This is the default when no OTel exporter is configured, so telemetry "rides
|
|
11
|
-
* for free"
|
|
11
|
+
* for free": integration code can call `this.telemetry.*`
|
|
12
12
|
* unconditionally and it costs nothing on the OTel side. Critically, this module
|
|
13
13
|
* imports **zero** OpenTelemetry packages — the no-op path never loads the OTel
|
|
14
14
|
* SDK (guarded by a require-graph test), protecting Lambda cold-start.
|
package/telemetry/north-star.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Adopter North Star metric
|
|
2
|
+
* Adopter North Star metric. A North Star simply references
|
|
3
3
|
* a usage-counter key (canonical or custom); its value is then read like any
|
|
4
4
|
* other counter via `frigg.usage.totals({ metric: northStarKey })`. It is
|
|
5
5
|
* populated either by (a) direct emission of that counter, or (b) derived from a
|
|
@@ -47,7 +47,7 @@ function ensureContextManager() {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* The OpenTelemetry-backed telemetry service
|
|
50
|
+
* The OpenTelemetry-backed telemetry service. Reached only
|
|
51
51
|
* when a real exporter is configured; `createTelemetry` returns the no-op
|
|
52
52
|
* otherwise. `BatchSpanProcessor` is used uniformly — spans are delivered by the
|
|
53
53
|
* bounded `forceFlush()` the Lambda handler awaits before the container freezes
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const { wireTelemetrySubscribers } = require('./plugin-subscribers');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Process-wide wiring of adopter-declared telemetry subscribers
|
|
5
|
-
*
|
|
4
|
+
* Process-wide wiring of adopter-declared telemetry subscribers. Built once per
|
|
5
|
+
* cold start and reused for the life of the Lambda
|
|
6
6
|
* container, mirroring the usage-rollup singleton. Independent of the usage
|
|
7
7
|
* rollup: adopter taps wire even when no integration declares `Definition.usage`.
|
|
8
8
|
* Never throws — a bad/absent app definition just means no adopter taps.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Declarative plugin/extension telemetry taps
|
|
2
|
+
* Declarative plugin/extension telemetry taps.
|
|
3
3
|
*
|
|
4
4
|
* The built-in usage rollup and North Star derivation subscribe to the telemetry
|
|
5
5
|
* bus in framework code; this lets an ADOPTER subscribe declaratively from the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolves and validates the telemetry section of an app definition
|
|
3
|
-
*
|
|
3
|
+
* into a normalized config the TelemetryService and
|
|
4
4
|
* usage rollup consume: `{ exporter, northStar, sampleRatio }`.
|
|
5
5
|
*
|
|
6
6
|
* Exporter default is keyed off STAGE: only a genuinely LOCAL run (STAGE=local)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { AsyncLocalStorage } = require('node:async_hooks');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Ambient telemetry context
|
|
4
|
+
* Ambient telemetry context. A single process-wide AsyncLocalStorage
|
|
5
5
|
* holds the standard identifiers ({integrationId, integrationType, userId,
|
|
6
6
|
* version, ...}) for the duration of a handler, set once at the handler seam via
|
|
7
7
|
* `telemetry.withContext(...)`. Any emission during that async scope — including
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TelemetryEventBus — the internal event stream telemetry flows onto
|
|
3
|
-
*
|
|
2
|
+
* TelemetryEventBus — the internal event stream telemetry flows onto.
|
|
3
|
+
* Plugins/extensions and the built-in usage rollup
|
|
4
4
|
* subscribe here; it is deliberately independent of OTel export (Decision 7),
|
|
5
5
|
* so usage counters persist even when the OTel exporter is a no-op.
|
|
6
6
|
*
|
|
@@ -12,7 +12,7 @@ function isNoOpExporter(exporter) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Create the vendor-neutral telemetry service
|
|
15
|
+
* Create the vendor-neutral telemetry service.
|
|
16
16
|
*
|
|
17
17
|
* Integration code uses the returned object (`this.telemetry`) and never imports
|
|
18
18
|
* a backend SDK. When no exporter is configured the service is a pure no-op that
|
|
@@ -26,8 +26,8 @@ function isNoOpExporter(exporter) {
|
|
|
26
26
|
* @param {object} [options.bus] Event bus to reuse (defaults to a fresh one).
|
|
27
27
|
*/
|
|
28
28
|
function createTelemetry(options = {}) {
|
|
29
|
-
// The internal event stream is always on and independent of OTel export
|
|
30
|
-
//
|
|
29
|
+
// The internal event stream is always on and independent of OTel export:
|
|
30
|
+
// the usage rollup + plugin taps must work even when
|
|
31
31
|
// the OTel exporter is a no-op. The bus is pure JS, so this does not load
|
|
32
32
|
// any OTel module on the no-op path.
|
|
33
33
|
const bus = options.bus || createTelemetryEventBus();
|
|
@@ -2,7 +2,7 @@ const { createTelemetry } = require('./telemetry-service');
|
|
|
2
2
|
const { createNoOpTelemetry } = require('./no-op-telemetry');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Process-wide telemetry singleton
|
|
5
|
+
* Process-wide telemetry singleton. Created lazily on first use and
|
|
6
6
|
* reused for the life of the Lambda container, so the OTel SDK initialises at
|
|
7
7
|
* most once per cold start. Building it never throws — any failure (e.g. no app
|
|
8
8
|
* definition on disk in a unit test) falls back to the no-op so a handler is
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { createUsageRollupSubscriber } = require('./usage-rollup-subscriber');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Process-wide usage-rollup subscriber
|
|
4
|
+
* Process-wide usage-rollup subscriber. Built once per cold start,
|
|
5
5
|
* subscribed to the telemetry singleton's bus, and reused across invocations.
|
|
6
6
|
* Returns null when usage is disabled (no integration declares Definition.usage)
|
|
7
7
|
* or when the app definition can't be loaded — the handler then skips the flush.
|
|
@@ -3,8 +3,8 @@ const { computeUsageWindows } = require('./usage-windows');
|
|
|
3
3
|
const WEBHOOK_EVENT_NAMES = new Set(['ON_WEBHOOK']);
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Framework auto-signal metric names → the canonical usage key they feed
|
|
7
|
-
*
|
|
6
|
+
* Framework auto-signal metric names → the canonical usage key they feed.
|
|
7
|
+
* Resolvers receive (attributes, context) and may return null to
|
|
8
8
|
* decline. Handler invocations map by event: USER_ACTION → user_actions; the
|
|
9
9
|
* DB-connected `ON_WEBHOOK` queue dispatch → webhooks.received (per-integration,
|
|
10
10
|
* and where a durable write is actually possible — the HTTP receipt handler is
|
|
@@ -22,7 +22,7 @@ const METRIC_TO_CANONICAL = {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* The built-in usage-rollup subscriber
|
|
25
|
+
* The built-in usage-rollup subscriber. Subscribes to the
|
|
26
26
|
* telemetry event bus and folds *declared* counters (canonical or custom) into
|
|
27
27
|
* the durable usage store. It buffers within an invocation and writes on
|
|
28
28
|
* `flush()` (no timers — Lambda-safe), or drops the buffer on `discard()` for an
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Compute the rollup window keys a usage event falls into
|
|
2
|
+
* Compute the rollup window keys a usage event falls into.
|
|
3
3
|
* Windows are UTC and prefixed by their granularity so the store can filter a
|
|
4
4
|
* series by bucket (`window startsWith 'day:'`).
|
|
5
5
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Port for the durable usage-counter store
|
|
2
|
+
* Port for the durable usage-counter store.
|
|
3
3
|
*
|
|
4
4
|
* The store is deliberately isolated (ADR-010 Decision 3): its fact rows carry
|
|
5
5
|
* NO userId and NO foreign key to Integration, so a user-scoped query can never
|
|
@@ -2,7 +2,7 @@ const { prisma } = require('../../database/prisma');
|
|
|
2
2
|
const { UsageRepositoryInterface } = require('./usage-repository-interface');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Prisma-backed usage store
|
|
5
|
+
* Prisma-backed usage store. This is the canonical implementation;
|
|
6
6
|
* because Prisma abstracts the underlying database, the Mongo and DocumentDB
|
|
7
7
|
* adapters extend this class unchanged (see their files). All queries touch only
|
|
8
8
|
* the isolated `UsageCounter` model — never user/integration-scoped tables.
|
package/usage/tracked-metrics.js
CHANGED
|
@@ -2,7 +2,7 @@ const { isCanonicalCounter } = require('../telemetry/canonical-counters');
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Compute the set of usage-counter keys the rollup should persist, from each
|
|
5
|
-
* integration's `Definition.usage` opt-in
|
|
5
|
+
* integration's `Definition.usage` opt-in.
|
|
6
6
|
* Declaring a canonical key opts into cross-type comparison + the rollup; custom
|
|
7
7
|
* keys are tracked per integration type. Unknown canonical keys are dropped with
|
|
8
8
|
* a warning (lazy validation, matching how Definition is treated elsewhere).
|