@zuplo/cli 6.71.27 → 6.72.1

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 (135) hide show
  1. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-json-stringify/.github/dependabot.yml +42 -2
  2. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-json-stringify/README.md +5 -5
  3. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-json-stringify/index.js +4 -7
  4. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-json-stringify/package.json +3 -3
  5. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-json-stringify/test/additionalProperties.test.js +47 -0
  6. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-json-stringify/test/const.test.js +20 -0
  7. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-json-stringify/test/patternProperties.test.js +24 -0
  8. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/.gitattributes +2 -0
  9. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/.github/dependabot.yml +53 -0
  10. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/.github/workflows/ci.yml +154 -0
  11. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/.github/workflows/lock-threads.yml +19 -0
  12. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/LICENSE +30 -0
  13. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/README.md +152 -0
  14. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/benchmark/benchmark.mjs +159 -0
  15. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/benchmark/encoder.mjs +54 -0
  16. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/benchmark/equal.mjs +51 -0
  17. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/benchmark/non-simple-domain.mjs +22 -0
  18. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/benchmark/package.json +17 -0
  19. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/benchmark/string-array-to-hex-stripped.mjs +24 -0
  20. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/benchmark/ws-is-secure.mjs +65 -0
  21. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/eslint.config.js +6 -0
  22. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/index.js +405 -0
  23. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/lib/schemes.js +267 -0
  24. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/lib/utils.js +585 -0
  25. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/package.json +68 -0
  26. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/ajv.test.js +43 -0
  27. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/equal.test.js +168 -0
  28. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/fixtures/uri-js-parse.json +501 -0
  29. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/fixtures/uri-js-serialize.json +120 -0
  30. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/parse.test.js +325 -0
  31. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
  32. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/resolve.test.js +87 -0
  33. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/rfc-3986.test.js +90 -0
  34. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/scheme-normalization.test.js +16 -0
  35. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/security-normalization.test.js +39 -0
  36. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/security-utf8-encoding.test.js +0 -0
  37. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/security.test.js +161 -0
  38. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/serialize.test.js +151 -0
  39. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/uri-js-compatibility.test.js +33 -0
  40. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/uri-js.test.js +912 -0
  41. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/test/util.test.js +47 -0
  42. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/tsconfig.json +10 -0
  43. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/types/index.d.ts +51 -0
  44. package/node_modules/@fastify/fast-json-stringify-compiler/node_modules/fast-uri/types/index.tst.ts +15 -0
  45. package/node_modules/@posthog/core/dist/index.d.ts +3 -0
  46. package/node_modules/@posthog/core/dist/index.d.ts.map +1 -1
  47. package/node_modules/@posthog/core/dist/index.js +133 -93
  48. package/node_modules/@posthog/core/dist/index.mjs +2 -1
  49. package/node_modules/@posthog/core/dist/metrics/index.d.ts +61 -0
  50. package/node_modules/@posthog/core/dist/metrics/index.d.ts.map +1 -0
  51. package/node_modules/@posthog/core/dist/metrics/index.js +326 -0
  52. package/node_modules/@posthog/core/dist/metrics/index.mjs +283 -0
  53. package/node_modules/@posthog/core/dist/metrics/metrics-utils.d.ts +41 -0
  54. package/node_modules/@posthog/core/dist/metrics/metrics-utils.d.ts.map +1 -0
  55. package/node_modules/@posthog/core/dist/metrics/metrics-utils.js +117 -0
  56. package/node_modules/@posthog/core/dist/metrics/metrics-utils.mjs +68 -0
  57. package/node_modules/@posthog/core/dist/metrics/types.d.ts +69 -0
  58. package/node_modules/@posthog/core/dist/metrics/types.d.ts.map +1 -0
  59. package/node_modules/@posthog/core/dist/metrics/types.js +18 -0
  60. package/node_modules/@posthog/core/dist/metrics/types.mjs +0 -0
  61. package/node_modules/@posthog/core/dist/posthog-core-stateless.d.ts +2 -0
  62. package/node_modules/@posthog/core/dist/posthog-core-stateless.d.ts.map +1 -1
  63. package/node_modules/@posthog/core/dist/posthog-core-stateless.js +16 -1
  64. package/node_modules/@posthog/core/dist/posthog-core-stateless.mjs +16 -1
  65. package/node_modules/@posthog/core/package.json +2 -2
  66. package/node_modules/@posthog/core/src/index.ts +20 -0
  67. package/node_modules/@posthog/core/src/metrics/index.spec.ts +459 -0
  68. package/node_modules/@posthog/core/src/metrics/index.ts +414 -0
  69. package/node_modules/@posthog/core/src/metrics/metrics-utils.ts +100 -0
  70. package/node_modules/@posthog/core/src/metrics/types.ts +89 -0
  71. package/node_modules/@posthog/core/src/posthog-core-stateless.ts +26 -0
  72. package/node_modules/@posthog/types/dist/capture-metric.d.ts +122 -0
  73. package/node_modules/@posthog/types/dist/capture-metric.d.ts.map +1 -0
  74. package/node_modules/@posthog/types/dist/capture-metric.js +36 -0
  75. package/node_modules/@posthog/types/dist/capture-metric.mjs +2 -0
  76. package/node_modules/@posthog/types/dist/index.d.ts +3 -1
  77. package/node_modules/@posthog/types/dist/index.d.ts.map +1 -1
  78. package/node_modules/@posthog/types/dist/index.js +19 -1
  79. package/node_modules/@posthog/types/dist/index.mjs +2 -0
  80. package/node_modules/@posthog/types/dist/posthog-config.d.ts +60 -0
  81. package/node_modules/@posthog/types/dist/posthog-config.d.ts.map +1 -1
  82. package/node_modules/@posthog/types/package.json +1 -1
  83. package/node_modules/@posthog/types/src/capture-metric.ts +133 -0
  84. package/node_modules/@posthog/types/src/index.ts +17 -0
  85. package/node_modules/@posthog/types/src/posthog-config.ts +62 -0
  86. package/node_modules/@types/node/README.md +1 -1
  87. package/node_modules/@types/node/fs/promises.d.ts +16 -6
  88. package/node_modules/@types/node/package.json +2 -2
  89. package/node_modules/@zuplo/core/package.json +1 -1
  90. package/node_modules/@zuplo/graphql/package.json +1 -1
  91. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  92. package/node_modules/@zuplo/otel/package.json +1 -1
  93. package/node_modules/@zuplo/runtime/out/esm/{chunk-D3O7C43P.js → chunk-IC7XGD5C.js} +93 -93
  94. package/node_modules/@zuplo/runtime/out/esm/chunk-IC7XGD5C.js.map +1 -0
  95. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  96. package/node_modules/@zuplo/runtime/out/esm/index.js.map +1 -1
  97. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +9 -9
  98. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js.map +1 -1
  99. package/node_modules/@zuplo/runtime/out/types/index.d.ts +830 -6
  100. package/node_modules/@zuplo/runtime/out/types/mcp-gateway/index.d.ts +30 -0
  101. package/node_modules/@zuplo/runtime/package.json +1 -1
  102. package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -1
  103. package/node_modules/lru-cache/dist/commonjs/browser/index.js +11 -4
  104. package/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -1
  105. package/node_modules/lru-cache/dist/commonjs/browser/index.min.js +1 -1
  106. package/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +3 -3
  107. package/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -1
  108. package/node_modules/lru-cache/dist/commonjs/index.js +11 -4
  109. package/node_modules/lru-cache/dist/commonjs/index.js.map +1 -1
  110. package/node_modules/lru-cache/dist/commonjs/index.min.js +1 -1
  111. package/node_modules/lru-cache/dist/commonjs/index.min.js.map +3 -3
  112. package/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -1
  113. package/node_modules/lru-cache/dist/commonjs/node/index.js +11 -4
  114. package/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -1
  115. package/node_modules/lru-cache/dist/commonjs/node/index.min.js +1 -1
  116. package/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +3 -3
  117. package/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -1
  118. package/node_modules/lru-cache/dist/esm/browser/index.js +11 -4
  119. package/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -1
  120. package/node_modules/lru-cache/dist/esm/browser/index.min.js +1 -1
  121. package/node_modules/lru-cache/dist/esm/browser/index.min.js.map +3 -3
  122. package/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -1
  123. package/node_modules/lru-cache/dist/esm/index.js +11 -4
  124. package/node_modules/lru-cache/dist/esm/index.js.map +1 -1
  125. package/node_modules/lru-cache/dist/esm/index.min.js +1 -1
  126. package/node_modules/lru-cache/dist/esm/index.min.js.map +3 -3
  127. package/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -1
  128. package/node_modules/lru-cache/dist/esm/node/index.js +11 -4
  129. package/node_modules/lru-cache/dist/esm/node/index.js.map +1 -1
  130. package/node_modules/lru-cache/dist/esm/node/index.min.js +1 -1
  131. package/node_modules/lru-cache/dist/esm/node/index.min.js.map +3 -3
  132. package/node_modules/lru-cache/package.json +1 -1
  133. package/package.json +6 -6
  134. package/node_modules/@zuplo/runtime/out/esm/chunk-D3O7C43P.js.map +0 -1
  135. /package/node_modules/@zuplo/runtime/out/esm/{chunk-D3O7C43P.js.LEGAL.txt → chunk-IC7XGD5C.js.LEGAL.txt} +0 -0
@@ -0,0 +1,326 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ buildMetricsResourceAttributes: ()=>external_metrics_utils_js_namespaceObject.buildMetricsResourceAttributes,
28
+ PostHogMetrics: ()=>PostHogMetrics,
29
+ buildOtlpMetricsPayload: ()=>external_metrics_utils_js_namespaceObject.buildOtlpMetricsPayload,
30
+ DEFAULT_HISTOGRAM_BOUNDS: ()=>external_metrics_utils_js_namespaceObject.DEFAULT_HISTOGRAM_BOUNDS
31
+ });
32
+ const index_js_namespaceObject = require("../utils/index.js");
33
+ const logs_utils_js_namespaceObject = require("../logs/logs-utils.js");
34
+ const external_metrics_utils_js_namespaceObject = require("./metrics-utils.js");
35
+ const OTLP_TEMPORALITY_DELTA = 1;
36
+ class PostHogMetrics {
37
+ constructor(_instance, _config, _logger){
38
+ this._instance = _instance;
39
+ this._config = _config;
40
+ this._logger = _logger;
41
+ this._series = new Map();
42
+ this._flushPromise = null;
43
+ this._seriesCapWarned = false;
44
+ this._typeByName = new Map();
45
+ this._typeCollisionWarned = new Set();
46
+ }
47
+ count(name, value = 1, options) {
48
+ this._capture({
49
+ name,
50
+ type: 'count',
51
+ value,
52
+ unit: options?.unit,
53
+ attributes: options?.attributes
54
+ });
55
+ }
56
+ gauge(name, value, options) {
57
+ this._capture({
58
+ name,
59
+ type: 'gauge',
60
+ value,
61
+ unit: options?.unit,
62
+ attributes: options?.attributes
63
+ });
64
+ }
65
+ histogram(name, value, options) {
66
+ this._capture({
67
+ name,
68
+ type: 'histogram',
69
+ value,
70
+ unit: options?.unit,
71
+ attributes: options?.attributes
72
+ });
73
+ }
74
+ flush() {
75
+ const prev = this._flushPromise;
76
+ const run = async ()=>{
77
+ if (prev) await prev.catch(()=>{});
78
+ await this._doFlush();
79
+ };
80
+ const p = run().finally(()=>{
81
+ if (this._flushPromise === p) this._flushPromise = null;
82
+ });
83
+ this._flushPromise = p;
84
+ return p;
85
+ }
86
+ drainWindow() {
87
+ if (0 === this._series.size) return null;
88
+ const window = this._series;
89
+ this._series = new Map();
90
+ this._seriesCapWarned = false;
91
+ this._typeByName = new Map();
92
+ this._typeCollisionWarned = new Set();
93
+ return this._buildPayload(window);
94
+ }
95
+ reset() {
96
+ this._clearFlushTimer();
97
+ this._series = new Map();
98
+ this._flushPromise = null;
99
+ this._seriesCapWarned = false;
100
+ this._typeByName = new Map();
101
+ this._typeCollisionWarned = new Set();
102
+ }
103
+ _capture(sample) {
104
+ if (this._instance.isDisabled || this._instance.optedOut) return;
105
+ const filtered = this._runBeforeSend(sample);
106
+ if (null === filtered) return;
107
+ if (!filtered.name || 'string' != typeof filtered.name) return void this._logger.warn('Dropping metric with empty name');
108
+ if ('number' != typeof filtered.value || !Number.isFinite(filtered.value)) return void this._logger.warn(`Dropping metric '${filtered.name}': value must be a finite number`);
109
+ if ('count' === filtered.type && filtered.value < 0) return void this._logger.warn(`Dropping count '${filtered.name}': counters are monotonic, value must be >= 0`);
110
+ const seenType = this._typeByName.get(filtered.name);
111
+ if (void 0 === seenType) this._typeByName.set(filtered.name, filtered.type);
112
+ else if (seenType !== filtered.type && !this._typeCollisionWarned.has(filtered.name)) {
113
+ this._typeCollisionWarned.add(filtered.name);
114
+ this._logger.warn(`Metric name '${filtered.name}' is already used as a ${seenType}; recording it as a ${filtered.type} too will blend both series in charts. Use a distinct name.`);
115
+ }
116
+ const key = (0, external_metrics_utils_js_namespaceObject.seriesKey)(filtered.type, filtered.name, filtered.unit, filtered.attributes);
117
+ let state = this._series.get(key);
118
+ if (!state) {
119
+ if (this._series.size >= this._config.maxSeriesPerFlush) {
120
+ if (!this._seriesCapWarned) {
121
+ this._seriesCapWarned = true;
122
+ this._logger.warn(`Metric series cap reached (${this._config.maxSeriesPerFlush} per flush window); dropping new series until the next flush. Reduce attribute cardinality.`);
123
+ }
124
+ return;
125
+ }
126
+ state = {
127
+ name: filtered.name,
128
+ type: filtered.type,
129
+ unit: filtered.unit,
130
+ attributes: filtered.attributes ? {
131
+ ...filtered.attributes
132
+ } : void 0,
133
+ windowStartMs: Date.now()
134
+ };
135
+ this._series.set(key, state);
136
+ }
137
+ this._fold(state, filtered.value);
138
+ this._armFlushTimer();
139
+ }
140
+ _fold(state, value) {
141
+ switch(state.type){
142
+ case 'count':
143
+ state.total = (state.total ?? 0) + value;
144
+ break;
145
+ case 'gauge':
146
+ state.last = value;
147
+ break;
148
+ case 'histogram':
149
+ {
150
+ if (!state.hist) state.hist = {
151
+ count: 0,
152
+ sum: 0,
153
+ min: value,
154
+ max: value,
155
+ bucketCounts: new Array(external_metrics_utils_js_namespaceObject.DEFAULT_HISTOGRAM_BOUNDS.length + 1).fill(0)
156
+ };
157
+ const hist = state.hist;
158
+ hist.count += 1;
159
+ hist.sum += value;
160
+ hist.min = Math.min(hist.min, value);
161
+ hist.max = Math.max(hist.max, value);
162
+ hist.bucketCounts[(0, external_metrics_utils_js_namespaceObject.bucketIndexFor)(value, external_metrics_utils_js_namespaceObject.DEFAULT_HISTOGRAM_BOUNDS)] += 1;
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ _runBeforeSend(sample) {
168
+ const beforeSend = this._config.beforeSend;
169
+ if (!beforeSend) return sample;
170
+ const fns = (0, index_js_namespaceObject.isArray)(beforeSend) ? beforeSend : [
171
+ beforeSend
172
+ ];
173
+ let result = sample;
174
+ for (const fn of fns)try {
175
+ const next = fn(result);
176
+ if (!next) {
177
+ this._logger.info("Metric was rejected in beforeSend function");
178
+ return null;
179
+ }
180
+ result = next;
181
+ } catch (e) {
182
+ this._logger.error("Error in beforeSend function for metric:", e);
183
+ return null;
184
+ }
185
+ return result;
186
+ }
187
+ _armFlushTimer() {
188
+ if (this._flushTimer) return;
189
+ this._flushTimer = (0, index_js_namespaceObject.safeSetTimeout)(()=>{
190
+ this._flushTimer = void 0;
191
+ this.flush().catch(()=>{});
192
+ }, this._config.flushIntervalMs);
193
+ }
194
+ _clearFlushTimer() {
195
+ if (this._flushTimer) {
196
+ clearTimeout(this._flushTimer);
197
+ this._flushTimer = void 0;
198
+ }
199
+ }
200
+ async _doFlush() {
201
+ if (0 === this._series.size) return;
202
+ const window = this._series;
203
+ this._series = new Map();
204
+ this._seriesCapWarned = false;
205
+ this._typeByName = new Map();
206
+ this._typeCollisionWarned = new Set();
207
+ const outcome = await this._instance._sendMetricsBatch(this._buildPayload(window));
208
+ switch(outcome.kind){
209
+ case 'ok':
210
+ return;
211
+ case 'retry-later':
212
+ this._mergeWindowBack(window);
213
+ this._armFlushTimer();
214
+ return;
215
+ case 'too-large':
216
+ this._logger.warn('Metrics batch exceeded the server size limit and was dropped');
217
+ return;
218
+ case 'fatal':
219
+ this._logger.error('Failed to send metrics batch:', outcome.error);
220
+ return;
221
+ }
222
+ }
223
+ _buildPayload(window) {
224
+ return (0, external_metrics_utils_js_namespaceObject.buildOtlpMetricsPayload)(this._buildMetrics(window), (0, external_metrics_utils_js_namespaceObject.buildMetricsResourceAttributes)(this._config, this._instance.getLibraryId(), this._instance.getLibraryVersion()), this._instance.getLibraryId(), this._instance.getLibraryVersion());
225
+ }
226
+ _buildMetrics(window) {
227
+ const nowNano = (0, external_metrics_utils_js_namespaceObject.msToUnixNano)(Date.now());
228
+ const byMetric = new Map();
229
+ for (const state of window.values()){
230
+ const metricKey = (0, external_metrics_utils_js_namespaceObject.seriesKey)(state.type, state.name, state.unit, void 0);
231
+ let metric = byMetric.get(metricKey);
232
+ if (!metric) {
233
+ metric = {
234
+ name: state.name,
235
+ ...state.unit && {
236
+ unit: state.unit
237
+ }
238
+ };
239
+ if ('count' === state.type) metric.sum = {
240
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
241
+ isMonotonic: true,
242
+ dataPoints: []
243
+ };
244
+ else if ('gauge' === state.type) metric.gauge = {
245
+ dataPoints: []
246
+ };
247
+ else metric.histogram = {
248
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
249
+ dataPoints: []
250
+ };
251
+ byMetric.set(metricKey, metric);
252
+ }
253
+ const attributes = (0, logs_utils_js_namespaceObject.toOtlpKeyValueList)(state.attributes ?? {});
254
+ const startNano = (0, external_metrics_utils_js_namespaceObject.msToUnixNano)(state.windowStartMs);
255
+ if ('count' === state.type) {
256
+ const dp = {
257
+ attributes,
258
+ startTimeUnixNano: startNano,
259
+ timeUnixNano: nowNano,
260
+ asDouble: state.total ?? 0
261
+ };
262
+ metric.sum.dataPoints.push(dp);
263
+ } else if ('gauge' === state.type) {
264
+ const dp = {
265
+ attributes,
266
+ timeUnixNano: nowNano,
267
+ asDouble: state.last ?? 0
268
+ };
269
+ metric.gauge.dataPoints.push(dp);
270
+ } else if (state.hist) {
271
+ const dp = {
272
+ attributes,
273
+ startTimeUnixNano: startNano,
274
+ timeUnixNano: nowNano,
275
+ count: state.hist.count,
276
+ sum: state.hist.sum,
277
+ min: state.hist.min,
278
+ max: state.hist.max,
279
+ bucketCounts: state.hist.bucketCounts,
280
+ explicitBounds: external_metrics_utils_js_namespaceObject.DEFAULT_HISTOGRAM_BOUNDS
281
+ };
282
+ metric.histogram.dataPoints.push(dp);
283
+ }
284
+ }
285
+ return Array.from(byMetric.values());
286
+ }
287
+ _mergeWindowBack(window) {
288
+ for (const [key, old] of window){
289
+ const current = this._series.get(key);
290
+ if (!current) {
291
+ this._series.set(key, old);
292
+ continue;
293
+ }
294
+ current.windowStartMs = Math.min(current.windowStartMs, old.windowStartMs);
295
+ switch(current.type){
296
+ case 'count':
297
+ current.total = (current.total ?? 0) + (old.total ?? 0);
298
+ break;
299
+ case 'gauge':
300
+ break;
301
+ case 'histogram':
302
+ if (old.hist) if (current.hist) {
303
+ current.hist.count += old.hist.count;
304
+ current.hist.sum += old.hist.sum;
305
+ current.hist.min = Math.min(current.hist.min, old.hist.min);
306
+ current.hist.max = Math.max(current.hist.max, old.hist.max);
307
+ for(let i = 0; i < current.hist.bucketCounts.length; i++)current.hist.bucketCounts[i] += old.hist.bucketCounts[i];
308
+ } else current.hist = old.hist;
309
+ break;
310
+ }
311
+ }
312
+ }
313
+ }
314
+ exports.DEFAULT_HISTOGRAM_BOUNDS = __webpack_exports__.DEFAULT_HISTOGRAM_BOUNDS;
315
+ exports.PostHogMetrics = __webpack_exports__.PostHogMetrics;
316
+ exports.buildMetricsResourceAttributes = __webpack_exports__.buildMetricsResourceAttributes;
317
+ exports.buildOtlpMetricsPayload = __webpack_exports__.buildOtlpMetricsPayload;
318
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
319
+ "DEFAULT_HISTOGRAM_BOUNDS",
320
+ "PostHogMetrics",
321
+ "buildMetricsResourceAttributes",
322
+ "buildOtlpMetricsPayload"
323
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
324
+ Object.defineProperty(exports, '__esModule', {
325
+ value: true
326
+ });
@@ -0,0 +1,283 @@
1
+ import { isArray, safeSetTimeout } from "../utils/index.mjs";
2
+ import { toOtlpKeyValueList } from "../logs/logs-utils.mjs";
3
+ import { DEFAULT_HISTOGRAM_BOUNDS, bucketIndexFor, buildMetricsResourceAttributes, buildOtlpMetricsPayload, msToUnixNano, seriesKey } from "./metrics-utils.mjs";
4
+ const OTLP_TEMPORALITY_DELTA = 1;
5
+ class PostHogMetrics {
6
+ constructor(_instance, _config, _logger){
7
+ this._instance = _instance;
8
+ this._config = _config;
9
+ this._logger = _logger;
10
+ this._series = new Map();
11
+ this._flushPromise = null;
12
+ this._seriesCapWarned = false;
13
+ this._typeByName = new Map();
14
+ this._typeCollisionWarned = new Set();
15
+ }
16
+ count(name, value = 1, options) {
17
+ this._capture({
18
+ name,
19
+ type: 'count',
20
+ value,
21
+ unit: options?.unit,
22
+ attributes: options?.attributes
23
+ });
24
+ }
25
+ gauge(name, value, options) {
26
+ this._capture({
27
+ name,
28
+ type: 'gauge',
29
+ value,
30
+ unit: options?.unit,
31
+ attributes: options?.attributes
32
+ });
33
+ }
34
+ histogram(name, value, options) {
35
+ this._capture({
36
+ name,
37
+ type: 'histogram',
38
+ value,
39
+ unit: options?.unit,
40
+ attributes: options?.attributes
41
+ });
42
+ }
43
+ flush() {
44
+ const prev = this._flushPromise;
45
+ const run = async ()=>{
46
+ if (prev) await prev.catch(()=>{});
47
+ await this._doFlush();
48
+ };
49
+ const p = run().finally(()=>{
50
+ if (this._flushPromise === p) this._flushPromise = null;
51
+ });
52
+ this._flushPromise = p;
53
+ return p;
54
+ }
55
+ drainWindow() {
56
+ if (0 === this._series.size) return null;
57
+ const window = this._series;
58
+ this._series = new Map();
59
+ this._seriesCapWarned = false;
60
+ this._typeByName = new Map();
61
+ this._typeCollisionWarned = new Set();
62
+ return this._buildPayload(window);
63
+ }
64
+ reset() {
65
+ this._clearFlushTimer();
66
+ this._series = new Map();
67
+ this._flushPromise = null;
68
+ this._seriesCapWarned = false;
69
+ this._typeByName = new Map();
70
+ this._typeCollisionWarned = new Set();
71
+ }
72
+ _capture(sample) {
73
+ if (this._instance.isDisabled || this._instance.optedOut) return;
74
+ const filtered = this._runBeforeSend(sample);
75
+ if (null === filtered) return;
76
+ if (!filtered.name || 'string' != typeof filtered.name) return void this._logger.warn('Dropping metric with empty name');
77
+ if ('number' != typeof filtered.value || !Number.isFinite(filtered.value)) return void this._logger.warn(`Dropping metric '${filtered.name}': value must be a finite number`);
78
+ if ('count' === filtered.type && filtered.value < 0) return void this._logger.warn(`Dropping count '${filtered.name}': counters are monotonic, value must be >= 0`);
79
+ const seenType = this._typeByName.get(filtered.name);
80
+ if (void 0 === seenType) this._typeByName.set(filtered.name, filtered.type);
81
+ else if (seenType !== filtered.type && !this._typeCollisionWarned.has(filtered.name)) {
82
+ this._typeCollisionWarned.add(filtered.name);
83
+ this._logger.warn(`Metric name '${filtered.name}' is already used as a ${seenType}; recording it as a ${filtered.type} too will blend both series in charts. Use a distinct name.`);
84
+ }
85
+ const key = seriesKey(filtered.type, filtered.name, filtered.unit, filtered.attributes);
86
+ let state = this._series.get(key);
87
+ if (!state) {
88
+ if (this._series.size >= this._config.maxSeriesPerFlush) {
89
+ if (!this._seriesCapWarned) {
90
+ this._seriesCapWarned = true;
91
+ this._logger.warn(`Metric series cap reached (${this._config.maxSeriesPerFlush} per flush window); dropping new series until the next flush. Reduce attribute cardinality.`);
92
+ }
93
+ return;
94
+ }
95
+ state = {
96
+ name: filtered.name,
97
+ type: filtered.type,
98
+ unit: filtered.unit,
99
+ attributes: filtered.attributes ? {
100
+ ...filtered.attributes
101
+ } : void 0,
102
+ windowStartMs: Date.now()
103
+ };
104
+ this._series.set(key, state);
105
+ }
106
+ this._fold(state, filtered.value);
107
+ this._armFlushTimer();
108
+ }
109
+ _fold(state, value) {
110
+ switch(state.type){
111
+ case 'count':
112
+ state.total = (state.total ?? 0) + value;
113
+ break;
114
+ case 'gauge':
115
+ state.last = value;
116
+ break;
117
+ case 'histogram':
118
+ {
119
+ if (!state.hist) state.hist = {
120
+ count: 0,
121
+ sum: 0,
122
+ min: value,
123
+ max: value,
124
+ bucketCounts: new Array(DEFAULT_HISTOGRAM_BOUNDS.length + 1).fill(0)
125
+ };
126
+ const hist = state.hist;
127
+ hist.count += 1;
128
+ hist.sum += value;
129
+ hist.min = Math.min(hist.min, value);
130
+ hist.max = Math.max(hist.max, value);
131
+ hist.bucketCounts[bucketIndexFor(value, DEFAULT_HISTOGRAM_BOUNDS)] += 1;
132
+ break;
133
+ }
134
+ }
135
+ }
136
+ _runBeforeSend(sample) {
137
+ const beforeSend = this._config.beforeSend;
138
+ if (!beforeSend) return sample;
139
+ const fns = isArray(beforeSend) ? beforeSend : [
140
+ beforeSend
141
+ ];
142
+ let result = sample;
143
+ for (const fn of fns)try {
144
+ const next = fn(result);
145
+ if (!next) {
146
+ this._logger.info("Metric was rejected in beforeSend function");
147
+ return null;
148
+ }
149
+ result = next;
150
+ } catch (e) {
151
+ this._logger.error("Error in beforeSend function for metric:", e);
152
+ return null;
153
+ }
154
+ return result;
155
+ }
156
+ _armFlushTimer() {
157
+ if (this._flushTimer) return;
158
+ this._flushTimer = safeSetTimeout(()=>{
159
+ this._flushTimer = void 0;
160
+ this.flush().catch(()=>{});
161
+ }, this._config.flushIntervalMs);
162
+ }
163
+ _clearFlushTimer() {
164
+ if (this._flushTimer) {
165
+ clearTimeout(this._flushTimer);
166
+ this._flushTimer = void 0;
167
+ }
168
+ }
169
+ async _doFlush() {
170
+ if (0 === this._series.size) return;
171
+ const window = this._series;
172
+ this._series = new Map();
173
+ this._seriesCapWarned = false;
174
+ this._typeByName = new Map();
175
+ this._typeCollisionWarned = new Set();
176
+ const outcome = await this._instance._sendMetricsBatch(this._buildPayload(window));
177
+ switch(outcome.kind){
178
+ case 'ok':
179
+ return;
180
+ case 'retry-later':
181
+ this._mergeWindowBack(window);
182
+ this._armFlushTimer();
183
+ return;
184
+ case 'too-large':
185
+ this._logger.warn('Metrics batch exceeded the server size limit and was dropped');
186
+ return;
187
+ case 'fatal':
188
+ this._logger.error('Failed to send metrics batch:', outcome.error);
189
+ return;
190
+ }
191
+ }
192
+ _buildPayload(window) {
193
+ return buildOtlpMetricsPayload(this._buildMetrics(window), buildMetricsResourceAttributes(this._config, this._instance.getLibraryId(), this._instance.getLibraryVersion()), this._instance.getLibraryId(), this._instance.getLibraryVersion());
194
+ }
195
+ _buildMetrics(window) {
196
+ const nowNano = msToUnixNano(Date.now());
197
+ const byMetric = new Map();
198
+ for (const state of window.values()){
199
+ const metricKey = seriesKey(state.type, state.name, state.unit, void 0);
200
+ let metric = byMetric.get(metricKey);
201
+ if (!metric) {
202
+ metric = {
203
+ name: state.name,
204
+ ...state.unit && {
205
+ unit: state.unit
206
+ }
207
+ };
208
+ if ('count' === state.type) metric.sum = {
209
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
210
+ isMonotonic: true,
211
+ dataPoints: []
212
+ };
213
+ else if ('gauge' === state.type) metric.gauge = {
214
+ dataPoints: []
215
+ };
216
+ else metric.histogram = {
217
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
218
+ dataPoints: []
219
+ };
220
+ byMetric.set(metricKey, metric);
221
+ }
222
+ const attributes = toOtlpKeyValueList(state.attributes ?? {});
223
+ const startNano = msToUnixNano(state.windowStartMs);
224
+ if ('count' === state.type) {
225
+ const dp = {
226
+ attributes,
227
+ startTimeUnixNano: startNano,
228
+ timeUnixNano: nowNano,
229
+ asDouble: state.total ?? 0
230
+ };
231
+ metric.sum.dataPoints.push(dp);
232
+ } else if ('gauge' === state.type) {
233
+ const dp = {
234
+ attributes,
235
+ timeUnixNano: nowNano,
236
+ asDouble: state.last ?? 0
237
+ };
238
+ metric.gauge.dataPoints.push(dp);
239
+ } else if (state.hist) {
240
+ const dp = {
241
+ attributes,
242
+ startTimeUnixNano: startNano,
243
+ timeUnixNano: nowNano,
244
+ count: state.hist.count,
245
+ sum: state.hist.sum,
246
+ min: state.hist.min,
247
+ max: state.hist.max,
248
+ bucketCounts: state.hist.bucketCounts,
249
+ explicitBounds: DEFAULT_HISTOGRAM_BOUNDS
250
+ };
251
+ metric.histogram.dataPoints.push(dp);
252
+ }
253
+ }
254
+ return Array.from(byMetric.values());
255
+ }
256
+ _mergeWindowBack(window) {
257
+ for (const [key, old] of window){
258
+ const current = this._series.get(key);
259
+ if (!current) {
260
+ this._series.set(key, old);
261
+ continue;
262
+ }
263
+ current.windowStartMs = Math.min(current.windowStartMs, old.windowStartMs);
264
+ switch(current.type){
265
+ case 'count':
266
+ current.total = (current.total ?? 0) + (old.total ?? 0);
267
+ break;
268
+ case 'gauge':
269
+ break;
270
+ case 'histogram':
271
+ if (old.hist) if (current.hist) {
272
+ current.hist.count += old.hist.count;
273
+ current.hist.sum += old.hist.sum;
274
+ current.hist.min = Math.min(current.hist.min, old.hist.min);
275
+ current.hist.max = Math.max(current.hist.max, old.hist.max);
276
+ for(let i = 0; i < current.hist.bucketCounts.length; i++)current.hist.bucketCounts[i] += old.hist.bucketCounts[i];
277
+ } else current.hist = old.hist;
278
+ break;
279
+ }
280
+ }
281
+ }
282
+ }
283
+ export { DEFAULT_HISTOGRAM_BOUNDS, PostHogMetrics, buildMetricsResourceAttributes, buildOtlpMetricsPayload };
@@ -0,0 +1,41 @@
1
+ import type { MetricAttributeValue, OtlpMetric, OtlpMetricsPayload } from '@posthog/types';
2
+ import type { ResolvedPostHogMetricsConfig } from './types';
3
+ /**
4
+ * Default histogram bucket boundaries — the OpenTelemetry SDK defaults.
5
+ * Chosen so the server-side p95/quantile aggregations have usable resolution
6
+ * for the common latency/size ranges without any per-metric configuration.
7
+ */
8
+ export declare const DEFAULT_HISTOGRAM_BOUNDS: number[];
9
+ /**
10
+ * Converts epoch millis to the unix-nanos string OTLP requires (uint64
11
+ * doesn't fit in JS Number, so concatenate instead of multiplying).
12
+ */
13
+ export declare function msToUnixNano(ms: number): string;
14
+ /**
15
+ * Canonical identity of a series within the aggregation window: type, name,
16
+ * unit, and the attribute set with keys sorted so insertion order can't split
17
+ * a series. NUL (`\u0000`) separators can't appear in metric names or JSON output.
18
+ */
19
+ export declare function seriesKey(type: string, name: string, unit: string | undefined, attributes: Record<string, MetricAttributeValue> | undefined): string;
20
+ /**
21
+ * Returns the bucket index for a histogram observation: the first boundary
22
+ * the value is `<=`, or the overflow bucket (`bounds.length`) past the last.
23
+ */
24
+ export declare function bucketIndexFor(value: number, bounds: number[]): number;
25
+ /**
26
+ * OTLP resource attributes for every metrics batch. Same layering policy as
27
+ * the logs builder: user `resourceAttributes` spread first, SDK-controlled
28
+ * keys layered on top so a stray user key can't clobber attribution.
29
+ */
30
+ export declare function buildMetricsResourceAttributes(config: ResolvedPostHogMetricsConfig, scopeName: string, scopeVersion: string): Record<string, MetricAttributeValue>;
31
+ /**
32
+ * Wraps aggregated metrics in the OTLP `resourceMetrics` envelope
33
+ * (`ExportMetricsServiceRequest`, JSON encoding).
34
+ *
35
+ * Encoding notes pinned by the ingest's JSON deserializer: nano timestamps
36
+ * are decimal strings, but histogram `count`/`bucketCounts` are plain JSON
37
+ * numbers — string-encoded u64s in those fields have been silently dropped
38
+ * by upstream opentelemetry-proto deserializers (opentelemetry-rust#3328).
39
+ */
40
+ export declare function buildOtlpMetricsPayload(metrics: OtlpMetric[], resourceAttributes: Record<string, MetricAttributeValue>, scopeName: string, scopeVersion: string): OtlpMetricsPayload;
41
+ //# sourceMappingURL=metrics-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-utils.d.ts","sourceRoot":"","sources":["../../src/metrics/metrics-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAE1F,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAA;AAE3D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,UAA4E,CAAA;AAEjH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,GAC3D,MAAM,CAOR;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAOtE;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,4BAA4B,EACpC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAStC;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,UAAU,EAAE,EACrB,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,EACxD,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,kBAAkB,CAcpB"}