@mandujs/core 0.29.0 → 0.30.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/package.json +10 -1
- package/src/bundler/analyzer.ts +843 -0
- package/src/config/mandu.ts +68 -0
- package/src/config/validate.ts +44 -0
- package/src/filling/context.ts +166 -0
- package/src/filling/filling.ts +10 -1
- package/src/index.ts +32 -0
- package/src/observability/index.ts +26 -0
- package/src/observability/tracing.ts +694 -0
- package/src/runtime/cache.ts +197 -13
- package/src/runtime/index.ts +8 -0
- package/src/runtime/server.ts +387 -24
package/src/config/mandu.ts
CHANGED
|
@@ -170,6 +170,16 @@ export interface ManduConfig {
|
|
|
170
170
|
minify?: boolean;
|
|
171
171
|
sourcemap?: boolean;
|
|
172
172
|
splitting?: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Phase 18.η — emit `.mandu/analyze/report.html` + `report.json` after
|
|
175
|
+
* a successful build. Equivalent to `mandu build --analyze`. Default:
|
|
176
|
+
* `false`. Report artefacts are self-contained (no CDN, no external
|
|
177
|
+
* JS) and safe to commit to a private dashboard or inspect locally.
|
|
178
|
+
*
|
|
179
|
+
* The CLI `--analyze` flag wins over this field; `--analyze=json`
|
|
180
|
+
* writes JSON only (useful for CI, skips the HTML render cost).
|
|
181
|
+
*/
|
|
182
|
+
analyze?: boolean;
|
|
173
183
|
};
|
|
174
184
|
dev?: {
|
|
175
185
|
hmr?: boolean;
|
|
@@ -286,6 +296,64 @@ export interface ManduConfig {
|
|
|
286
296
|
heapEndpoint?: boolean;
|
|
287
297
|
/** `/_mandu/metrics` Prometheus text exposure toggle. */
|
|
288
298
|
metricsEndpoint?: boolean;
|
|
299
|
+
/**
|
|
300
|
+
* Phase 18.θ — OpenTelemetry-compatible request tracing.
|
|
301
|
+
*
|
|
302
|
+
* When enabled, every request opens a root server span
|
|
303
|
+
* (`http.request`) that chains child spans for middleware, loader,
|
|
304
|
+
* SSR, and sandbox execution. The root span's trace-id is
|
|
305
|
+
* propagated across AsyncLocalStorage and stamped onto outgoing
|
|
306
|
+
* fetches via `traceparent`.
|
|
307
|
+
*
|
|
308
|
+
* Exporters:
|
|
309
|
+
* - `"console"` (default) — pretty-prints spans to stderr, useful
|
|
310
|
+
* in `mandu dev`.
|
|
311
|
+
* - `"otlp"` — POSTs OTLP/HTTP JSON to `endpoint/v1/traces`.
|
|
312
|
+
* Compatible with Honeycomb, Grafana Tempo, AWS X-Ray (via the
|
|
313
|
+
* OTel Collector), and the standalone OpenTelemetry Collector.
|
|
314
|
+
*
|
|
315
|
+
* Setting the `MANDU_OTEL_ENDPOINT` env var overrides both
|
|
316
|
+
* `enabled` and `exporter` at runtime (shortcut for ops that want
|
|
317
|
+
* to enable tracing without a config change).
|
|
318
|
+
*
|
|
319
|
+
* Default: disabled (zero overhead when `observability.tracing` is
|
|
320
|
+
* omitted).
|
|
321
|
+
*/
|
|
322
|
+
tracing?: {
|
|
323
|
+
enabled?: boolean;
|
|
324
|
+
exporter?: "console" | "otlp";
|
|
325
|
+
endpoint?: string;
|
|
326
|
+
headers?: Record<string, string>;
|
|
327
|
+
serviceName?: string;
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* Phase 18.ζ — ISR / tag-based cache invalidation.
|
|
332
|
+
*
|
|
333
|
+
* - `defaultMaxAge` : fresh TTL (seconds) applied when a loader
|
|
334
|
+
* does not emit its own `_cache` / `ctx.cache`
|
|
335
|
+
* metadata. Set to a positive integer to enable
|
|
336
|
+
* automatic caching across every non-dynamic
|
|
337
|
+
* route (Next.js `export const revalidate`
|
|
338
|
+
* equivalent). Default `undefined` (no auto).
|
|
339
|
+
* - `defaultSwr` : stale-while-revalidate window (seconds)
|
|
340
|
+
* appended after the fresh TTL. Serves stale
|
|
341
|
+
* HTML instantly while background regeneration
|
|
342
|
+
* runs. Default `0`.
|
|
343
|
+
* - `maxEntries` : LRU bound for the in-memory store. Default
|
|
344
|
+
* `1000`.
|
|
345
|
+
* - `store` : backend. Currently `"memory"` only; reserved
|
|
346
|
+
* for future `"redis"` adapter.
|
|
347
|
+
*
|
|
348
|
+
* Disable entirely by omitting this block. Revalidation APIs live in
|
|
349
|
+
* `@mandujs/core/runtime`: `revalidate(tag)`, `revalidateTag(tag)`,
|
|
350
|
+
* `revalidatePath(path)`.
|
|
351
|
+
*/
|
|
352
|
+
cache?: {
|
|
353
|
+
defaultMaxAge?: number;
|
|
354
|
+
defaultSwr?: number;
|
|
355
|
+
maxEntries?: number;
|
|
356
|
+
store?: "memory";
|
|
289
357
|
};
|
|
290
358
|
plugins?: ManduPlugin[];
|
|
291
359
|
hooks?: Partial<ManduHooks>;
|
package/src/config/validate.ts
CHANGED
|
@@ -105,6 +105,13 @@ const BuildConfigSchema = z
|
|
|
105
105
|
* module exports `generateStaticParams` is prerendered).
|
|
106
106
|
*/
|
|
107
107
|
prerender: z.boolean().default(true),
|
|
108
|
+
/**
|
|
109
|
+
* Phase 18.η — opt into post-build bundle analyzer artefacts
|
|
110
|
+
* (`.mandu/analyze/report.html` + `report.json`). Default `false`.
|
|
111
|
+
* CLI `--analyze` overrides this at runtime; config is the "always on
|
|
112
|
+
* for this project" switch.
|
|
113
|
+
*/
|
|
114
|
+
analyze: z.boolean().default(false),
|
|
108
115
|
})
|
|
109
116
|
.strict();
|
|
110
117
|
|
|
@@ -229,10 +236,28 @@ const TestConfigSchema = z
|
|
|
229
236
|
* default so the runtime can distinguish "not set" (use mode default)
|
|
230
237
|
* from "explicit false" (force off even in dev).
|
|
231
238
|
*/
|
|
239
|
+
/**
|
|
240
|
+
* Phase 18.θ — tracing sub-block. All fields optional; omitting the
|
|
241
|
+
* whole block keeps tracing disabled and incurs zero runtime overhead.
|
|
242
|
+
* `endpoint` and `headers` are only meaningful when `exporter === "otlp"`
|
|
243
|
+
* but we don't make that a cross-field refine — runtime falls back to
|
|
244
|
+
* console with a warning when `"otlp"` is requested without an endpoint.
|
|
245
|
+
*/
|
|
246
|
+
const TracingConfigSchema = z
|
|
247
|
+
.object({
|
|
248
|
+
enabled: z.boolean().optional(),
|
|
249
|
+
exporter: z.enum(["console", "otlp"]).optional(),
|
|
250
|
+
endpoint: z.string().url().optional(),
|
|
251
|
+
headers: z.record(z.string()).optional(),
|
|
252
|
+
serviceName: z.string().min(1).optional(),
|
|
253
|
+
})
|
|
254
|
+
.strict();
|
|
255
|
+
|
|
232
256
|
const ObservabilityConfigSchema = z
|
|
233
257
|
.object({
|
|
234
258
|
heapEndpoint: z.boolean().optional(),
|
|
235
259
|
metricsEndpoint: z.boolean().optional(),
|
|
260
|
+
tracing: TracingConfigSchema.optional(),
|
|
236
261
|
})
|
|
237
262
|
.strict();
|
|
238
263
|
|
|
@@ -293,6 +318,23 @@ const MiddlewareSchema = z.custom<Middleware>(
|
|
|
293
318
|
}
|
|
294
319
|
);
|
|
295
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Phase 18.ζ — ISR / cache config (strict).
|
|
323
|
+
*
|
|
324
|
+
* All fields optional. Omitting the block leaves caching disabled unless
|
|
325
|
+
* individual routes opt in via `filling.loader(fn, { revalidate })` or
|
|
326
|
+
* loader-level `_cache` metadata. Setting `defaultMaxAge` makes every
|
|
327
|
+
* non-dynamic route auto-cache with that fresh TTL.
|
|
328
|
+
*/
|
|
329
|
+
const CacheConfigSchema = z
|
|
330
|
+
.object({
|
|
331
|
+
defaultMaxAge: z.number().int().nonnegative().optional(),
|
|
332
|
+
defaultSwr: z.number().int().nonnegative().optional(),
|
|
333
|
+
maxEntries: z.number().int().positive().optional(),
|
|
334
|
+
store: z.enum(["memory"]).optional(),
|
|
335
|
+
})
|
|
336
|
+
.strict();
|
|
337
|
+
|
|
296
338
|
export const ManduConfigSchema = z
|
|
297
339
|
.object({
|
|
298
340
|
adapter: AdapterConfigSchema.optional(),
|
|
@@ -322,6 +364,8 @@ export const ManduConfigSchema = z
|
|
|
322
364
|
seo: SeoConfigSchema.default({}),
|
|
323
365
|
test: TestConfigSchema.default({}),
|
|
324
366
|
observability: ObservabilityConfigSchema.default({}),
|
|
367
|
+
/** Phase 18.ζ — ISR / tag-based cache invalidation. Optional. */
|
|
368
|
+
cache: CacheConfigSchema.optional(),
|
|
325
369
|
plugins: z.array(ManduPluginSchema).optional(),
|
|
326
370
|
hooks: ManduHooksSchema.optional(),
|
|
327
371
|
/**
|
package/src/filling/context.ts
CHANGED
|
@@ -12,6 +12,14 @@ import { ContractValidator, type ContractValidatorOptions } from "../contract/va
|
|
|
12
12
|
import { getCookieCodec } from "./cookie-codec";
|
|
13
13
|
import { type FillingDeps, globalDeps } from "./deps";
|
|
14
14
|
import { createSSEConnection, type SSEOptions, type SSEConnection } from "./sse";
|
|
15
|
+
import {
|
|
16
|
+
getActiveSpan,
|
|
17
|
+
getTracer,
|
|
18
|
+
runWithSpan,
|
|
19
|
+
type Span,
|
|
20
|
+
type SpanAttributes,
|
|
21
|
+
type SpanOptions,
|
|
22
|
+
} from "../observability/tracing";
|
|
15
23
|
|
|
16
24
|
type ContractInput<
|
|
17
25
|
TContract extends ContractSchema,
|
|
@@ -285,12 +293,45 @@ async function hmacSign(data: string, secret: string): Promise<string> {
|
|
|
285
293
|
|
|
286
294
|
// ========== ManduContext ==========
|
|
287
295
|
|
|
296
|
+
/**
|
|
297
|
+
* Phase 18.ζ — 로더가 캐시 메타데이터를 선언하기 위한 플루언트 헬퍼.
|
|
298
|
+
*
|
|
299
|
+
* 내부적으로는 `ctx._cacheMeta` 에 누적하며, 서버 런타임이 loader 실행
|
|
300
|
+
* 직후 읽어 `_cache` 블록과 동일하게 해석한다. 반환 데이터에 `_cache` 를
|
|
301
|
+
* 끼워넣는 방식과 동일한 의미지만, 타입 안정성이 더 높다.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* .loader(async (ctx) => {
|
|
306
|
+
* ctx.cache.tag("posts").tag("posts:42").maxAge(3600).swr(86400);
|
|
307
|
+
* return { post: await db.getPost(42) };
|
|
308
|
+
* })
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
export interface CacheHelper {
|
|
312
|
+
tag(...tags: string[]): CacheHelper;
|
|
313
|
+
maxAge(seconds: number): CacheHelper;
|
|
314
|
+
/** alias for maxAge — Next.js parity */
|
|
315
|
+
revalidate(seconds: number): CacheHelper;
|
|
316
|
+
swr(seconds: number): CacheHelper;
|
|
317
|
+
/** alias for swr */
|
|
318
|
+
staleWhileRevalidate(seconds: number): CacheHelper;
|
|
319
|
+
/** 현재까지 누적된 메타데이터 스냅샷 (런타임 내부용) */
|
|
320
|
+
readonly meta: {
|
|
321
|
+
tags: string[];
|
|
322
|
+
maxAge?: number;
|
|
323
|
+
staleWhileRevalidate?: number;
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
288
327
|
export class ManduContext {
|
|
289
328
|
private store: Map<string, unknown> = new Map();
|
|
290
329
|
private _params: Record<string, string>;
|
|
291
330
|
private _query: Record<string, string>;
|
|
292
331
|
private _cookies: CookieManager;
|
|
293
332
|
private _deps: FillingDeps;
|
|
333
|
+
private _cacheMeta: { tags: string[]; maxAge?: number; staleWhileRevalidate?: number } = { tags: [] };
|
|
334
|
+
private _cacheHelper: CacheHelper | null = null;
|
|
294
335
|
|
|
295
336
|
constructor(
|
|
296
337
|
public readonly request: Request,
|
|
@@ -303,6 +344,59 @@ export class ManduContext {
|
|
|
303
344
|
this._deps = deps ?? globalDeps.get();
|
|
304
345
|
}
|
|
305
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Phase 18.ζ — 로더 내부에서 호출하는 캐시 메타데이터 플루언트 헬퍼.
|
|
349
|
+
* 누적 호출 가능: `ctx.cache.tag("a", "b").maxAge(60).swr(300)`
|
|
350
|
+
*/
|
|
351
|
+
get cache(): CacheHelper {
|
|
352
|
+
if (this._cacheHelper) return this._cacheHelper;
|
|
353
|
+
const meta = this._cacheMeta;
|
|
354
|
+
const helper: CacheHelper = {
|
|
355
|
+
tag: (...tags: string[]) => {
|
|
356
|
+
for (const t of tags) {
|
|
357
|
+
if (typeof t === "string" && t.length > 0 && !meta.tags.includes(t)) {
|
|
358
|
+
meta.tags.push(t);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return helper;
|
|
362
|
+
},
|
|
363
|
+
maxAge: (seconds: number) => {
|
|
364
|
+
if (Number.isFinite(seconds) && seconds >= 0) meta.maxAge = seconds;
|
|
365
|
+
return helper;
|
|
366
|
+
},
|
|
367
|
+
revalidate: (seconds: number) => helper.maxAge(seconds),
|
|
368
|
+
swr: (seconds: number) => {
|
|
369
|
+
if (Number.isFinite(seconds) && seconds >= 0) meta.staleWhileRevalidate = seconds;
|
|
370
|
+
return helper;
|
|
371
|
+
},
|
|
372
|
+
staleWhileRevalidate: (seconds: number) => helper.swr(seconds),
|
|
373
|
+
get meta() {
|
|
374
|
+
return {
|
|
375
|
+
tags: [...meta.tags],
|
|
376
|
+
maxAge: meta.maxAge,
|
|
377
|
+
staleWhileRevalidate: meta.staleWhileRevalidate,
|
|
378
|
+
};
|
|
379
|
+
},
|
|
380
|
+
};
|
|
381
|
+
this._cacheHelper = helper;
|
|
382
|
+
return helper;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Phase 18.ζ — 서버 런타임이 loader 종료 후 누적된 메타 스냅샷을 읽는다.
|
|
387
|
+
* 내부 전용. 유저 코드는 `ctx.cache` 를 사용할 것.
|
|
388
|
+
*/
|
|
389
|
+
getCacheMetaSnapshot(): { tags: string[]; maxAge?: number; staleWhileRevalidate?: number } | null {
|
|
390
|
+
if (this._cacheMeta.tags.length === 0 && this._cacheMeta.maxAge === undefined && this._cacheMeta.staleWhileRevalidate === undefined) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
tags: [...this._cacheMeta.tags],
|
|
395
|
+
maxAge: this._cacheMeta.maxAge,
|
|
396
|
+
staleWhileRevalidate: this._cacheMeta.staleWhileRevalidate,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
306
400
|
/**
|
|
307
401
|
* DNA-002: 의존성 접근
|
|
308
402
|
*
|
|
@@ -631,6 +725,78 @@ export class ManduContext {
|
|
|
631
725
|
has(key: string): boolean {
|
|
632
726
|
return this.store.has(key);
|
|
633
727
|
}
|
|
728
|
+
|
|
729
|
+
// ============================================
|
|
730
|
+
// 🥟 Tracing (Phase 18.θ)
|
|
731
|
+
// ============================================
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* The currently-active tracing span for this request, or `undefined`
|
|
735
|
+
* when tracing is disabled. Looked up via AsyncLocalStorage so it
|
|
736
|
+
* stays accurate across nested awaits — a loader that opens a child
|
|
737
|
+
* span before hitting an external API will see `ctx.span` return
|
|
738
|
+
* that child span until the child's `end()` fires.
|
|
739
|
+
*
|
|
740
|
+
* When tracing is disabled this reads as `undefined` (the runtime
|
|
741
|
+
* never opens a recording span), keeping the hot path free of
|
|
742
|
+
* extra allocations.
|
|
743
|
+
*/
|
|
744
|
+
get span(): Span | undefined {
|
|
745
|
+
const active = getActiveSpan();
|
|
746
|
+
return active && active.recording ? active : undefined;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Open a child span scoped to the async context of `fn`. The span
|
|
751
|
+
* auto-ends when the returned promise resolves; if `fn` throws, the
|
|
752
|
+
* span is marked `status=error` with the thrown message, the span
|
|
753
|
+
* is ended, and the error re-thrown.
|
|
754
|
+
*
|
|
755
|
+
* When tracing is disabled this degenerates to just `await fn(noopSpan)`
|
|
756
|
+
* with no allocation in the hot path — callers don't have to branch
|
|
757
|
+
* on `ctx.span` themselves.
|
|
758
|
+
*
|
|
759
|
+
* @example
|
|
760
|
+
* const users = await ctx.startSpan("db.users.findAll", async (span) => {
|
|
761
|
+
* span.setAttribute("db.system", "postgres");
|
|
762
|
+
* return await sql\`SELECT * FROM users\`;
|
|
763
|
+
* });
|
|
764
|
+
*/
|
|
765
|
+
async startSpan<T>(
|
|
766
|
+
name: string,
|
|
767
|
+
fn: (span: Span) => Promise<T> | T,
|
|
768
|
+
opts: SpanOptions = {}
|
|
769
|
+
): Promise<T> {
|
|
770
|
+
const tracer = getTracer();
|
|
771
|
+
if (!tracer.enabled) {
|
|
772
|
+
// Fast path: invoke fn with a shared no-op span (type-shape
|
|
773
|
+
// identical, zero allocations).
|
|
774
|
+
const { startSpan } = tracer;
|
|
775
|
+
const span = startSpan.call(tracer, name, opts);
|
|
776
|
+
return await fn(span);
|
|
777
|
+
}
|
|
778
|
+
const span = tracer.startSpan(name, opts);
|
|
779
|
+
try {
|
|
780
|
+
const result = await runWithSpan(span, () => fn(span));
|
|
781
|
+
if (span.status === "unset") span.setStatus("ok");
|
|
782
|
+
return result;
|
|
783
|
+
} catch (err) {
|
|
784
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
785
|
+
span.setStatus("error", msg);
|
|
786
|
+
throw err;
|
|
787
|
+
} finally {
|
|
788
|
+
span.end();
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Set attributes on the active request span (if any). Convenience
|
|
794
|
+
* wrapper so user code doesn't have to null-check `ctx.span`
|
|
795
|
+
* themselves.
|
|
796
|
+
*/
|
|
797
|
+
setSpanAttributes(attrs: SpanAttributes): void {
|
|
798
|
+
this.span?.setAttributes(attrs);
|
|
799
|
+
}
|
|
634
800
|
}
|
|
635
801
|
|
|
636
802
|
/** Route context for error reporting */
|
package/src/filling/filling.ts
CHANGED
|
@@ -72,8 +72,17 @@ export interface LoaderOptions<T = unknown> {
|
|
|
72
72
|
|
|
73
73
|
/** Loader 캐시/ISR 옵션 */
|
|
74
74
|
export interface LoaderCacheOptions {
|
|
75
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* Fresh 캐시 유지 시간 (초). `maxAge` 의 별칭 — Next.js `revalidate`
|
|
77
|
+
* API 와 호환성을 유지한다. 0 이면 캐시 안 함.
|
|
78
|
+
*/
|
|
76
79
|
revalidate?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Phase 18.ζ — fresh 창을 지난 뒤 캐시를 계속 서빙할 stale-while-revalidate
|
|
82
|
+
* 창 길이 (초). 지정 시 `revalidate` 구간 후 이 기간만큼 STALE 응답을
|
|
83
|
+
* 즉시 반환하고 백그라운드에서 재생성한다.
|
|
84
|
+
*/
|
|
85
|
+
staleWhileRevalidate?: number;
|
|
77
86
|
/** 온디맨드 무효화 태그 */
|
|
78
87
|
tags?: string[];
|
|
79
88
|
}
|
package/src/index.ts
CHANGED
|
@@ -38,6 +38,38 @@ export { type GuardViolation } from "./guard";
|
|
|
38
38
|
export { type Severity } from "./guard";
|
|
39
39
|
export { Image, type ImageProps } from "./components/Image";
|
|
40
40
|
|
|
41
|
+
// Phase 18.θ — `Tracer` is exported by both `runtime/trace.ts` (the
|
|
42
|
+
// legacy lifecycle trace collector) and `observability/tracing.ts` (the
|
|
43
|
+
// new OTel tracer). `export *` from both yields TS2308 ambiguity, so
|
|
44
|
+
// explicitly re-export the new one as canonical. The legacy runtime
|
|
45
|
+
// tracer remains accessible via the `runtime/trace` subpath export
|
|
46
|
+
// (`createTracer`, `TraceEvent`, etc. are unchanged).
|
|
47
|
+
export {
|
|
48
|
+
Tracer,
|
|
49
|
+
ConsoleSpanExporter,
|
|
50
|
+
OtlpHttpSpanExporter,
|
|
51
|
+
encodeOtlpJson,
|
|
52
|
+
parseTraceparent,
|
|
53
|
+
formatTraceparent,
|
|
54
|
+
newTraceId,
|
|
55
|
+
newSpanId,
|
|
56
|
+
getActiveSpan,
|
|
57
|
+
runWithSpan,
|
|
58
|
+
injectTraceContext,
|
|
59
|
+
getTracer,
|
|
60
|
+
setTracer,
|
|
61
|
+
resetTracer,
|
|
62
|
+
createTracerFromConfig,
|
|
63
|
+
type Span,
|
|
64
|
+
type SpanAttributes,
|
|
65
|
+
type SpanExporter,
|
|
66
|
+
type SpanKind,
|
|
67
|
+
type SpanOptions,
|
|
68
|
+
type SpanStatus,
|
|
69
|
+
type TraceparentFields,
|
|
70
|
+
type TracerConfig,
|
|
71
|
+
} from "./observability/tracing";
|
|
72
|
+
|
|
41
73
|
// Consolidated Mandu namespace
|
|
42
74
|
import { ManduFilling, ManduContext, ManduFillingFactory, createSSEConnection } from "./filling";
|
|
43
75
|
import { createContract, defineHandler, defineRoute, createClient, contractFetch, createClientContract, querySchema, bodySchema, apiError } from "./contract";
|
|
@@ -35,3 +35,29 @@ export {
|
|
|
35
35
|
type HeapSnapshot,
|
|
36
36
|
type CacheName,
|
|
37
37
|
} from "./metrics";
|
|
38
|
+
// Phase 18.θ: OpenTelemetry-compatible request tracing
|
|
39
|
+
export {
|
|
40
|
+
Tracer,
|
|
41
|
+
ConsoleSpanExporter,
|
|
42
|
+
OtlpHttpSpanExporter,
|
|
43
|
+
encodeOtlpJson,
|
|
44
|
+
parseTraceparent,
|
|
45
|
+
formatTraceparent,
|
|
46
|
+
newTraceId,
|
|
47
|
+
newSpanId,
|
|
48
|
+
getActiveSpan,
|
|
49
|
+
runWithSpan,
|
|
50
|
+
injectTraceContext,
|
|
51
|
+
getTracer,
|
|
52
|
+
setTracer,
|
|
53
|
+
resetTracer,
|
|
54
|
+
createTracerFromConfig,
|
|
55
|
+
type Span,
|
|
56
|
+
type SpanAttributes,
|
|
57
|
+
type SpanExporter,
|
|
58
|
+
type SpanKind,
|
|
59
|
+
type SpanOptions,
|
|
60
|
+
type SpanStatus,
|
|
61
|
+
type TraceparentFields,
|
|
62
|
+
type TracerConfig,
|
|
63
|
+
} from "./tracing";
|