@adonis-agora/telescope 0.11.0 → 0.13.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 +108 -0
- package/dist/providers/telescope_provider.d.ts.map +1 -1
- package/dist/providers/telescope_provider.js +1 -1
- package/dist/providers/telescope_provider.js.map +1 -1
- package/dist/src/ai/index.d.ts +1 -1
- package/dist/src/ai/index.js +1 -1
- package/dist/src/alerts/exception_source.d.ts.map +1 -1
- package/dist/src/alerts/exception_source.js +2 -4
- package/dist/src/alerts/exception_source.js.map +1 -1
- package/dist/src/alerts/index.d.ts +1 -1
- package/dist/src/alerts/index.js +1 -1
- package/dist/src/client_errors/ingestor.d.ts +20 -0
- package/dist/src/client_errors/ingestor.d.ts.map +1 -1
- package/dist/src/client_errors/ingestor.js +29 -2
- package/dist/src/client_errors/ingestor.js.map +1 -1
- package/dist/src/context_accessor.d.ts +13 -0
- package/dist/src/context_accessor.d.ts.map +1 -1
- package/dist/src/context_accessor.js +20 -0
- package/dist/src/context_accessor.js.map +1 -1
- package/dist/src/define_config.d.ts +10 -1
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +1 -0
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/entry.d.ts +13 -0
- package/dist/src/entry.d.ts.map +1 -1
- package/dist/src/entry.js +15 -0
- package/dist/src/entry.js.map +1 -1
- package/dist/src/index.d.ts +6 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/metrics/metrics_service.d.ts +13 -0
- package/dist/src/metrics/metrics_service.d.ts.map +1 -1
- package/dist/src/metrics/metrics_service.js +23 -4
- package/dist/src/metrics/metrics_service.js.map +1 -1
- package/dist/src/metrics/pulse.d.ts +2 -0
- package/dist/src/metrics/pulse.d.ts.map +1 -1
- package/dist/src/metrics/pulse.js +6 -2
- package/dist/src/metrics/pulse.js.map +1 -1
- package/dist/src/metrics/stats.d.ts +14 -0
- package/dist/src/metrics/stats.d.ts.map +1 -1
- package/dist/src/metrics/stats.js +7 -2
- package/dist/src/metrics/stats.js.map +1 -1
- package/dist/src/profiling/index.d.ts +1 -1
- package/dist/src/profiling/index.js +1 -1
- package/dist/src/registry.d.ts +7 -2
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +4 -1
- package/dist/src/registry.js.map +1 -1
- package/dist/src/request_watcher.d.ts +111 -8
- package/dist/src/request_watcher.d.ts.map +1 -1
- package/dist/src/request_watcher.js +113 -17
- package/dist/src/request_watcher.js.map +1 -1
- package/dist/src/telescope_middleware.d.ts.map +1 -1
- package/dist/src/telescope_middleware.js +2 -0
- package/dist/src/telescope_middleware.js.map +1 -1
- package/dist/src/ui/index.d.ts +1 -1
- package/dist/src/ui/index.js +1 -1
- package/dist/src/watchers/index.d.ts +1 -1
- package/dist/src/watchers/index.js +1 -1
- package/dist/stubs/config/telescope.stub +20 -0
- package/package.json +1 -1
|
@@ -12,6 +12,16 @@ export interface RequestEntryContent {
|
|
|
12
12
|
durationMs: number;
|
|
13
13
|
/** The active trace id at request time, or `null`. */
|
|
14
14
|
traceId: string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Host-supplied context for this request, from the {@link RequestEnrichment}
|
|
17
|
+
* hook — e.g. which front-end screen issued the call. Absent when no hook is
|
|
18
|
+
* configured or it returned nothing.
|
|
19
|
+
*
|
|
20
|
+
* Declared BEFORE `body` on purpose: the recorder's content-byte budget drops
|
|
21
|
+
* keys in insertion order, and a captured body is the field that can be
|
|
22
|
+
* megabytes. A few short context fields must not be the ones starved out.
|
|
23
|
+
*/
|
|
24
|
+
context?: Record<string, unknown>;
|
|
15
25
|
/**
|
|
16
26
|
* Captured request body — present ONLY when the request exposes a body and it
|
|
17
27
|
* passed the {@link RequestCaptureOptions} gates. A gated-out body is a marker
|
|
@@ -20,9 +30,10 @@ export interface RequestEntryContent {
|
|
|
20
30
|
*/
|
|
21
31
|
body?: unknown;
|
|
22
32
|
/**
|
|
23
|
-
* The authenticated user at request time,
|
|
24
|
-
*
|
|
25
|
-
*
|
|
33
|
+
* The authenticated user at request time, from `ctx.auth.user` or — when the
|
|
34
|
+
* host's guard is async and publishes it instead — the `@adonis-agora/context`
|
|
35
|
+
* `userRef()` (see {@link resolveRequestUser}). Only `id` and `email` are
|
|
36
|
+
* captured, never the full model. `null` when unauthenticated or not exposed.
|
|
26
37
|
*/
|
|
27
38
|
user: {
|
|
28
39
|
id: string;
|
|
@@ -79,6 +90,55 @@ export interface ResolvedRequestCapture {
|
|
|
79
90
|
}
|
|
80
91
|
/** Apply the requestCapture defaults to a (possibly partial) config. */
|
|
81
92
|
export declare function resolveRequestCapture(options: RequestCaptureOptions | undefined): ResolvedRequestCapture;
|
|
93
|
+
/** Cap on host-supplied tags per entry — a buggy hook can't bloat the entry. */
|
|
94
|
+
export declare const MAX_ENRICHMENT_TAGS = 16;
|
|
95
|
+
/** Cap on the length of a single host-supplied tag. */
|
|
96
|
+
export declare const MAX_ENRICHMENT_TAG_LENGTH = 128;
|
|
97
|
+
/**
|
|
98
|
+
* What a {@link RequestEnrichment} hook may contribute to a `request` entry.
|
|
99
|
+
* Every field is optional; returning `undefined` (or nothing) enriches nothing.
|
|
100
|
+
*/
|
|
101
|
+
export interface RequestEnrichmentResult {
|
|
102
|
+
/**
|
|
103
|
+
* Extra tags, appended to the ones the watcher derives. Tags are how the
|
|
104
|
+
* dashboard filters, so this is the field to use for anything you want to slice
|
|
105
|
+
* by — `screen:researcher/dashboard_page`, `tenant:acme`, `feature-flag:new-nav`.
|
|
106
|
+
* Capped at {@link MAX_ENRICHMENT_TAGS} tags of {@link MAX_ENRICHMENT_TAG_LENGTH}
|
|
107
|
+
* characters; non-strings and blanks are dropped.
|
|
108
|
+
*/
|
|
109
|
+
tags?: string[];
|
|
110
|
+
/**
|
|
111
|
+
* The authenticated user, for hosts where neither `ctx.auth.user` nor the
|
|
112
|
+
* `@adonis-agora/context` `userRef()` applies. Wins over both when returned.
|
|
113
|
+
*/
|
|
114
|
+
user?: {
|
|
115
|
+
id: string;
|
|
116
|
+
email?: string;
|
|
117
|
+
} | null;
|
|
118
|
+
/**
|
|
119
|
+
* Free-form fields recorded under `content.context`. Use for detail you want to
|
|
120
|
+
* READ on the entry but not filter by; anything you want to filter by belongs
|
|
121
|
+
* in `tags`.
|
|
122
|
+
*/
|
|
123
|
+
context?: Record<string, unknown>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Host hook that enriches a `request` entry with information only the app has.
|
|
127
|
+
*
|
|
128
|
+
* The motivating case: correlating a front-end screen with the calls it makes.
|
|
129
|
+
* The browser sends the current page in a header, and this hook turns it into a
|
|
130
|
+
* `screen:<name>` tag — after which the dashboard can answer "which requests came
|
|
131
|
+
* from the writing screen?" with its existing tag filter.
|
|
132
|
+
*
|
|
133
|
+
* SYNCHRONOUS on purpose. It runs on the recording path of every request, so an
|
|
134
|
+
* `await` here (a DB lookup for the user, say) would put host I/O between the
|
|
135
|
+
* response and the next request. Read what is already on the `ctx` — headers,
|
|
136
|
+
* route, a guard's resolved state — and return.
|
|
137
|
+
*
|
|
138
|
+
* A throw is swallowed: enrichment is never a reason to lose an entry, let alone
|
|
139
|
+
* to break the request being observed.
|
|
140
|
+
*/
|
|
141
|
+
export type RequestEnrichment = (ctx: HttpContextLike) => RequestEnrichmentResult | undefined;
|
|
82
142
|
/** The minimal slice of an Adonis HttpContext the watcher reads. */
|
|
83
143
|
export interface RequestLike {
|
|
84
144
|
method(): string;
|
|
@@ -88,9 +148,23 @@ export interface RequestLike {
|
|
|
88
148
|
/** A single request header by (case-insensitive) name, when exposed. */
|
|
89
149
|
header?(name: string): string | string[] | number | undefined;
|
|
90
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* The minimal slice of a response the watcher reads.
|
|
153
|
+
*
|
|
154
|
+
* BOTH accessors are optional because hosts disagree on which they expose:
|
|
155
|
+
* AdonisJS's `Response` has ONLY `getStatus()` (its `statusCode` lives on the
|
|
156
|
+
* wrapped Node `ServerResponse`, one level down), while a Node/Express-style
|
|
157
|
+
* response — and every stub in this repo's tests — exposes `statusCode`. Reading
|
|
158
|
+
* just one silently yields `null` on half the hosts, which is how the status went
|
|
159
|
+
* missing on every real Adonis request for so long: `statusCode?: number` is
|
|
160
|
+
* satisfied by any object, so the type system had nothing to say about it.
|
|
161
|
+
*/
|
|
91
162
|
export interface ResponseLike {
|
|
92
163
|
response: {
|
|
164
|
+
/** Node/Express-style status property. */
|
|
93
165
|
statusCode?: number;
|
|
166
|
+
/** AdonisJS `Response.getStatus()` — the only status accessor Adonis exposes. */
|
|
167
|
+
getStatus?(): number;
|
|
94
168
|
};
|
|
95
169
|
}
|
|
96
170
|
export interface HttpContextLike {
|
|
@@ -115,18 +189,47 @@ export interface RecordRequestOptions {
|
|
|
115
189
|
*/
|
|
116
190
|
capture?: RequestCaptureOptions;
|
|
117
191
|
/**
|
|
118
|
-
* Override the
|
|
119
|
-
*
|
|
192
|
+
* Override the resolved user; pass `null` to force "no user". Omit to resolve
|
|
193
|
+
* from the enrichment hook, then `ctx.auth`, then the context accessor
|
|
194
|
+
* (see {@link resolveRequestUser}).
|
|
120
195
|
*/
|
|
121
196
|
user?: {
|
|
122
197
|
id: string;
|
|
123
198
|
email?: string;
|
|
124
199
|
} | null;
|
|
200
|
+
/**
|
|
201
|
+
* Host hook contributing tags / user / context to the entry. See
|
|
202
|
+
* {@link RequestEnrichment}. Omit for the pre-existing behavior.
|
|
203
|
+
*/
|
|
204
|
+
enrich?: RequestEnrichment;
|
|
125
205
|
}
|
|
126
206
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
207
|
+
* The response status, or `null` when it genuinely cannot be determined.
|
|
208
|
+
*
|
|
209
|
+
* Tries `getStatus()` FIRST — it is what AdonisJS exposes, and an Adonis
|
|
210
|
+
* `Response` has no `statusCode` of its own — then the Node/Express-style
|
|
211
|
+
* `statusCode` property. Defensive throughout: a throwing accessor or a
|
|
212
|
+
* non-finite result yields `null` rather than breaking request capture.
|
|
213
|
+
*/
|
|
214
|
+
export declare function resolveResponseStatus(response: HttpContextLike['response']): number | null;
|
|
215
|
+
/**
|
|
216
|
+
* The authenticated user for the entry, extracting only `id` + `email` — never the
|
|
217
|
+
* full model. Two sources, in order:
|
|
218
|
+
*
|
|
219
|
+
* 1. `ctx.auth.user` — the `@adonisjs/auth` convention: a SYNCHRONOUS property,
|
|
220
|
+
* populated once the guard has authenticated.
|
|
221
|
+
* 2. `userRef()` from the `@adonis-agora/context` accessor — the Agora
|
|
222
|
+
* convention, where the guard is async (`getUser()`/`getIdentity()`) and the
|
|
223
|
+
* host publishes the resolved reference into the request context instead.
|
|
224
|
+
*
|
|
225
|
+
* The fallback is what makes attribution work at all on an Agora stack: an auth
|
|
226
|
+
* lib with no synchronous `user` property leaves (1) permanently `undefined`, so
|
|
227
|
+
* every request entry recorded `user: null` even for a fully authenticated
|
|
228
|
+
* session. Reading (2) costs one property read and is skipped entirely when
|
|
229
|
+
* `@adonis-agora/context` is not installed.
|
|
230
|
+
*
|
|
231
|
+
* Strictly defensive: any throw or malformed shape yields `null`, so a hostile or
|
|
232
|
+
* odd auth model can never break (or crash) request capture.
|
|
130
233
|
*/
|
|
131
234
|
export declare function resolveRequestUser(ctx: HttpContextLike): {
|
|
132
235
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request_watcher.d.ts","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"request_watcher.d.ts","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { currentUserRef } from './context_accessor.js';
|
|
1
2
|
import { EntryType } from './entry.js';
|
|
2
3
|
/**
|
|
3
4
|
* Default `requestCapture.maxBodyBytes`: bodies over 128 KiB are not captured.
|
|
@@ -22,6 +23,10 @@ export function resolveRequestCapture(options) {
|
|
|
22
23
|
skipBody: options?.skipBody,
|
|
23
24
|
};
|
|
24
25
|
}
|
|
26
|
+
/** Cap on host-supplied tags per entry — a buggy hook can't bloat the entry. */
|
|
27
|
+
export const MAX_ENRICHMENT_TAGS = 16;
|
|
28
|
+
/** Cap on the length of a single host-supplied tag. */
|
|
29
|
+
export const MAX_ENRICHMENT_TAG_LENGTH = 128;
|
|
25
30
|
/** First string value of a header read via the platform accessor. */
|
|
26
31
|
function headerString(request, name) {
|
|
27
32
|
const value = request.header?.(name);
|
|
@@ -93,29 +98,111 @@ function gateRequestBody(request, capture) {
|
|
|
93
98
|
return body;
|
|
94
99
|
}
|
|
95
100
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
101
|
+
* The response status, or `null` when it genuinely cannot be determined.
|
|
102
|
+
*
|
|
103
|
+
* Tries `getStatus()` FIRST — it is what AdonisJS exposes, and an Adonis
|
|
104
|
+
* `Response` has no `statusCode` of its own — then the Node/Express-style
|
|
105
|
+
* `statusCode` property. Defensive throughout: a throwing accessor or a
|
|
106
|
+
* non-finite result yields `null` rather than breaking request capture.
|
|
107
|
+
*/
|
|
108
|
+
export function resolveResponseStatus(response) {
|
|
109
|
+
try {
|
|
110
|
+
if (typeof response.getStatus === 'function') {
|
|
111
|
+
const status = response.getStatus();
|
|
112
|
+
if (typeof status === 'number' && Number.isFinite(status))
|
|
113
|
+
return status;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// A throwing accessor is not a reason to lose the whole entry — fall through.
|
|
118
|
+
}
|
|
119
|
+
return typeof response.statusCode === 'number' ? response.statusCode : null;
|
|
120
|
+
}
|
|
121
|
+
/** Narrow an arbitrary user-ish value to the `{ id, email? }` slice we record. */
|
|
122
|
+
function userSlice(value) {
|
|
123
|
+
if (value === null || value === undefined)
|
|
124
|
+
return null;
|
|
125
|
+
const record = value;
|
|
126
|
+
const id = record.id;
|
|
127
|
+
if (typeof id !== 'string' && typeof id !== 'number')
|
|
128
|
+
return null;
|
|
129
|
+
const email = record.email;
|
|
130
|
+
return {
|
|
131
|
+
id: String(id),
|
|
132
|
+
...(typeof email === 'string' && email.length > 0 ? { email } : {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The authenticated user for the entry, extracting only `id` + `email` — never the
|
|
137
|
+
* full model. Two sources, in order:
|
|
138
|
+
*
|
|
139
|
+
* 1. `ctx.auth.user` — the `@adonisjs/auth` convention: a SYNCHRONOUS property,
|
|
140
|
+
* populated once the guard has authenticated.
|
|
141
|
+
* 2. `userRef()` from the `@adonis-agora/context` accessor — the Agora
|
|
142
|
+
* convention, where the guard is async (`getUser()`/`getIdentity()`) and the
|
|
143
|
+
* host publishes the resolved reference into the request context instead.
|
|
144
|
+
*
|
|
145
|
+
* The fallback is what makes attribution work at all on an Agora stack: an auth
|
|
146
|
+
* lib with no synchronous `user` property leaves (1) permanently `undefined`, so
|
|
147
|
+
* every request entry recorded `user: null` even for a fully authenticated
|
|
148
|
+
* session. Reading (2) costs one property read and is skipped entirely when
|
|
149
|
+
* `@adonis-agora/context` is not installed.
|
|
150
|
+
*
|
|
151
|
+
* Strictly defensive: any throw or malformed shape yields `null`, so a hostile or
|
|
152
|
+
* odd auth model can never break (or crash) request capture.
|
|
99
153
|
*/
|
|
100
154
|
export function resolveRequestUser(ctx) {
|
|
101
155
|
try {
|
|
102
|
-
const
|
|
103
|
-
if (
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return
|
|
111
|
-
id: String(id),
|
|
112
|
-
...(typeof email === 'string' && email.length > 0 ? { email } : {}),
|
|
113
|
-
};
|
|
156
|
+
const fromGuard = userSlice(ctx.auth?.user);
|
|
157
|
+
if (fromGuard !== null)
|
|
158
|
+
return fromGuard;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Fall through to the context — a broken guard must not cost us the fallback.
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
return userSlice(currentUserRef());
|
|
114
165
|
}
|
|
115
166
|
catch {
|
|
116
167
|
return null;
|
|
117
168
|
}
|
|
118
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Run the host's enrichment hook defensively and normalize what it returned.
|
|
172
|
+
*
|
|
173
|
+
* Everything here is "never let the host break the entry": a throwing hook, a
|
|
174
|
+
* hook returning garbage, a hook returning a thousand tags — all degrade to
|
|
175
|
+
* recording what we would have recorded anyway. Tags are filtered to non-empty
|
|
176
|
+
* strings, trimmed to {@link MAX_ENRICHMENT_TAG_LENGTH}, and capped at
|
|
177
|
+
* {@link MAX_ENRICHMENT_TAGS}.
|
|
178
|
+
*/
|
|
179
|
+
function runEnrichment(enrich, ctx) {
|
|
180
|
+
if (enrich === undefined)
|
|
181
|
+
return { tags: [] };
|
|
182
|
+
let result;
|
|
183
|
+
try {
|
|
184
|
+
result = enrich(ctx);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return { tags: [] };
|
|
188
|
+
}
|
|
189
|
+
if (result === null || typeof result !== 'object')
|
|
190
|
+
return { tags: [] };
|
|
191
|
+
const tags = Array.isArray(result.tags)
|
|
192
|
+
? result.tags
|
|
193
|
+
.filter((tag) => typeof tag === 'string' && tag.length > 0)
|
|
194
|
+
.slice(0, MAX_ENRICHMENT_TAGS)
|
|
195
|
+
.map((tag) => tag.length > MAX_ENRICHMENT_TAG_LENGTH ? tag.slice(0, MAX_ENRICHMENT_TAG_LENGTH) : tag)
|
|
196
|
+
: [];
|
|
197
|
+
const context = result.context !== null && typeof result.context === 'object' && !Array.isArray(result.context)
|
|
198
|
+
? result.context
|
|
199
|
+
: undefined;
|
|
200
|
+
return {
|
|
201
|
+
tags,
|
|
202
|
+
...(result.user !== undefined ? { user: userSlice(result.user) } : {}),
|
|
203
|
+
...(context !== undefined ? { context } : {}),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
119
206
|
/**
|
|
120
207
|
* The pure, framework-agnostic core of the HTTP request watcher: build a
|
|
121
208
|
* `request` {@link RecordInput} from a (stubbable) HttpContext-like value and a
|
|
@@ -125,9 +212,16 @@ export function resolveRequestUser(ctx) {
|
|
|
125
212
|
export async function recordRequest(store, ctx, startedAt, options = {}) {
|
|
126
213
|
const method = String(ctx.request.method()).toUpperCase();
|
|
127
214
|
const url = stripQuery(ctx.request.url());
|
|
128
|
-
const status =
|
|
215
|
+
const status = resolveResponseStatus(ctx.response);
|
|
129
216
|
const durationMs = options.durationMs ?? Math.max(0, Date.now() - startedAt);
|
|
130
|
-
const
|
|
217
|
+
const enrichment = runEnrichment(options.enrich, ctx);
|
|
218
|
+
// Precedence: an explicit `options.user` (a caller that already knows) beats the
|
|
219
|
+
// host hook, which beats what we can read off the ctx.
|
|
220
|
+
const user = options.user !== undefined
|
|
221
|
+
? options.user
|
|
222
|
+
: enrichment.user !== undefined
|
|
223
|
+
? enrichment.user
|
|
224
|
+
: resolveRequestUser(ctx);
|
|
131
225
|
// Body capture (gated). Only when the caller opted in AND the request exposes a
|
|
132
226
|
// body accessor. The gate runs HERE — before the store's synchronous redaction
|
|
133
227
|
// walk — so a huge/binary body is replaced by a marker and never walked; a body
|
|
@@ -144,6 +238,7 @@ export async function recordRequest(store, ctx, startedAt, options = {}) {
|
|
|
144
238
|
durationMs,
|
|
145
239
|
traceId: options.traceId ?? null,
|
|
146
240
|
user,
|
|
241
|
+
...(enrichment.context !== undefined ? { context: enrichment.context } : {}),
|
|
147
242
|
...(captureBody !== undefined ? { body: captureBody } : {}),
|
|
148
243
|
},
|
|
149
244
|
durationMs,
|
|
@@ -152,6 +247,7 @@ export async function recordRequest(store, ctx, startedAt, options = {}) {
|
|
|
152
247
|
`method:${method}`,
|
|
153
248
|
...(status !== null ? [`status:${status}`] : []),
|
|
154
249
|
...(user?.id ? [`user:${user.id}`] : []),
|
|
250
|
+
...enrichment.tags,
|
|
155
251
|
],
|
|
156
252
|
...(options.traceId !== undefined ? { traceId: options.traceId } : {}),
|
|
157
253
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request_watcher.js","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAoB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"request_watcher.js","sourceRoot":"","sources":["../../src/request_watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telescope_middleware.d.ts","sourceRoot":"","sources":["../../src/telescope_middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAwBxD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAChC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"telescope_middleware.d.ts","sourceRoot":"","sources":["../../src/telescope_middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAwBxD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAChC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,gBA4D1C;CACF"}
|
|
@@ -70,6 +70,8 @@ export default class TelescopeMiddleware {
|
|
|
70
70
|
// Body capture is opt-in: only pass `capture` when configured, so the
|
|
71
71
|
// default stays "no body field" and zero body-read overhead.
|
|
72
72
|
...(runtime.requestCapture !== null ? { capture: runtime.requestCapture } : {}),
|
|
73
|
+
// Host enrichment (screen tag, tenant, …). Absent unless configured.
|
|
74
|
+
...(runtime.requestEnrichment !== null ? { enrich: runtime.requestEnrichment } : {}),
|
|
73
75
|
});
|
|
74
76
|
}
|
|
75
77
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telescope_middleware.js","sourceRoot":"","sources":["../../src/telescope_middleware.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAwB,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAU3E;;;8FAG8F;AAC9F,SAAS,YAAY,CAAC,GAAoB;IACxC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IACpC,MAAM,OAAO,GAAI,GAAsC,CAAC,KAAK,EAAE,OAAO,CAAC;IACvE,OAAO,GAAG,MAAM,IAAI,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IACtC,KAAK,CAAC,MAAM,CAAC,GAAgB,EAAE,IAAY;QACzC,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;QACtC,gFAAgF;QAChF,gFAAgF;QAChF,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,qBAAqB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACvE,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAE5B,8FAA8F;QAC9F,oFAAoF;QACpF,sFAAsF;QACtF,yFAAyF;QACzF,oEAAoE;QACpE,MAAM,OAAO,GAAG,GAAiC,CAAC;QAClD,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACjE,MAAM,OAAO,GACX,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC;YACzD,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC;YAClC,CAAC,CAAC,IAAI,CAAC;QAEX,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,0EAA0E;YAC1E,mEAAmE;YACnE,IAAI,CAAC;gBACH,MAAM,OAAO,GAAI,GAAkC,CAAC,OAAO,CAAC;gBAC5D,MAAM,sBAAsB,CAAC,KAAK,EAAE,KAAK,EAAE;oBACzC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;oBACxB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;iBACnB,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,0DAA0D;YAC5D,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,0EAA0E;YAC1E,qEAAqE;YACrE,uEAAuE;YACvE,IAAI,CAAC;gBACH,MAAM,aAAa,CAAC,KAAK,EAAE,GAAiC,EAAE,SAAS,EAAE;oBACvE,sEAAsE;oBACtE,6DAA6D;oBAC7D,GAAG,CAAC,OAAO,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"telescope_middleware.js","sourceRoot":"","sources":["../../src/telescope_middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/src/ui/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.13.0";
|
|
3
3
|
export type { AccessDeniedInfo, AccessDeniedPageOptions, AccessDeniedReason, } from './access_denied_page.js';
|
|
4
4
|
export { CONSOLE as ACCESS_DENIED_CONSOLE, escapeHtml, renderAccessDeniedPage, resolveAccessDeniedPage, } from './access_denied_page.js';
|
|
5
5
|
export type { EntrySummary, RetentionInfo, RetentionOptions, RetentionPruneOptions, RetentionSamplingRate, } from './api.js';
|
package/dist/src/ui/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.13.0';
|
|
3
3
|
// — the built-in "access denied" page (what a browser sees on a refused page navigation) —
|
|
4
4
|
export { CONSOLE as ACCESS_DENIED_CONSOLE, escapeHtml, renderAccessDeniedPage, resolveAccessDeniedPage, } from './access_denied_page.js';
|
|
5
5
|
// — JSON API —
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.13.0";
|
|
3
3
|
export type { CacheEntryContent, CacheEventLike, CacheOperation } from './cache_watcher.js';
|
|
4
4
|
export { buildCacheEntry, CACHE_EVENTS, CacheWatcher } from './cache_watcher.js';
|
|
5
5
|
export { nextCronRunMs } from './cron_next_run.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.13.0';
|
|
3
3
|
// — cache watcher —
|
|
4
4
|
export { buildCacheEntry, CACHE_EVENTS, CacheWatcher } from './cache_watcher.js';
|
|
5
5
|
export { nextCronRunMs } from './cron_next_run.js';
|
|
@@ -88,6 +88,26 @@ export default defineConfig({
|
|
|
88
88
|
// skipBody: (request) => request.url.startsWith('/webhooks/'),
|
|
89
89
|
// },
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Enrich every request entry with what only your app knows. Return 'tags' for
|
|
93
|
+
* anything you want to FILTER by in the dashboard, 'context' for detail you only
|
|
94
|
+
* want to read, and 'user' when neither ctx.auth.user nor the
|
|
95
|
+
* @adonis-agora/context userRef() applies.
|
|
96
|
+
*
|
|
97
|
+
* The classic use: have the front end send its current screen in a header, and
|
|
98
|
+
* tag the entry with it — then the dashboard answers "which requests came from
|
|
99
|
+
* the writing screen?" with its normal tag filter.
|
|
100
|
+
*
|
|
101
|
+
* SYNCHRONOUS: it runs on the recording path of every request, so read what is
|
|
102
|
+
* already on the ctx (headers, route, resolved guard state) rather than doing
|
|
103
|
+
* I/O. A throw is swallowed — enrichment never costs you the entry.
|
|
104
|
+
*/
|
|
105
|
+
// requestEnrichment: (ctx) => {
|
|
106
|
+
// // header() is optional on the framework-agnostic ctx type — hence the ?. call
|
|
107
|
+
// const screen = ctx.request.header?.('x-screen')
|
|
108
|
+
// return typeof screen === 'string' ? { tags: ['screen:' + screen] } : undefined
|
|
109
|
+
// },
|
|
110
|
+
|
|
91
111
|
/**
|
|
92
112
|
* Sensitive-data redaction. Every entry's content is scrubbed before it is
|
|
93
113
|
* persisted — a built-in set of sensitive keys ('authorization', 'cookie',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonis-agora/telescope",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Laravel Telescope-style headless observability for AdonisJS — records HTTP requests and every Agora diagnostics event as queryable entries, plus opt-in subpaths for per-technology watchers, a web dashboard, AI exception diagnosis, and alerting.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|