@cravery/firebase 0.0.45 → 0.0.46
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/converters/access/usage.d.ts.map +1 -1
- package/dist/converters/access/usage.js.map +1 -1
- package/dist/converters/equipment/content.d.ts +1 -1
- package/dist/converters/equipment/content.d.ts.map +1 -1
- package/dist/converters/equipment/content.js +2 -2
- package/dist/converters/equipment/content.js.map +1 -1
- package/dist/converters/equipment/meta.d.ts +1 -1
- package/dist/converters/equipment/meta.d.ts.map +1 -1
- package/dist/converters/equipment/meta.js +2 -2
- package/dist/converters/equipment/meta.js.map +1 -1
- package/dist/converters/index.d.ts +2 -1
- package/dist/converters/index.d.ts.map +1 -1
- package/dist/converters/index.js +2 -1
- package/dist/converters/index.js.map +1 -1
- package/dist/converters/ingredients/content.d.ts +1 -1
- package/dist/converters/ingredients/content.d.ts.map +1 -1
- package/dist/converters/ingredients/content.js +2 -2
- package/dist/converters/ingredients/content.js.map +1 -1
- package/dist/converters/ingredients/meta.d.ts +1 -1
- package/dist/converters/ingredients/meta.d.ts.map +1 -1
- package/dist/converters/ingredients/meta.js +2 -2
- package/dist/converters/ingredients/meta.js.map +1 -1
- package/dist/converters/interactions/cook.d.ts +4 -0
- package/dist/converters/interactions/cook.d.ts.map +1 -0
- package/dist/converters/interactions/cook.js +26 -0
- package/dist/converters/interactions/cook.js.map +1 -0
- package/dist/converters/interactions/index.d.ts +4 -0
- package/dist/converters/interactions/index.d.ts.map +1 -0
- package/dist/converters/interactions/index.js +20 -0
- package/dist/converters/interactions/index.js.map +1 -0
- package/dist/converters/interactions/rate.d.ts +4 -0
- package/dist/converters/interactions/rate.d.ts.map +1 -0
- package/dist/converters/interactions/rate.js +26 -0
- package/dist/converters/interactions/rate.js.map +1 -0
- package/dist/converters/interactions/save.d.ts +4 -0
- package/dist/converters/interactions/save.d.ts.map +1 -0
- package/dist/converters/interactions/save.js +26 -0
- package/dist/converters/interactions/save.js.map +1 -0
- package/dist/converters/limits/index.d.ts +2 -0
- package/dist/converters/limits/index.d.ts.map +1 -0
- package/dist/converters/limits/index.js +18 -0
- package/dist/converters/limits/index.js.map +1 -0
- package/dist/converters/limits/usage.d.ts +4 -0
- package/dist/converters/limits/usage.d.ts.map +1 -0
- package/dist/converters/limits/usage.js +21 -0
- package/dist/converters/limits/usage.js.map +1 -0
- package/dist/converters/subscriptions/subscription.d.ts.map +1 -1
- package/dist/converters/subscriptions/subscription.js +4 -4
- package/dist/converters/subscriptions/subscription.js.map +1 -1
- package/dist/converters/users/index.d.ts +0 -2
- package/dist/converters/users/index.d.ts.map +1 -1
- package/dist/converters/users/index.js +0 -2
- package/dist/converters/users/index.js.map +1 -1
- package/dist/lib/monitoring.d.ts +5 -4
- package/dist/lib/monitoring.d.ts.map +1 -1
- package/dist/lib/monitoring.js +93 -25
- package/dist/lib/monitoring.js.map +1 -1
- package/package.json +2 -2
- package/src/converters/equipment/content.ts +1 -1
- package/src/converters/equipment/meta.ts +1 -1
- package/src/converters/index.ts +2 -1
- package/src/converters/ingredients/content.ts +1 -1
- package/src/converters/ingredients/meta.ts +1 -1
- package/src/converters/interactions/cook.ts +36 -0
- package/src/converters/interactions/index.ts +3 -0
- package/src/converters/{users/profile.ts → interactions/rate.ts} +36 -36
- package/src/converters/{users/bookmark.ts → interactions/save.ts} +6 -6
- package/src/converters/{access → limits}/index.ts +1 -1
- package/src/converters/{access → limits}/usage.ts +24 -28
- package/src/converters/subscriptions/subscription.ts +4 -2
- package/src/converters/users/index.ts +0 -2
- package/src/lib/monitoring.ts +121 -33
package/src/lib/monitoring.ts
CHANGED
|
@@ -4,50 +4,112 @@ import {
|
|
|
4
4
|
} from "@opentelemetry/sdk-metrics";
|
|
5
5
|
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
6
6
|
import { MetricExporter } from "@google-cloud/opentelemetry-cloud-monitoring-exporter";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Counter,
|
|
9
|
+
Histogram,
|
|
10
|
+
ObservableGauge,
|
|
11
|
+
Meter,
|
|
12
|
+
Attributes as OtelAttributes,
|
|
13
|
+
} from "@opentelemetry/api";
|
|
14
|
+
|
|
15
|
+
const METRIC_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_.-]*$/;
|
|
16
|
+
const MAX_CACHED_METRICS = 1000;
|
|
17
|
+
|
|
18
|
+
const validateMetricName = (name: string): void => {
|
|
19
|
+
if (!METRIC_NAME_REGEX.test(name)) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Invalid metric name "${name}": must start with a letter and contain only alphanumeric characters, underscores, dots, or hyphens`,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
8
25
|
|
|
9
26
|
const resource = resourceFromAttributes({
|
|
10
27
|
"service.name": "cravery-backend",
|
|
11
28
|
});
|
|
12
29
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
let meterProvider: MeterProvider | null = null;
|
|
31
|
+
let meter: Meter | null = null;
|
|
32
|
+
let isShutdown = false;
|
|
33
|
+
|
|
34
|
+
const initializeProvider = (): void => {
|
|
35
|
+
if (meterProvider) return;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const exporter = new MetricExporter();
|
|
39
|
+
meterProvider = new MeterProvider({
|
|
40
|
+
resource,
|
|
41
|
+
readers: [
|
|
42
|
+
new PeriodicExportingMetricReader({
|
|
43
|
+
exporter,
|
|
44
|
+
exportIntervalMillis: 60000,
|
|
45
|
+
}),
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
meter = meterProvider.getMeter("cravery");
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error("Failed to initialize metrics provider:", error);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
24
54
|
|
|
25
|
-
const
|
|
55
|
+
const getMeter = (): Meter => {
|
|
56
|
+
if (isShutdown) {
|
|
57
|
+
throw new Error("Metrics provider has been shut down");
|
|
58
|
+
}
|
|
59
|
+
if (!meter) {
|
|
60
|
+
initializeProvider();
|
|
61
|
+
}
|
|
62
|
+
return meter!;
|
|
63
|
+
};
|
|
26
64
|
|
|
27
65
|
const counters = new Map<string, Counter>();
|
|
28
66
|
const histograms = new Map<string, Histogram>();
|
|
67
|
+
const gauges = new Map<string, ObservableGauge>();
|
|
29
68
|
|
|
30
69
|
const getCounter = (name: string, description?: string): Counter => {
|
|
70
|
+
validateMetricName(name);
|
|
71
|
+
if (counters.size >= MAX_CACHED_METRICS && !counters.has(name)) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`Maximum number of cached counters (${MAX_CACHED_METRICS}) exceeded. Avoid dynamic metric names.`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
31
76
|
if (!counters.has(name)) {
|
|
32
|
-
counters.set(
|
|
77
|
+
counters.set(
|
|
78
|
+
name,
|
|
79
|
+
getMeter().createCounter(`cravery.${name}`, { description }),
|
|
80
|
+
);
|
|
33
81
|
}
|
|
34
82
|
return counters.get(name)!;
|
|
35
83
|
};
|
|
36
84
|
|
|
37
|
-
|
|
85
|
+
interface HistogramOptions {
|
|
86
|
+
description?: string;
|
|
87
|
+
unit?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const getHistogram = (
|
|
91
|
+
name: string,
|
|
92
|
+
options: HistogramOptions = {},
|
|
93
|
+
): Histogram => {
|
|
94
|
+
validateMetricName(name);
|
|
95
|
+
if (histograms.size >= MAX_CACHED_METRICS && !histograms.has(name)) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Maximum number of cached histograms (${MAX_CACHED_METRICS}) exceeded. Avoid dynamic metric names.`,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
38
100
|
if (!histograms.has(name)) {
|
|
39
101
|
histograms.set(
|
|
40
102
|
name,
|
|
41
|
-
|
|
42
|
-
description,
|
|
43
|
-
unit: "ms",
|
|
103
|
+
getMeter().createHistogram(`cravery.${name}`, {
|
|
104
|
+
description: options.description,
|
|
105
|
+
unit: options.unit ?? "ms",
|
|
44
106
|
}),
|
|
45
107
|
);
|
|
46
108
|
}
|
|
47
109
|
return histograms.get(name)!;
|
|
48
110
|
};
|
|
49
111
|
|
|
50
|
-
type Attributes =
|
|
112
|
+
type Attributes = OtelAttributes;
|
|
51
113
|
|
|
52
114
|
export const incrementCounter = (
|
|
53
115
|
name: string,
|
|
@@ -71,21 +133,34 @@ export const withTiming = async <T>(
|
|
|
71
133
|
attributes?: Attributes,
|
|
72
134
|
): Promise<T> => {
|
|
73
135
|
const start = Date.now();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
try {
|
|
137
|
+
return await fn();
|
|
138
|
+
} finally {
|
|
139
|
+
recordTiming(name, Date.now() - start, attributes);
|
|
140
|
+
}
|
|
77
141
|
};
|
|
78
142
|
|
|
79
143
|
export const registerGauge = (
|
|
80
144
|
name: string,
|
|
81
|
-
callback: () => number
|
|
145
|
+
callback: () => number,
|
|
82
146
|
attributes?: Attributes,
|
|
83
147
|
): ObservableGauge => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
148
|
+
validateMetricName(name);
|
|
149
|
+
if (gauges.has(name)) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Gauge "${name}" is already registered. Gauges cannot be re-registered.`,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
const gauge = getMeter().createObservableGauge(`cravery.${name}`);
|
|
155
|
+
gauge.addCallback((observableResult) => {
|
|
156
|
+
try {
|
|
157
|
+
const value = callback();
|
|
158
|
+
observableResult.observe(value, attributes);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error(`Error in gauge callback for "${name}":`, error);
|
|
161
|
+
}
|
|
88
162
|
});
|
|
163
|
+
gauges.set(name, gauge);
|
|
89
164
|
return gauge;
|
|
90
165
|
};
|
|
91
166
|
|
|
@@ -102,11 +177,24 @@ export const createMetricsScope = (defaultAttributes: Attributes) => ({
|
|
|
102
177
|
attributes?: Attributes,
|
|
103
178
|
) => withTiming(name, fn, { ...defaultAttributes, ...attributes }),
|
|
104
179
|
|
|
105
|
-
registerGauge: (
|
|
106
|
-
name
|
|
107
|
-
callback: () => number | Promise<number>,
|
|
108
|
-
attributes?: Attributes,
|
|
109
|
-
) => registerGauge(name, callback, { ...defaultAttributes, ...attributes }),
|
|
180
|
+
registerGauge: (name: string, callback: () => number, attributes?: Attributes) =>
|
|
181
|
+
registerGauge(name, callback, { ...defaultAttributes, ...attributes }),
|
|
110
182
|
});
|
|
111
183
|
|
|
112
|
-
export const
|
|
184
|
+
export const forceFlush = async (): Promise<void> => {
|
|
185
|
+
if (!meterProvider || isShutdown) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
await meterProvider.forceFlush();
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const shutdown = async (): Promise<void> => {
|
|
192
|
+
if (!meterProvider || isShutdown) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
isShutdown = true;
|
|
196
|
+
await meterProvider.shutdown();
|
|
197
|
+
counters.clear();
|
|
198
|
+
histograms.clear();
|
|
199
|
+
gauges.clear();
|
|
200
|
+
};
|