@axiomhq/tanstack-start

中文文档
0.2.0发布于 2026/06/29MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 4879

The official TanStack Start package for Axiom

原始使用文档
文档目录17 节
  1. Install
  2. Package Surface
  3. Root: shared TanStack Start core
  4. @axiomhq/tanstack-start/router
  5. @axiomhq/tanstack-start/react
  6. @axiomhq/tanstack-start/solid
  7. Logger Setup
  8. Shared Start Middleware
  9. Router Observer
  10. Client-Side Proxy Ingestion
  11. Client Error Boundaries
  12. React
  13. Solid
  14. Observability Coverage
  15. Examples
  16. Migration Note
  17. License

Axiom TanStack Start

The @axiomhq/tanstack-start package provides observability helpers for TanStack Start applications across React and Solid.

Install

npm install @axiomhq/js @axiomhq/logging @axiomhq/tanstack-start

Package Surface

Root: shared TanStack Start core

Use the root package for framework-neutral Start observability:

  • createAxiomRequestMiddleware
  • createAxiomFnMiddleware
  • createAxiomFnCorrelationMiddleware
  • createAxiomProxyHandler
  • createAxiomUncaughtErrorHandler
  • captureError
  • getLogLevelFromStatusCode
  • getStartErrorStatusCode
  • transformStartRequestSuccessResult
  • transformStartRequestErrorResult
  • transformStartFunctionSuccessResult
  • transformStartFunctionErrorResult
  • tanStackStartServerFormatters
  • tanStackStartClientFormatters
import {
  createAxiomFnMiddleware,
  createAxiomRequestMiddleware,
  tanStackStartServerFormatters,
} from '@axiomhq/tanstack-start';

@axiomhq/tanstack-start/router

Use the explicit router subpath for TanStack Router navigation and timing helpers:

  • observeTanStackRouter
  • tanStackRouterFormatters
import { observeTanStackRouter, tanStackRouterFormatters } from '@axiomhq/tanstack-start/router';

@axiomhq/tanstack-start/react

Use the React adapter to report errors from TanStack Router defaultErrorComponent, per-route errorComponent, or broader app-level boundaries:

import { createAxiomReactErrorHandler } from '@axiomhq/tanstack-start/react';

@axiomhq/tanstack-start/solid

Use the Solid adapter to report errors from TanStack Router defaultErrorComponent, per-route errorComponent, or broader app-level boundaries:

import { createAxiomSolidErrorHandler } from '@axiomhq/tanstack-start/solid';

Logger Setup

import { Logger, ConsoleTransport } from '@axiomhq/logging';
import { tanStackStartServerFormatters } from '@axiomhq/tanstack-start';
import { tanStackRouterFormatters } from '@axiomhq/tanstack-start/router';

export const routerLogger = new Logger({
  transports: [new ConsoleTransport()],
  formatters: tanStackRouterFormatters,
});

export const startLogger = new Logger({
  transports: [new ConsoleTransport()],
  formatters: tanStackStartServerFormatters,
});

TanStack Start helpers that receive a logger append axiom-tanstack-start/<version> to supported logging transports' X-Axiom-Client header.

Shared Start Middleware

The Start middleware APIs are framework-neutral because they build on TanStack Start core contracts.

import {
  createAxiomFnMiddleware,
  createAxiomRequestMiddleware,
} from '@axiomhq/tanstack-start';

export const requestMiddleware = [
  createAxiomRequestMiddleware(startLogger, {
    include: ['/api/*', '/_server/*'],
    exclude: ['/api/health'],
  }),
];

export const functionMiddleware = [
  createAxiomFnMiddleware(startLogger, {
    correlation: true,
  }),
];

Request and function middleware currently await logger.flush() before resolving. When we want non-blocking delivery later, the clean path is to introduce an injected waitUntil-style primitive instead of expanding the public config surface.

Use one function instrumentation path per server function. If createAxiomFnMiddleware is mounted globally through createStart({ functionMiddleware }), do not also attach it to individual server functions unless you intentionally want multiple log events for the same call.

To fully customize emitted fields or side effects, provide onSuccess / onError callbacks. When a callback is provided, the middleware skips default logging for that path. The transformStart*Result helpers are exported for users who want to keep the default message/report shape and add their own fields.

