@objectstack/observability 17.0.0 → 17.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.
- package/CHANGELOG.md +215 -0
- package/dist/index.cjs +92 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -9
- package/dist/index.d.ts +147 -9
- package/dist/index.js +90 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,220 @@
|
|
|
1
1
|
# @objectstack/observability
|
|
2
2
|
|
|
3
|
+
## 17.1.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 899052a: docs(observability): record what a zero on `cache_*` MEANS — "no configured consumer", not "no cache activity" (#9954)
|
|
8
|
+
|
|
9
|
+
`SEMCONV` declares the `cache_*` families as a stable namespace explicitly so
|
|
10
|
+
hosts can wire alerts and dashboards against it. An operator who does that gets
|
|
11
|
+
a flat zero on `cache_lookups_total` in a default install — and nothing in the
|
|
12
|
+
declaration or the operator docs said why, so the only available readings were
|
|
13
|
+
"0% hit rate" or "the adapter is broken". Both are wrong.
|
|
14
|
+
|
|
15
|
+
**Nothing about emission changes.** The path is proven working: #9832 wired the
|
|
16
|
+
cache adapter to the host's registry and #9951 pins a real lookup observing
|
|
17
|
+
`cache_lookups_total{adapter=memory,result=miss}`. The zero is *true*; what it
|
|
18
|
+
failed to communicate is its cause.
|
|
19
|
+
|
|
20
|
+
The cause, re-measured on `origin/main` rather than taken from the card: no
|
|
21
|
+
consumer of the `cache` service is unconditional. Every production consumer is
|
|
22
|
+
a rate-limit or budget counter store, and each is gated on a declaration
|
|
23
|
+
somebody has to write:
|
|
24
|
+
|
|
25
|
+
- `packages/plugins/plugin-auth/src/auth-plugin.ts` — better-auth's per-IP
|
|
26
|
+
counters, reached only when `rate_limit_max` or `rate_limit_window_seconds`
|
|
27
|
+
is explicitly supplied in auth settings.
|
|
28
|
+
- `packages/runtime/src/dispatcher-plugin.ts` — the inbound rate limiter and
|
|
29
|
+
the declarative per-endpoint buckets. Both register *nothing at all* when no
|
|
30
|
+
budget is declared (`createInboundRateLimitMiddleware` returns `null`;
|
|
31
|
+
`limiterFor` returns `null` on an endpoint with no armed `rateLimit`), so an
|
|
32
|
+
unmetered deployment never reaches the cache.
|
|
33
|
+
- the per-number OTP send budget, reached only on an SMS send path.
|
|
34
|
+
|
|
35
|
+
Declare none of them — the default slate — and the family sits at 0 while the
|
|
36
|
+
server handles traffic normally.
|
|
37
|
+
|
|
38
|
+
So the annotation states the invariant rather than a roster: *every* consumer
|
|
39
|
+
is an explicitly-declared rate-limit/budget counter store. That sentence stays
|
|
40
|
+
true when another conditional consumer is added, and goes false exactly when an
|
|
41
|
+
unconditional one appears — which is when it should be revisited.
|
|
42
|
+
|
|
43
|
+
This is the mirror image of the HTTP note that landed alongside it: there a
|
|
44
|
+
zero means "not instrumented"; here a zero is a true count of a service nothing
|
|
45
|
+
asked anything of. The two are deliberately worded so they cannot be read as
|
|
46
|
+
the same statement.
|
|
47
|
+
|
|
48
|
+
The note is attached as per-family JSDoc rather than a `//` group header, and
|
|
49
|
+
that placement is load-bearing: `tsup`'s dts generation drops line comments, so
|
|
50
|
+
only the JSDoc form reaches `dist/index.d.ts` — i.e. the operator's IDE hover,
|
|
51
|
+
which is where somebody wiring a `cache_lookups_total` panel actually meets the
|
|
52
|
+
declaration. Verified in the built artifact, not assumed.
|
|
53
|
+
- 1e050a5: fix(observability): emit `http_request_duration_ms` from the transport seam, so
|
|
54
|
+
p95 latency sees every inbound surface instead of dispatcher routes only
|
|
55
|
+
(#9834)
|
|
56
|
+
|
|
57
|
+
#9835 moved `http_requests_total` to the `IHttpServer.afterResponse` seam and
|
|
58
|
+
stopped there, which left the two derived signals the operator guidance names
|
|
59
|
+
inconsistent with each other: 5xx rate covered auth's `getRawApp()` mount and
|
|
60
|
+
the REST data API, while p95 latency still saw only the routes the dispatcher's
|
|
61
|
+
own `Proxy` wrapped. A missing latency panel is at least loud; the worse
|
|
62
|
+
reading is the p95 that IS drawn, computed from dispatcher routes only and
|
|
63
|
+
presented as the server's.
|
|
64
|
+
|
|
65
|
+
- `@objectstack/observability`: new `armHttpRequestDurationHistogram(server,
|
|
66
|
+
metrics)`, the duration family's counterpart to `armHttpRequestCounter` —
|
|
67
|
+
same `afterResponse` seam, its own `Symbol.for` first-wins latch, so a host
|
|
68
|
+
that armed one family can still arm the other. `ArmHttpMetricResult` is the
|
|
69
|
+
family-neutral spelling of the result union; `ArmHttpRequestCounterResult`
|
|
70
|
+
stays as an alias.
|
|
71
|
+
- `@objectstack/plugin-hono-server`: `installHttpMetricsSeam` arms both
|
|
72
|
+
families, so the transport owns every transport-observable HTTP metric in the
|
|
73
|
+
shipped composition rather than splitting ownership across layers.
|
|
74
|
+
- `@objectstack/runtime`: the dispatcher offers its registry to the histogram
|
|
75
|
+
seam as well, and `instrumentRouteHandler` gains
|
|
76
|
+
`emitHttpRequestDurationMs` (default `true`) — passed `false` exactly when
|
|
77
|
+
the transport implements the seam, which is what keeps the dispatcher's own
|
|
78
|
+
routes at ONE observation instead of reintroducing the #9833 double count one
|
|
79
|
+
family over.
|
|
80
|
+
|
|
81
|
+
**⚠️ The observation window changes with the emitter.** The per-route wrapper
|
|
82
|
+
timed `await handler(req, res)` — handler latency. The transport times from
|
|
83
|
+
first seeing the request to the response existing, so the middleware chain and
|
|
84
|
+
body parse are now included and samples can only move UP. This is the number a
|
|
85
|
+
latency panel should show (the request's latency, not one layer's share of it),
|
|
86
|
+
but it is a visible shift in an existing series: compare p95 across the upgrade
|
|
87
|
+
boundary deliberately. Documented in `docs/OBSERVABILITY.md` and the
|
|
88
|
+
production-readiness guide.
|
|
89
|
+
|
|
90
|
+
`http_request_errors_total` is deliberately NOT moved. The observation carries
|
|
91
|
+
no throw signal — only `{method, routePattern, status, elapsedMs}` — so a
|
|
92
|
+
transport-side emitter would have to key off a status class, which counts a
|
|
93
|
+
different population than "the handler threw". That is a semantics decision,
|
|
94
|
+
recorded on #9834 rather than guessed at here; the counter stays ungated on
|
|
95
|
+
every transport and keeps its documented meaning.
|
|
96
|
+
- 7ff3975: feat(spec): `IHttpServer` gains an optional `afterResponse` response-observing
|
|
97
|
+
hook so HTTP metrics are transport-agnostic instead of Hono-only (#9835)
|
|
98
|
+
|
|
99
|
+
The contract addition (additive — a new optional member plus the
|
|
100
|
+
`HttpResponseObservation` / `HttpResponseObserver` types and the reserved
|
|
101
|
+
`UNMATCHED_ROUTE_PATTERN` label): a transport invokes each registered observer
|
|
102
|
+
exactly once per answered request with `{ method, routePattern, status,
|
|
103
|
+
elapsedMs }`, after the response exists — the observation point the `use()`
|
|
104
|
+
middleware contract cannot express (it runs before dispatch and never sees a
|
|
105
|
+
status). `routePattern` is REQUIRED to be the registered route pattern
|
|
106
|
+
(`/api/v1/data/:id`), never the concrete path, so no adapter re-decides metric
|
|
107
|
+
cardinality. Optionality is feature-detected runtime-real
|
|
108
|
+
(`typeof server.afterResponse === 'function'`); a transport that does not
|
|
109
|
+
implement the seam reports **no** HTTP metrics — zero there means "not
|
|
110
|
+
instrumented", never "no traffic".
|
|
111
|
+
|
|
112
|
+
Implementations and consumers in the same change:
|
|
113
|
+
|
|
114
|
+
- `@objectstack/plugin-hono-server`: `HonoHttpServer` implements the seam (the
|
|
115
|
+
ruled #9650 raw-app middleware becomes its delivery path — same reach,
|
|
116
|
+
including `getRawApp()` mounts and middleware-refused 429s); unrouted
|
|
117
|
+
requests are now labelled with the reserved `unmatched` pattern (previously
|
|
118
|
+
they could surface as `/*`).
|
|
119
|
+
- `@objectstack/observability`: new `armHttpRequestCounter(server, metrics)`
|
|
120
|
+
arms the `http_requests_total` counter through the seam at most once per
|
|
121
|
+
server (first caller wins), which is what makes "exactly one counter per
|
|
122
|
+
server" structural.
|
|
123
|
+
- `@objectstack/runtime`: the dispatcher offers its `observability.metrics`
|
|
124
|
+
registry to the seam (a host that wires only the dispatcher now counts every
|
|
125
|
+
inbound surface) and suppresses its own per-route copy of
|
|
126
|
+
`http_requests_total` when the transport implements the seam — retiring the
|
|
127
|
+
#9833 double count. Request-id echo, the duration histogram, the error
|
|
128
|
+
counter and the error reporter are unchanged.
|
|
129
|
+
- `@objectstack/http-conformance`: `NodeHttpServer` implements the seam, and a
|
|
130
|
+
new cross-adapter conformance suite locks the semantics for both adapters.
|
|
131
|
+
- `@objectstack/core`: re-exports the new contract types/constant.
|
|
132
|
+
- Updated dependencies [56656aa]
|
|
133
|
+
- Updated dependencies [07e630e]
|
|
134
|
+
- Updated dependencies [2f65b1b]
|
|
135
|
+
- Updated dependencies [720ee95]
|
|
136
|
+
- Updated dependencies [f287435]
|
|
137
|
+
- Updated dependencies [9aa8890]
|
|
138
|
+
- Updated dependencies [7c9c1dd]
|
|
139
|
+
- Updated dependencies [75b7c24]
|
|
140
|
+
- Updated dependencies [d5552ca]
|
|
141
|
+
- Updated dependencies [d9813a9]
|
|
142
|
+
- Updated dependencies [8640fb2]
|
|
143
|
+
- Updated dependencies [2420641]
|
|
144
|
+
- Updated dependencies [2ad91c3]
|
|
145
|
+
- Updated dependencies [f57fb38]
|
|
146
|
+
- Updated dependencies [00777a0]
|
|
147
|
+
- Updated dependencies [d491625]
|
|
148
|
+
- Updated dependencies [420804d]
|
|
149
|
+
- Updated dependencies [716ac9b]
|
|
150
|
+
- Updated dependencies [62b1427]
|
|
151
|
+
- Updated dependencies [7ea1372]
|
|
152
|
+
- Updated dependencies [23abe27]
|
|
153
|
+
- Updated dependencies [985a9cd]
|
|
154
|
+
- Updated dependencies [a8189ae]
|
|
155
|
+
- Updated dependencies [26e70fb]
|
|
156
|
+
- Updated dependencies [42b05af]
|
|
157
|
+
- Updated dependencies [2b292ce]
|
|
158
|
+
- Updated dependencies [abcf853]
|
|
159
|
+
- Updated dependencies [8b9eba5]
|
|
160
|
+
- Updated dependencies [d575779]
|
|
161
|
+
- Updated dependencies [94f7ef8]
|
|
162
|
+
- Updated dependencies [c5ac5e4]
|
|
163
|
+
- Updated dependencies [a777944]
|
|
164
|
+
- Updated dependencies [dd88e1c]
|
|
165
|
+
- Updated dependencies [856527c]
|
|
166
|
+
- Updated dependencies [870f710]
|
|
167
|
+
- Updated dependencies [79c46da]
|
|
168
|
+
- Updated dependencies [7ff3975]
|
|
169
|
+
- Updated dependencies [29d055b]
|
|
170
|
+
- Updated dependencies [65589d6]
|
|
171
|
+
- Updated dependencies [2c86fe3]
|
|
172
|
+
- Updated dependencies [e196c6a]
|
|
173
|
+
- Updated dependencies [4ab7523]
|
|
174
|
+
- Updated dependencies [19539b4]
|
|
175
|
+
- Updated dependencies [11b779e]
|
|
176
|
+
- Updated dependencies [739fe5b]
|
|
177
|
+
- Updated dependencies [4bfe1a5]
|
|
178
|
+
- Updated dependencies [2065e31]
|
|
179
|
+
- Updated dependencies [b69d0f5]
|
|
180
|
+
- Updated dependencies [4d47afe]
|
|
181
|
+
- Updated dependencies [e4e5c6e]
|
|
182
|
+
- Updated dependencies [9a56784]
|
|
183
|
+
- Updated dependencies [d00d2f6]
|
|
184
|
+
- Updated dependencies [df0c12d]
|
|
185
|
+
- Updated dependencies [d31785f]
|
|
186
|
+
- Updated dependencies [c308a4f]
|
|
187
|
+
- Updated dependencies [e2899f6]
|
|
188
|
+
- Updated dependencies [3851f87]
|
|
189
|
+
- Updated dependencies [2a29caa]
|
|
190
|
+
- Updated dependencies [09a6eee]
|
|
191
|
+
- Updated dependencies [1a7f907]
|
|
192
|
+
- Updated dependencies [cd455c8]
|
|
193
|
+
- Updated dependencies [30d3752]
|
|
194
|
+
- Updated dependencies [c80e7ae]
|
|
195
|
+
- Updated dependencies [09a9a8a]
|
|
196
|
+
- Updated dependencies [07026cf]
|
|
197
|
+
- Updated dependencies [5d4f3d5]
|
|
198
|
+
- Updated dependencies [4d80e8b]
|
|
199
|
+
- Updated dependencies [30b1c63]
|
|
200
|
+
- Updated dependencies [079b457]
|
|
201
|
+
- Updated dependencies [e43b211]
|
|
202
|
+
- Updated dependencies [890b38f]
|
|
203
|
+
- Updated dependencies [8bee54b]
|
|
204
|
+
- Updated dependencies [7a537ce]
|
|
205
|
+
- Updated dependencies [593c4bf]
|
|
206
|
+
- Updated dependencies [ff08691]
|
|
207
|
+
- Updated dependencies [60e0f90]
|
|
208
|
+
- Updated dependencies [90c5285]
|
|
209
|
+
- Updated dependencies [7901b2d]
|
|
210
|
+
- Updated dependencies [56bca91]
|
|
211
|
+
- Updated dependencies [79394d7]
|
|
212
|
+
- Updated dependencies [730fd9a]
|
|
213
|
+
- Updated dependencies [44bc51d]
|
|
214
|
+
- Updated dependencies [73cfddf]
|
|
215
|
+
- Updated dependencies [d634e66]
|
|
216
|
+
- @objectstack/spec@17.1.0
|
|
217
|
+
|
|
3
218
|
## 17.0.0
|
|
4
219
|
|
|
5
220
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,8 @@ __export(index_exports, {
|
|
|
37
37
|
RUNTIME_METRICS: () => RUNTIME_METRICS,
|
|
38
38
|
SEMCONV: () => SEMCONV,
|
|
39
39
|
allowPerfDisclosure: () => allowPerfDisclosure,
|
|
40
|
+
armHttpRequestCounter: () => armHttpRequestCounter,
|
|
41
|
+
armHttpRequestDurationHistogram: () => armHttpRequestDurationHistogram,
|
|
40
42
|
countServerTiming: () => countServerTiming,
|
|
41
43
|
currentPerfTiming: () => currentPerfTiming,
|
|
42
44
|
formatServerTiming: () => formatServerTiming,
|
|
@@ -59,14 +61,28 @@ var OBSERVABILITY_ERRORS_SERVICE = "observability:errors";
|
|
|
59
61
|
|
|
60
62
|
// src/semconv.ts
|
|
61
63
|
var SEMCONV = {
|
|
62
|
-
// ── HTTP —
|
|
63
|
-
/**
|
|
64
|
+
// ── HTTP — emitter differs per family, see each ────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* Counter, labels: `method`, `route`, `status`. Emitted by the TRANSPORT
|
|
67
|
+
* through the `IHttpServer.afterResponse` seam (#9835), so it covers
|
|
68
|
+
* every inbound request on the server rather than only the routes the
|
|
69
|
+
* runtime dispatcher registers.
|
|
70
|
+
*/
|
|
64
71
|
httpRequestsTotal: "http_requests_total",
|
|
65
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Histogram (ms), labels: `method`, `route`. Emitted by the TRANSPORT
|
|
74
|
+
* through the same seam (#9834). It measures the REQUEST as the transport
|
|
75
|
+
* sees it — first sight to the response existing, middleware chain and
|
|
76
|
+
* body parse included — not the handler's share of it.
|
|
77
|
+
*/
|
|
66
78
|
httpRequestDurationMs: "http_request_duration_ms",
|
|
67
79
|
/**
|
|
68
|
-
* Counter, labels: `method`, `route`. Incremented when an
|
|
69
|
-
*
|
|
80
|
+
* Counter, labels: `method`, `route`. Incremented when an in-flight
|
|
81
|
+
* handler throws after the response is sent. Emitted by
|
|
82
|
+
* `@objectstack/runtime`'s `instrumentRouteHandler`, and NOT movable to
|
|
83
|
+
* the seam above as-is: the observation carries a status but no throw
|
|
84
|
+
* signal, so a transport-side emitter would count a different population
|
|
85
|
+
* (#9834 records the fork).
|
|
70
86
|
*/
|
|
71
87
|
httpRequestErrorsTotal: "http_request_errors_total",
|
|
72
88
|
// ── Storage — emitted by `@objectstack/service-storage` adapters ──
|
|
@@ -77,11 +93,41 @@ var SEMCONV = {
|
|
|
77
93
|
/** Counter, labels: `adapter`, `op`, `errorClass`. */
|
|
78
94
|
storageErrorsTotal: "storage_errors_total",
|
|
79
95
|
// ── Cache — emitted by `@objectstack/service-cache` adapters ──
|
|
80
|
-
|
|
96
|
+
// Uniform emitter; what varies is who CONSULTS the service — see below.
|
|
97
|
+
/**
|
|
98
|
+
* Counter, labels: `adapter` (`memory`|`redis`), `result` (`hit`|`miss`).
|
|
99
|
+
*
|
|
100
|
+
* ⚠️ A flat zero means "NO CONFIGURED CONSUMER", not "no cache activity",
|
|
101
|
+
* and — unlike the HTTP families above — it is NOT an instrumentation gap.
|
|
102
|
+
* The adapters hold the host's registry and count every call they receive
|
|
103
|
+
* (#9832 wired that; #9951 pins it), so a zero here is TRUE. What it fails
|
|
104
|
+
* to communicate is WHY.
|
|
105
|
+
*
|
|
106
|
+
* The why: nothing consults the `cache` service unconditionally. Every
|
|
107
|
+
* production consumer is a rate-limit / budget counter store, and each is
|
|
108
|
+
* gated on a declaration somebody has to write — better-auth's per-IP
|
|
109
|
+
* counters (`rate_limit_max` / `rate_limit_window_seconds` in auth
|
|
110
|
+
* settings), the dispatcher's inbound limiter and its declarative
|
|
111
|
+
* per-endpoint buckets (an armed `rateLimit` budget; with none declared
|
|
112
|
+
* the dispatcher registers no limiter at all), and the per-number OTP send
|
|
113
|
+
* budget (an SMS send path). A default install declares none of them, so
|
|
114
|
+
* this counter stays at 0 while the server handles traffic normally.
|
|
115
|
+
*
|
|
116
|
+
* ⇒ Read a flat `cache_*` as a question about CONFIGURATION, never as a 0%
|
|
117
|
+
* hit rate or a broken adapter. Before trusting a cache hit-rate panel,
|
|
118
|
+
* confirm at least one consumer above is actually armed.
|
|
119
|
+
*/
|
|
81
120
|
cacheLookupsTotal: "cache_lookups_total",
|
|
82
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* Counter, labels: `adapter`, `op` (`set`|`delete`|`clear`). Same
|
|
123
|
+
* "zero = no configured consumer" reading as `cacheLookupsTotal` above.
|
|
124
|
+
*/
|
|
83
125
|
cacheWritesTotal: "cache_writes_total",
|
|
84
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* Counter, labels: `adapter`, `op`, `errorClass`. Same "zero = no
|
|
128
|
+
* configured consumer" reading as `cacheLookupsTotal` above — a zero is
|
|
129
|
+
* "nothing was asked of the cache", not "every call succeeded".
|
|
130
|
+
*/
|
|
85
131
|
cacheErrorsTotal: "cache_errors_total",
|
|
86
132
|
// ── Background jobs — emitted by `@objectstack/runtime`'s AppPlugin ──
|
|
87
133
|
/**
|
|
@@ -105,6 +151,42 @@ var RUNTIME_METRICS = {
|
|
|
105
151
|
httpRequestErrorsTotal: SEMCONV.httpRequestErrorsTotal
|
|
106
152
|
};
|
|
107
153
|
|
|
154
|
+
// src/http-transport-metrics.ts
|
|
155
|
+
var HTTP_REQUEST_COUNTER_ARMED = /* @__PURE__ */ Symbol.for(
|
|
156
|
+
"objectstack.observability.httpRequestCounterArmed"
|
|
157
|
+
);
|
|
158
|
+
function armHttpRequestCounter(server, metrics) {
|
|
159
|
+
if (typeof server.afterResponse !== "function") return "unsupported";
|
|
160
|
+
const latched = server;
|
|
161
|
+
if (latched[HTTP_REQUEST_COUNTER_ARMED]) return "already-armed";
|
|
162
|
+
latched[HTTP_REQUEST_COUNTER_ARMED] = true;
|
|
163
|
+
server.afterResponse((observation) => {
|
|
164
|
+
metrics.counter(RUNTIME_METRICS.httpRequestsTotal, {
|
|
165
|
+
method: observation.method,
|
|
166
|
+
route: observation.routePattern,
|
|
167
|
+
status: String(observation.status)
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
return "armed";
|
|
171
|
+
}
|
|
172
|
+
var HTTP_REQUEST_DURATION_ARMED = /* @__PURE__ */ Symbol.for(
|
|
173
|
+
"objectstack.observability.httpRequestDurationArmed"
|
|
174
|
+
);
|
|
175
|
+
function armHttpRequestDurationHistogram(server, metrics) {
|
|
176
|
+
if (typeof server.afterResponse !== "function") return "unsupported";
|
|
177
|
+
const latched = server;
|
|
178
|
+
if (latched[HTTP_REQUEST_DURATION_ARMED]) return "already-armed";
|
|
179
|
+
latched[HTTP_REQUEST_DURATION_ARMED] = true;
|
|
180
|
+
server.afterResponse((observation) => {
|
|
181
|
+
metrics.histogram(
|
|
182
|
+
RUNTIME_METRICS.httpRequestDurationMs,
|
|
183
|
+
observation.elapsedMs,
|
|
184
|
+
{ method: observation.method, route: observation.routePattern }
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
return "armed";
|
|
188
|
+
}
|
|
189
|
+
|
|
108
190
|
// src/metrics-exporters.ts
|
|
109
191
|
var NoopMetricsRegistry = class {
|
|
110
192
|
counter() {
|
|
@@ -704,6 +786,8 @@ function isPerfDisclosurePrincipal(ec) {
|
|
|
704
786
|
RUNTIME_METRICS,
|
|
705
787
|
SEMCONV,
|
|
706
788
|
allowPerfDisclosure,
|
|
789
|
+
armHttpRequestCounter,
|
|
790
|
+
armHttpRequestDurationHistogram,
|
|
707
791
|
countServerTiming,
|
|
708
792
|
currentPerfTiming,
|
|
709
793
|
formatServerTiming,
|