feat: add diagnostics and telemetry runtime

This commit is contained in:
donghyeon-ka
2026-07-26 16:42:27 +09:00
parent 2fa0baa577
commit 5173b6c8d6
43 changed files with 1760 additions and 116 deletions
+2
View File
@@ -1,5 +1,6 @@
import { createRoot } from "react-dom/client";
import { recordBootFailure } from "../adapters/diagnostics/bounded-diagnostics.js";
import { BootErrorShell } from "../presentation/boundaries/boot-error-shell.jsx";
import { createRuntimeComposition } from "./create-runtime-composition.js";
import { initializeColorScheme } from "./initialize-color-scheme.js";
@@ -27,6 +28,7 @@ async function boot() {
? error.safe
: { supportReference: "boot:unknown" };
recordBootFailure(error, safe);
root.render(<BootErrorShell {...safe} />);
}
}
+27 -6
View File
@@ -4,6 +4,7 @@ import {
createUnavailableSessionAdapter,
} from "../adapters/auth/external-session-adapter.js";
import { createHttpClient } from "../adapters/http/client.js";
import { createDiagnosticsAdapter } from "../adapters/diagnostics/bounded-diagnostics.js";
import {
createQueryClient,
} from "../adapters/query-cache/tanstack-query-cache.js";
@@ -53,6 +54,8 @@ function storageOrUndefined(value) {
* fetcher?: typeof fetch,
* clock?: import("../application/ports/clock-port.js").ClockPort,
* scheduler?: Parameters<typeof createHttpClient>[0]["scheduler"]
* diagnostics?: Parameters<typeof createHttpClient>[0]["diagnostics"],
* telemetry?: Parameters<typeof createHttpClient>[0]["telemetry"]
* }} context
*/
export function createRuntimeHttpClient(context, contract = {}) {
@@ -64,6 +67,8 @@ export function createRuntimeHttpClient(context, contract = {}) {
fetcher: context.fetcher,
clock: context.clock,
scheduler: context.scheduler,
diagnostics: context.diagnostics,
telemetry: context.telemetry,
...contract,
});
}
@@ -86,15 +91,28 @@ export async function createRuntimeAdapters(context) {
: externalOwner
? createExternalAuthSessionAdapter(externalOwner)
: createUnavailableSessionAdapter();
const queryClient = createQueryClient();
const storage = createBrowserStorageAdapter({
localStorage: storageOrUndefined(host.localStorage),
sessionStorage: storageOrUndefined(host.sessionStorage),
});
const diagnostics = createDiagnosticsAdapter();
const telemetry = createTelemetryAdapter({
enabled: config.TELEMETRY_ENABLED,
endpoint: config.TELEMETRY_ENDPOINT,
fetcher: context.fetcher,
onDrop(event) {
const attributes =
event.attributes && typeof event.attributes === "object"
? event.attributes
: {};
diagnostics.record({
level: "warn",
eventId: "telemetry.delivery.dropped",
context: /** @type {Record<string, unknown>} */ (attributes),
});
},
});
const queryClient = createQueryClient({ diagnostics });
const storage = createBrowserStorageAdapter({
localStorage: storageOrUndefined(host.localStorage),
sessionStorage: storageOrUndefined(host.sessionStorage),
diagnostics,
});
const releaseInfo = Object.freeze({
async getCurrent() {
@@ -125,6 +143,8 @@ export async function createRuntimeAdapters(context) {
runtime: context.runtime,
authSession,
fetcher: context.fetcher,
diagnostics,
telemetry,
},
contract,
),
@@ -134,7 +154,8 @@ export async function createRuntimeAdapters(context) {
outputPorts: Object.freeze({
session: authSession,
preferences: storage,
diagnostics: telemetry,
diagnostics,
telemetry,
releaseInfo,
navigation,
}),