import {
  createAxiomRequestMiddleware,
  getLogLevelFromStatusCode,
  getStartErrorStatusCode,
  transformStartRequestErrorResult,
  transformStartRequestSuccessResult,
} from '@axiomhq/tanstack-start';

export const requestMiddleware = [
  createAxiomRequestMiddleware(startLogger, {
    onSuccess: async (data) => {
      const [message, report] = transformStartRequestSuccessResult(data);
      const logLevel = getLogLevelFromStatusCode(data.response.status);

      startLogger.log(logLevel, message, {
        ...report,
        tenant: data.request.headers.get('x-tenant-id'),
        region: data.request.headers.get('x-region'),
      });

      await startLogger.flush();
    },
    onError: async (data) => {
      const [message, report] = transformStartRequestErrorResult(data);
      const logLevel = getLogLevelFromStatusCode(getStartErrorStatusCode(data.error));

      startLogger.log(logLevel, message, {
        ...report,
        tenant: data.request.headers.get('x-tenant-id'),
        region: data.request.headers.get('x-region'),
      });

      await startLogger.flush();
    },
  }),
];
import {
  createAxiomFnMiddleware,
  transformStartFunctionErrorResult,
  transformStartFunctionSuccessResult,
} from '@axiomhq/tanstack-start';

export const functionMiddleware = [
  createAxiomFnMiddleware(startLogger, {
    correlation: true,
    onSuccess: async (data) => {
      const [message, report] = transformStartFunctionSuccessResult(data);

      startLogger.info(message, {
        ...report,
        requestHeaders: {
          tenant: data.context.context?.request?.headers.get('x-tenant-id'),
          region: data.context.context?.request?.headers.get('x-region'),
        },
      });

      await startLogger.flush();
    },
    onError: async (data) => {
      const [message, report] = transformStartFunctionErrorResult(data);

      startLogger.error(message, {
        ...report,
        requestHeaders: {
          tenant: data.context.context?.request?.headers.get('x-tenant-id'),
          region: data.context.context?.request?.headers.get('x-region'),
        },
      });

      await startLogger.flush();
    },
  }),
];

For simple side effects, callbacks can ignore logging entirely:

createAxiomRequestMiddleware(startLogger, {
  onSuccess: async (data) => {
    await analytics.track('request_complete', {
      path: new URL(data.request.url).pathname,
      statusCode: data.response.status,
    });
  },
});

Router Observer

import { observeTanStackRouter } from '@axiomhq/tanstack-start/router';

const observe = observeTanStackRouter(routerLogger, {
  source: 'tanstack-router-spa',
  performance: true,
});

const unsubscribe = observe(router);

observeTanStackRouter listens to onResolved by default. It only subscribes in the browser, so it is safe to call from router setup that also runs during SSR. The returned unsubscribe function can be used by HMR or custom router lifecycles.

Use the default source of tanstack-router for general Router instrumentation, or set a custom source such as tanstack-router-spa, tanstack-router-react, or tanstack-router-solid when you want to distinguish app/framework variants in Axiom.

When performance is enabled, the observer pairs router lifecycle events and emits route timing logs in addition to navigation logs.

Client-Side Proxy Ingestion

For browser logs, use ProxyTransport on the client and receive those events with createAxiomProxyHandler on the server. This keeps the Axiom token server-side while preserving the same logger API in client code.

// src/lib/axiom/client.ts
import { ConsoleTransport, Logger, ProxyTransport } from '@axiomhq/logging';
import type { Transport } from '@axiomhq/logging';
import { tanStackStartClientFormatters } from '@axiomhq/tanstack-start';
import { tanStackRouterFormatters } from '@axiomhq/tanstack-start/router';

function createBrowserTransports(): [Transport, ...Transport[]] {
  return [
    new ProxyTransport({ url: '/api/axiom' }),
    new ConsoleTransport({ prettyPrint: true }),
  ];
}

export const routerLogger = new Logger({
  transports: createBrowserTransports(),
  formatters: tanStackRouterFormatters,
});

export const clientLogger = new Logger({
  transports: createBrowserTransports(),
  formatters: tanStackStartClientFormatters,
});
// src/lib/axiom/server.ts
import { Axiom } from '@axiomhq/js';
import { AxiomJSTransport, ConsoleTransport, Logger } from '@axiomhq/logging';
import { tanStackStartServerFormatters } from '@axiomhq/tanstack-start';

