Skip to content

Repository files navigation

@komerce/telemetry

Cross-framework observability (errors, logs, breadcrumbs) with typed providers, explicit init, and tree-shakeable subpaths.

One setup flow: createTelemetry in config → telemetry.initClient() / initServer() in entries → bindClient / bindServer. See docs/FLOW.md. Konsep provider, adapter, dan createTelemetry: docs/KONSEP.md.

Install

npm install @komerce/telemetry

Install optional peers for your stack (react, react-router, vue, @angular/core) and monitoring (@sentry/browser, @sentry/node, …) only when needed.

Quick start

Vue 2:

import { createTelemetry } from "@komerce/telemetry/setup";
import { Console } from "@komerce/telemetry/providers/console";
import { vue2 } from "@komerce/telemetry/adapter/vue2";
import { Sentry } from "@komerce/telemetry/providers/sentry/client";

export const telemetry = createTelemetry({
  platform: vue2,
  appId: "shop",
  runtime: "client",
  providers: [Console(), Sentry({ dsn: "…" })],
});

React Router:

import { createTelemetry } from "@komerce/telemetry/setup";
import { Console } from "@komerce/telemetry/providers/console";
import { reactRouter } from "@komerce/telemetry/adapter/react-router";
import { Sentry } from "@komerce/telemetry/providers/sentry/client";
import "@komerce/telemetry/providers/sentry/react-router";

// telemetry.client.ts — import only from entry.client
export const telemetry = createTelemetry({
  platform: reactRouter,
  appId: "shop",
  runtime: "client",
  providers: [
    Console(),
    Sentry({ dsn: import.meta.env.VITE_SENTRY_DSN }),
  ],
});

// telemetry.server.ts — import only from entry.server
// import { Sentry } from "@komerce/telemetry/providers/sentry/server";

entry.client.ts:

import { bindClient } from "@komerce/telemetry/client";
import { telemetry } from "./telemetry.config";

const init = await telemetry.initClient();
init.listenUnhandledErrors();
bindClient(init.api);

Feature code (all providers on the plan for that runtime):

import { log, captureError } from "@komerce/telemetry/client";

Sentry only (same bindClient(init.api) — does not call Console/Http):

import { log, captureError } from "@komerce/telemetry/client/sentry";

Server: @komerce/telemetry/server and @komerce/telemetry/server/sentry after bindServer(init.api).

Omit providers → default Console() in the plan. captureGlobalErrors defaults to false — call listenUnhandledErrors() explicitly.

See docs/FLOW.md for the full bootstrap diagram. Reference apps: examples/react-router-ssr.

Contributing a new backend: docs/ADDING_A_PROVIDER.md.

Optional providers (import only what you use):

import { Http } from "@komerce/telemetry/providers/http";
import { Callback } from "@komerce/telemetry/providers/callback";
import { Sentry } from "@komerce/telemetry/providers/sentry/client";
// Server: import from "@komerce/telemetry/providers/sentry/server"

Subpaths

Import Use
@komerce/telemetry/setup createTelemetry + types (framework-agnostic)
@komerce/telemetry/providers/console Console provider
@komerce/telemetry/adapter/vue2 vue2 platform + Vue 2 installers
@komerce/telemetry/adapter/vue3 vue3 platform + Vue 3 installers
@komerce/telemetry/adapter/react-router reactRouter platform + RR UI helpers
@komerce/telemetry/client bindClient, log, captureError, … → all providers
@komerce/telemetry/client/sentry Same bind — log, captureError, … → Sentry only
@komerce/telemetry/server bindServer, server runtime facade → all providers
@komerce/telemetry/server/sentry Same bind — Sentry provider only
@komerce/telemetry/providers/sentry/client Sentry plugin (browser graph only)
@komerce/telemetry/providers/sentry/server Sentry plugin (Node graph only)
@komerce/telemetry/providers/sentry/react-router RR Sentry hydration / server instrumentations
@komerce/telemetry/react-router/adapter RouteErrorReporter, SSR helpers (alias of adapter/react-router)

Root @komerce/telemetry re-exports core setup for convenience; prefer subpaths in app bundles.

React Router + Sentry

Import @komerce/telemetry/providers/sentry/react-router in config (registers RR Sentry loaders + init extensions). Entry stays minimal — downstream modules read init.extensions when needed:

// hydration.client.tsx — not entry.client.ts
import { init } from "./entry.client";
init.extensions.sentry?.reactRouter?.hydrationProps;
await init.extensions.sentry?.reactRouter?.initLibrarySentry?.();

Direct helpers (bypassing init.extensions):

import { getReactRouterSentryHydrationProps } from "@komerce/telemetry/providers/sentry/react-router";

Adapters (explicit client)

import { RouteErrorReporter } from "@komerce/telemetry/react-router/adapter";

<RouteErrorReporter client={init.api} />

Vue / Angular installers require client: TelemetryClient — no global fallback.

Providers

  • Console / Http / Callback — core plugins, schema in schema/provider-core.ts
  • Sentry — plugin in providers/sentry/, schema in providers/sentry/schema.ts, optional @sentry/* peers
  • Injected SDK: Sentry({ inject: { client: SentryBrowser, server: SentryNode } }) registers on the plan's SentryClientRegistry (no global Symbol.for)
  • Split DSN/settings: Sentry({ client: { dsn: "…" }, server: { dsn: "…" }, features: { … } }) expands to two providers on the plan

Vue 2 / Webpack 4

Webpack 4 does not read package.json exports. After npm run build, the package emits filesystem shims (e.g. client.js, adapter/vue2.js) that re-export built files under dist/ so subpath imports resolve without aliases.

If you still hit ESM parse errors in node_modules, add to vue.config.js:

module.exports = {
  transpileDependencies: ["@komerce/telemetry"],
};

For stubborn setups, alias subpaths to the matching dist/**/*.cjs file (see package.json exports require targets).

Scripts

npm run build          # tsup + auto-generate webpack 4 shims
npm run typecheck
npm test
npm run test:bundle   # shim coverage + client facade + per-entry static graph smoke

License

MIT

About

Cross-framework frontend observability (errors, logs, breadcrumbs) with provider schema

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages