{"id":13469556,"url":"https://github.com/axiomhq/next-axiom","last_synced_at":"2025-04-13T16:44:26.857Z","repository":{"id":37728518,"uuid":"486575553","full_name":"axiomhq/next-axiom","owner":"axiomhq","description":"The official Next.js library for Axiom.","archived":false,"fork":false,"pushed_at":"2025-02-20T13:34:49.000Z","size":15537,"stargazers_count":392,"open_issues_count":34,"forks_count":29,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-05T21:32:29.648Z","etag":null,"topics":["axiom","javascript","logging","nextjs","typescript","vercel","web-vitals"],"latest_commit_sha":null,"homepage":"https://axiom.co/vercel","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axiomhq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-28T11:59:37.000Z","updated_at":"2025-04-05T09:09:21.000Z","dependencies_parsed_at":"2024-02-28T16:41:38.147Z","dependency_job_id":"03810bed-7d42-4632-a9e8-17ad6a207d7d","html_url":"https://github.com/axiomhq/next-axiom","commit_stats":{"total_commits":423,"total_committers":19,"mean_commits":"22.263157894736842","dds":"0.36170212765957444","last_synced_commit":"793efba124d7c9ff8cbc094aec4ad6ec05a8a2bc"},"previous_names":["axiomhq/vercel-next"],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomhq%2Fnext-axiom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomhq%2Fnext-axiom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomhq%2Fnext-axiom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomhq%2Fnext-axiom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axiomhq","download_url":"https://codeload.github.com/axiomhq/next-axiom/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248748200,"owners_count":21155580,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["axiom","javascript","logging","nextjs","typescript","vercel","web-vitals"],"created_at":"2024-07-31T15:01:44.767Z","updated_at":"2025-04-13T16:44:26.833Z","avatar_url":"https://github.com/axiomhq.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Official Libraries"],"sub_categories":["SDKs and Libraries"],"readme":"# next-axiom\n\n\u003ca href=\"https://axiom.co\"\u003e\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark) and (min-width: 600px)\" srcset=\"https://axiom.co/assets/github/axiom-github-banner-light-vertical.svg\"\u003e\n  \u003csource media=\"(prefers-color-scheme: light) and (min-width: 600px)\" srcset=\"https://axiom.co/assets/github/axiom-github-banner-dark-vertical.svg\"\u003e\n  \u003csource media=\"(prefers-color-scheme: dark) and (max-width: 599px)\" srcset=\"https://axiom.co/assets/github/axiom-github-banner-light-horizontal.svg\"\u003e\n  \u003cimg alt=\"Axiom.co banner\" src=\"https://axiom.co/assets/github/axiom-github-banner-dark-horizontal.svg\" align=\"right\"\u003e\n\u003c/picture\u003e\n\u003c/a\u003e\n\u0026nbsp;\n\n[![build](https://img.shields.io/github/actions/workflow/status/axiomhq/next-axiom/ci.yml?branch=main\u0026ghcache=unused)](https://github.com/axiomhq/next-axiom/actions?query=workflow%3ACI)\n[![Latest release](https://img.shields.io/github/release/axiomhq/next-axiom.svg)](https://github.com/axiomhq/next-axiom/releases/latest)\n[![License](https://img.shields.io/github/license/axiomhq/next-axiom.svg?color=blue)](https://opensource.org/licenses/MIT)\n\n[Axiom](https://axiom.co) unlocks observability at any scale.\n\n- **Ingest with ease, store without limits:** Axiom’s next-generation datastore enables ingesting petabytes of data with ultimate efficiency. Ship logs from Kubernetes, AWS, Azure, Google Cloud, DigitalOcean, Nomad, and others.\n- **Query everything, all the time:** Whether DevOps, SecOps, or EverythingOps, query all your data no matter its age. No provisioning, no moving data from cold/archive to “hot”, and no worrying about slow queries. All your data, all. the. time.\n- **Powerful dashboards, for continuous observability:** Build dashboards to collect related queries and present information that’s quick and easy to digest for you and your team. Dashboards can be kept private or shared with others, and are the perfect way to bring together data from different sources.\n\nFor more information, check out the [official documentation](https://axiom.co/docs).\n\n## Introduction\n\nThis library allows you to send Web Vitals as well as structured logs from your Next.js application to Axiom.\n\n\u003e Using the Pages Router? Use version `0.*` which continues to receive security patches. Here's the [README for `0.x`](https://github.com/axiomhq/next-axiom/blob/v0.x/README.md).\n\n## Prerequisites\n\n- [Create an Axiom account](https://app.axiom.co/).\n- [Create a dataset in Axiom](/docs/reference/datasets) where you send your data.\n- [Create an API token in Axiom](/docs/reference/tokens) with permissions to create, read, update, and delete datasets.\n- [A new or existing Next.js app](https://nextjs.org/).\n\n## Install next-axiom\n\n1. In your terminal, go to the root folder of your Next.js app, and then run `npm install --save next-axiom` to install the latest version of next-axiom.\n2. Add the following environment variables to your Next.js app. For more information, see the [Vercel documentation](https://vercel.com/docs/projects/environment-variables).\n    - `NEXT_PUBLIC_AXIOM_DATASET` is the name of the Axiom dataset where you want to send data.\n    - `NEXT_PUBLIC_AXIOM_TOKEN` is the Axiom API token you have generated.\n3. In the `next.config.ts` file, wrap your Next.js configuration in `withAxiom`:\n\n```js\nconst { withAxiom } = require('next-axiom');\n\nmodule.exports = withAxiom({\n  // Your existing configuration.\n});\n```\n\n## Capture traffic requests\n\nTo capture traffic requests, create a `middleware.ts` file in the root folder of your Next.js app:\n\n```ts\nimport { Logger } from 'next-axiom'\nimport { NextResponse } from 'next/server'\nimport type { NextFetchEvent, NextRequest } from 'next/server'\n\nexport async function middleware(request: NextRequest, event: NextFetchEvent) {\n    const logger = new Logger({ source: 'middleware' }); // traffic, request\n    logger.middleware(request)\n\n    event.waitUntil(logger.flush())\n    return NextResponse.next()\n\n// For more information, see Matching Paths below\nexport const config = {\n}\n```\n\n`logger.middleware` accepts a configuration object as the second argument. This object can contain the following properties:\n\n- `logRequestDetails`: Accepts a boolean or an array of keys. If you pass `true`, it will add all the request details to the log (method, URL, headers, etc.). If you pass an array of strings, it will only add the specified keys. See [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request/url) and [NextRequest](https://nextjs.org/docs/app/api-reference/functions/next-request) for documentation on the available keys. If `logRequestDetails` is enabled the function will return a Promise that needs to be awaited.\n\n```ts\nexport async function middleware(request: NextRequest, event: NextFetchEvent) {\n  const logger = new Logger({ source: \"middleware\" });\n  await logger.middleware(request, { logRequestDetails: [\"body\", \"nextUrl\"] });\n\n  event.waitUntil(logger.flush());\n  return NextResponse.next();\n}\n```\n\n## Web Vitals\n\nTo send Web Vitals to Axiom, add the `AxiomWebVitals` component from next-axiom to the `app/layout.tsx` file:\n\n```ts\nimport { AxiomWebVitals } from 'next-axiom';\n\nexport default function RootLayout() {\n  return (\n    \u003chtml\u003e\n      ...\n      \u003cAxiomWebVitals /\u003e\n      \u003cdiv\u003e...\u003c/div\u003e\n    \u003c/html\u003e\n  );\n}\n```\n\nWeb Vitals are only sent from production deployments.\n\n## Logs\n\nSend logs to Axiom from different parts of your app. Each log function call takes a message and an optional `fields` object.\n\n```ts\nlog.debug('Login attempt', { user: 'j_doe', status: 'success' }); // Results in {\"message\": \"Login attempt\", \"fields\": {\"user\": \"j_doe\", \"status\": \"success\"}}\nlog.info('Payment completed', { userID: '123', amount: '25USD' });\nlog.warn('API rate limit exceeded', { endpoint: '/users/1', rateLimitRemaining: 0 });\nlog.error('System Error', { code: '500', message: 'Internal server error' });\n```\n\n### Route handlers\n\nWrap your route handlers in `withAxiom` to add a logger to your request and log exceptions automatically:\n\n```ts\nimport { withAxiom, AxiomRequest } from 'next-axiom';\n\nexport const GET = withAxiom((req: AxiomRequest) =\u003e {\n  req.log.info('Login function called');\n\n  // You can create intermediate loggers\n  const log = req.log.with({ scope: 'user' });\n  log.info('User logged in', { userId: 42 });\n\n  return NextResponse.json({ hello: 'world' });\n});\n```\n\nRoute handlers accept a configuration object as the second argument. This object can contain the following properties:\n\n- `logRequestDetails`: Accepts a boolean or an array of keys. If you pass `true`, it will add all the request details to the log (method, URL, headers, etc.). If you pass an array of strings, it will only add the specified keys. See [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request/url) and [NextRequest](https://nextjs.org/docs/app/api-reference/functions/next-request) for documentation on the available keys.\n\n\n- `NotFoundLogLevel`: Override the log level for NOT_FOUND errors. Defaults to `warn`.\n\n- `RedirectLogLevel`: Override the log level for NEXT_REDIRECT errors. Defaults to `info`.\n\n\nConfig example: \n\n```ts\nexport const GET = withAxiom(\n  async () =\u003e {\n    return new Response(\"Hello World!\");\n  },\n  { \n    logRequestDetails: ['body', 'nextUrl'], // { logRequestDetails: true } is also valid\n    NotFoundLogLevel: 'error',\n    RedirectLogLevel: 'debug',\n  }\n);\n```\n\n### Client components\n\nTo send logs from client components, add `useLogger` from next-axiom to your component:\n\n```ts\n'use client';\nimport { useLogger } from 'next-axiom';\n\nexport default function ClientComponent() {\n  const log = useLogger();\n  log.debug('User logged in', { userId: 42 });\n  return \u003ch1\u003eLogged in\u003c/h1\u003e;\n}\n```\n\n### Server components\n\nTo send logs from server components, add `Logger` from next-axiom to your component, and call flush before returning:\n\n```ts\nimport { Logger } from 'next-axiom';\n\nexport default async function ServerComponent() {\n  const log = new Logger();\n  log.info('User logged in', { userId: 42 });\n\n  // ...\n\n  await log.flush();\n  return \u003ch1\u003eLogged in\u003c/h1\u003e;\n}\n```\n\n### Log levels\n\nThe log level defines the lowest level of logs sent to Axiom. Choose one of the following levels (from lowest to highest):\n\n- `debug` is the default setting. It means that you send all logs to Axiom.\n- `info`\n- `warn`\n- `error` means that you only send the highest-level logs to Axiom.\n- `off` means that you don't send any logs to Axiom.\n\nFor example, to send all logs except for debug logs to Axiom:\n\n```sh\nexport NEXT_PUBLIC_AXIOM_LOG_LEVEL=info\n```\n\n## Capture errors\n\nTo capture routing errors, use the [error handling mechanism of Next.js](https://nextjs.org/docs/app/building-your-application/routing/error-handling):\n\n1. Go to the `app` folder.\n2. Create an `error.tsx` file.\n3. Inside your component function, add `useLogger` from next-axiom to send the error to Axiom. For example:\n\n```ts\n\"use client\";\n\nimport { useLogger, LogLevel } from \"next-axiom\";\nimport { usePathname } from \"next/navigation\";\n\nexport default function ErrorPage({\n  error,\n}: {\n  error: Error \u0026 { digest?: string };\n}) {\n  const pathname = usePathname()\n  const log = useLogger({ source: \"error.tsx\" });\n  let status =  error.message == 'Invalid URL' ? 404 : 500;\n\n  log.logHttpRequest(\n    LogLevel.error,\n    error.message,\n    {\n      host: window.location.href,\n      path: pathname,\n      statusCode: status,\n    },\n    {\n      error: error.name,\n      cause: error.cause,\n      stack: error.stack,\n      digest: error.digest,\n    },\n  );\n\n  return (\n    \u003cdiv className=\"p-8\"\u003e\n      Ops! An Error has occurred:{\" \"}\n      \u003cp className=\"text-red-400 px-8 py-2 text-lg\"\u003e`{error.message}`\u003c/p\u003e\n      \u003cdiv className=\"w-1/3 mt-8\"\u003e\n        \u003cNavTable /\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## Upgrade to the App Router\n\nnext-axiom switched to support the App Router starting with version 1.0. If you are upgrading a Pages Router app with next-axiom v0.x to the App Router, you will need to make the following changes:\n\n- Upgrade next-axiom to version 1.0.0 or higher\n- Make sure that exported variables has `NEXT_PUBLIC_` prefix, e.g: `NEXT_PUBLIC_AXIOM_TOKEN`\n- Use `useLogger` hook in client components instead of `log` prop\n- For server side components, you will need to create an instance of `Logger` and flush the logs before component returns.\n- For web-vitals, remove `reportWebVitals()` and instead add the `AxiomWebVitals` component to your layout.\n\n## FAQ\n\n### How can I send logs from Vercel preview deployments?\n\nThe Axiom Vercel integration sets up an environment variable called `NEXT_PUBLIC_AXIOM_INGEST_ENDPOINT`, which by default is only enabled for the production environment. To send logs from preview deployments, go to your site settings in Vercel and enable preview deployments for that environment variable.\n\n### How can I extend the logger?\n\nYou can use `log.with` to create an intermediate logger, for example:\n\n```typescript\nconst logger = userLogger().with({ userId: 42 });\nlogger.info('Hi'); // will ingest { ..., \"message\": \"Hi\", \"fields\" { \"userId\": 42 }}\n```\n\n## License\n\nDistributed under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxiomhq%2Fnext-axiom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxiomhq%2Fnext-axiom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxiomhq%2Fnext-axiom/lists"}