const axiom = new Axiom({ token: process.env.AXIOM_TOKEN! });

export const startLogger = new Logger({
  transports: [
    new AxiomJSTransport({
      axiom,
      dataset: process.env.AXIOM_DATASET!,
    }),
    new ConsoleTransport({ prettyPrint: true }),
  ],
  formatters: tanStackStartServerFormatters,
});
// src/routes/api/axiom.ts
import { createFileRoute } from '@tanstack/react-router';
import { createAxiomProxyHandler } from '@axiomhq/tanstack-start';
import { startLogger } from '../../lib/axiom/server';

const proxyHandler = createAxiomProxyHandler(startLogger);

export const Route = createFileRoute('/api/axiom')({
  server: {
    handlers: {
      POST: ({ request }) => proxyHandler(request),
    },
  },
});

For Solid apps, use the same route pattern with createFileRoute from @tanstack/solid-router.

Client Error Boundaries

TanStack Start's built-in pattern is to catch route render and loader errors with TanStack Router defaultErrorComponent or route errorComponent. The adapters below are designed to plug into that boundary model first.

React

import { ErrorComponent, createRouter, type ErrorComponentProps } from '@tanstack/react-router';
import { useEffect } from 'react';
import { createAxiomReactErrorHandler } from '@axiomhq/tanstack-start/react';

const handleClientError = createAxiomReactErrorHandler(startLogger);

function RouterErrorBoundary({ error, reset }: ErrorComponentProps) {
  useEffect(() => {
    handleClientError(error);
  }, [error]);

  return <ErrorComponent error={error} />;
}

const router = createRouter({
  routeTree,
  defaultErrorComponent: RouterErrorBoundary,
});

Solid

import { ErrorComponent, createRouter, type ErrorComponentProps } from '@tanstack/solid-router';
import { onMount } from 'solid-js';
import { createAxiomSolidErrorHandler } from '@axiomhq/tanstack-start/solid';

const handleClientError = createAxiomSolidErrorHandler(startLogger);

function RouterErrorBoundary(props: ErrorComponentProps) {
  onMount(() => handleClientError(props.error, props.reset));
  return <ErrorComponent error={props.error} />;
}

const router = createRouter({
  routeTree,
  defaultErrorComponent: RouterErrorBoundary,
});

If you also want to catch client errors outside TanStack Router route boundaries, you can still use the same adapter helpers from a broader framework-level boundary.

Observability Coverage

SDK-backed:

  • request middleware
  • server-function middleware
  • request/function correlation
  • router navigation logs
  • router timing logs
  • proxy ingestion
  • uncaught server-entry capture
  • React and Solid client error-boundary helpers

App-pattern only:

  • health checks
  • debug headers
  • environment-specific logging policies

Examples

Migration Note

Router instrumentation is now intentionally explicit. Import router helpers from @axiomhq/tanstack-start/router instead of the root package.

License

MIT

版本与发布记录

@axiomhq/tanstack-start 共发布 4 个版本,首次发布于 2026/05/06;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.2.0latest2026/06/294 个月前
0.1.02026/05/125 个月前
0.0.1alpha2026/05/076 个月前
0.0.0placeholder2026/05/066 个月前

关于 @axiomhq/tanstack-start 的常见问题

@axiomhq/tanstack-start 是什么?

The official TanStack Start package for Axiom

如何安装 @axiomhq/tanstack-start?

在项目目录运行 npm install @axiomhq/tanstack-start,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@axiomhq/logging(0.3.0)、@tanstack/router-core(>=1)、@tanstack/start-client-core(>=1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@axiomhq/tanstack-start 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@axiomhq/tanstack-start 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@axiomhq/tanstack-start 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@axiomhq/tanstack-start 可以商用吗?

@axiomhq/tanstack-start 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@axiomhq/tanstack-start 的下载量有多少?

根据 npm 官方下载统计,@axiomhq/tanstack-start 在 2026/10/08 – 2026/11/06 这 30 天内被下载 4,879 次,日均约 163 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@axiomhq/tanstack-start 还在维护吗?

最新版本 0.2.0 发布于 2026/06/29(4 个月前);至今共发布 4 个版本,其中过去 12 个月发布了 4 个;首次发布于 2026/05/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。