Git Product home page Git Product logo

next-axiom's Introduction

next-axiom

Axiom.co banner  

build Latest release License

Axiom unlocks observability at any scale.

  • 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.
  • 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.
  • 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.

For more information, check out the official documentation.

Introduction

This library allows you to send Web Vitals as well as structured logs from your Next.js application to Axiom.

Using the Pages Router? Use version 0.* which continues to receive security patches. Here's the README for 0.x.

Prerequisites

Install next-axiom

  1. 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.
  2. Add the following environment variables to your Next.js app. For more information, see the Vercel documentation.
    • NEXT_PUBLIC_AXIOM_DATASET is the name of the Axiom dataset where you want to send data.
    • NEXT_PUBLIC_AXIOM_TOKEN is the Axiom API token you have generated.
  3. In the next.config.ts file, wrap your Next.js configuration in withAxiom:
const { withAxiom } = require('next-axiom');

module.exports = withAxiom({
  // Your existing configuration.
});

Capture traffic requests

To capture traffic requests, create a middleware.ts file in the root folder of your Next.js app:

import { Logger } from 'next-axiom'
import { NextResponse } from 'next/server'
import type { NextFetchEvent, NextRequest } from 'next/server'

export async function middleware(request: NextRequest, event: NextFetchEvent) {
    const logger = new Logger({ source: 'middleware' }); // traffic, request
    logger.middleware(request)

    event.waitUntil(logger.flush())
    return NextResponse.next()

// For more information, see Matching Paths below
export const config = {
}

Web Vitals

To send Web Vitals to Axiom, add the AxiomWebVitals component from next-axiom to the app/layout.tsx file:

import { AxiomWebVitals } from 'next-axiom';

export default function RootLayout() {
  return (
    <html>
      ...
      <AxiomWebVitals />
      <div>...</div>
    </html>
  );
}

Web Vitals are only sent from production deployments.

Logs

Send logs to Axiom from different parts of your app. Each log function call takes a message and an optional fields object.

log.debug('Login attempt', { user: 'j_doe', status: 'success' }); // Results in {"message": "Login attempt", "fields": {"user": "j_doe", "status": "success"}}
log.info('Payment completed', { userID: '123', amount: '25USD' });
log.warn('API rate limit exceeded', { endpoint: '/users/1', rateLimitRemaining: 0 });
log.error('System Error', { code: '500', message: 'Internal server error' });

Route handlers

Wrap your route handlers in withAxiom to add a logger to your request and log exceptions automatically:

import { withAxiom, AxiomRequest } from 'next-axiom';

export const GET = withAxiom((req: AxiomRequest) => {
  req.log.info('Login function called');

  // You can create intermediate loggers
  const log = req.log.with({ scope: 'user' });
  log.info('User logged in', { userId: 42 });

  return NextResponse.json({ hello: 'world' });
});

Client components

To send logs from client components, add useLogger from next-axiom to your component:

'use client';
import { useLogger } from 'next-axiom';

export default function ClientComponent() {
  const log = useLogger();
  log.debug('User logged in', { userId: 42 });
  return <h1>Logged in</h1>;
}

Server components

To send logs from server components, add Logger from next-axiom to your component, and call flush before returning:

import { Logger } from 'next-axiom';

export default async function ServerComponent() {
  const log = new Logger();
  log.info('User logged in', { userId: 42 });

  // ...

  await log.flush();
  return <h1>Logged in</h1>;
}

Log levels

The log level defines the lowest level of logs sent to Axiom. Choose one of the following levels (from lowest to highest):

  • debug is the default setting. It means that you send all logs to Axiom.
  • info
  • warn
  • error means that you only send the highest-level logs to Axiom.
  • off means that you don't send any logs to Axiom.

For example, to send all logs except for debug logs to Axiom:

export NEXT_PUBLIC_AXIOM_LOG_LEVEL=info

Capture errors

To capture routing errors, use the error handling mechanism of Next.js:

  1. Go to the app folder.
  2. Create an error.tsx file.
  3. Inside your component function, add useLogger from next-axiom to send the error to Axiom. For example:
"use client";

import { LogLevel } from "@/next-axiom/logger";
import { useLogger } from "next-axiom";
import { usePathname } from "next/navigation";

export default function ErrorPage({
  error,
}: {
  error: Error & { digest?: string };
}) {
  const pathname = usePathname()
  const log = useLogger({ source: "error.tsx" });
  let status =  error.message == 'Invalid URL' ? 404 : 500;

  log.logHttpRequest(
    LogLevel.error,
    error.message,
    {
      host: window.location.href,
      path: pathname,
      statusCode: status,
    },
    {
      error: error.name,
      cause: error.cause,
      stack: error.stack,
      digest: error.digest,
    },
  );

  return (
    <div className="p-8">
      Ops! An Error has occurred:{" "}
      <p className="text-red-400 px-8 py-2 text-lg">`{error.message}`</p>
      <div className="w-1/3 mt-8">
        <NavTable />
      </div>
    </div>
  );
}

Upgrade to the App Router

next-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:

  • Upgrade next-axiom to version 1.0.0 or higher
  • Make sure that exported variables has NEXT_PUBLIC_ prefix, e.g: NEXT_PUBLIC_AXIOM_TOKEN
  • Use useLogger hook in client components instead of log prop
  • For server side components, you will need to create an instance of Logger and flush the logs before component returns.
  • For web-vitals, remove reportWebVitals() and instead add the AxiomWebVitals component to your layout.

FAQ

How can I send logs from Vercel preview deployments?

The 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.

How can I extend the logger?

You can use log.with to create an intermediate logger, for example:

const logger = userLogger().with({ userId: 42 });
logger.info('Hi'); // will ingest { ..., "message": "Hi", "fields" { "userId": 42 }}

License

Distributed under the MIT License.

next-axiom's People

Contributors

bahlo avatar benjamin-guibert avatar bensigo avatar c-ehrlich avatar dependabot[bot] avatar dorbn4 avatar github-actions[bot] avatar haydn avatar imlunahey avatar izayl avatar kevinehosford avatar lufycz avatar lukasmalkmus avatar maxkostow avatar nikita-tech-writer avatar schehata avatar thecraftman avatar tothmano avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

next-axiom's Issues

next-axiom transports

next-axiom advanced configuration support

This researches the different ways to improve the package's configuration, allowing the user to make use of different transports for example, in the same app.

Configuration

  • should be able to import helper functions from axiom kit
import { Logger } from 'next-axiom';
import { Axiom as AxiomTransport } from '@axiomhq/js`
import { isVercel, isBrowser, isNode, isEdge, EventsBatch, ConsoleTransport, FetchTransport, autoDetectConfig } from '@axiomhq/kit';
  • An automatic config reader can auto detect config based on environment
const log = new Logger(autoDetectConfig());

const autoDetectConfig = () => {
    
    const transport = new FetchTransport() // ConsoleTransport()

    
    if (isVercel) {
        return VercelConfig({
            token: process.env.AXIOM_TOKEN,
            dataset: process.env.AXIOM_DATASET,
            edge: {
                transport: ConsoleTransport,
            },
        })
    }

    return {
        token: process.env.AXIOM_TOKEN,
        dataset: process.env.AXIOM_DATASET,
        transport: AxiomTransport()
    }
}
  • configuration could mixed and overridden
const log = new Logger({
    token: 'XAT-123',
    dataset: 'something',
    adapter: new FetchTransport(),
});

const log2 = new Logger({
    ...autoDetectConfig(),
    transport: new ConsoleTransport({ pretty: false }),
});
  • auto configure based on platform
const log = new Logger(VercelConfig())

const VercelConfig = (override) => {
    // get url and token from integration env
    const url = process.env.NEXT_PUBLIC_AXIOM_INGEST_URL;
    const token = process.env.NEXT_PUBLIC_AXIOM_TOKEN;
    const dataset = "vercel";

    if (isBrowser) {
        return { transport: new FetchTransport({ token, dataset })}
    } else if (isEdge || isNode) {
        return { transport: new ConsoleTransport() }
    }
}

passing a logger to route handlers:

loggerConfig = {
    transport: new ConsoleTransport(),
}

const handler = (request) => { ... }

export const Post = withAxiom(handler, loggerConfig)

ConsoleTransport

The ConsoleTransport would be a great choice for apps that have vercel or netlify integration because then functions can just log every thing to the console without waiting for fetch to finish. This would save time and avoid errors on edge and lambda functions.

The downside is the console log limit per platform, for example, vercel's 4kb limit. maybe the ConsoleTransport could have a fallback method, to queue to fetch. or vice-verse, the Fetch transport would queue stuff, but if its below the limit and integration is active, then it just prints to console instead of queuing.

`reportWebVitals` reports incorrect route

Since reportWebVitals in next-axiom relies on window.__NEXT_DATA__?.page, the route that's sent to Axiom isn't updated when user performs a client-side navigation.

Example:

Nagranie.z.ekranu.2022-08-12.o.15.23.27.mov

As you can see, client-side (via <Link/>) navigation doesn't affect the route being sent to Axiom. Only after doing a hard reload the correct route is being picked up and sent to Axiom.

Sending Client Logs on other Platforms than Vercel

Hi,

we are using NextJS both on Vercel and on self-hosted systems. Sending both Client and Server Logs on Vercel works without problem. Thank you for that :)

On our self-hosted system we only receive the Server Logs from our api routes and middleware. Is there a way, or will there be a way in the future to also support client logs on other platforms?

Looking through the code, I don't see a way other than leaking the Secret to the client. Could we maybe add an /api/_logs endpoint which would redirect the client logs to the axiom cloud?

Getting occasional 404s for _axiom/web-vitals call on PROD

Noticed my production dashboard is showing a small percentage of 404 errors for the web vitals call. Any idea what's causing this and how I can patch it? I do see the web vitals working since there are a number of successful calls for most users.

Secondly, is there a way to get this call to work locally?

API resolved without sending a response with intermediate logger using `req.log.with`

I am using Next.js 13.3.0 along with version 0.17.0 of the next-axiom library to handle API routing in my application. I have created an intermediate logger using req.log.with to customize the logs in my API endpoint handlers. However, I am experiencing an issue where responses are not sent correctly and warnings are generated in the console.

The issue seems to be related to the use of req.log.with, as when I use it, responses are not sent correctly and requests are left hanging, resulting in the following warning in the console:

"API resolved without sending a response for /api/[endpoint], this may result in stalled requests."

This issue only occurs when I use req.log.with, as if I only use req.log.info for logging, no warnings are generated and responses are sent correctly.

I have found a workaround by adding the following config object to my API route:

export const config = {
  api: {
    externalResolver: true,
  },
}

This seems to resolve the issue, but I'm not sure if it's the proper implementation or not, as there is no information available in the documentation of next-axiom.

Here are the versions I am using:

Next.js: 13.3.0
next-axiom: 0.17.0
Steps to reproduce the issue:

Create an intermediate logger using req.log.with in an API endpoint handler in Next.js.
Make a request to that endpoint from a client.
Observe that the response is not sent correctly and warnings are generated in the console.

eg:

import type { NextApiResponse } from 'next'
import { AxiomAPIRequest, withAxiom } from 'next-axiom'

async function handler(req: AxiomAPIRequest, res: NextApiResponse) {
  const logger = req.log.with({
    timestamp: new Date(Date.now()).toISOString(),
    env: process.env.NODE_ENV,
    node_version: process.version,
  })
  logger.info('test', {
    data: { url: req.url, method: req.method },
  })
  res.status(200).json({ message: 'Message sent' })
}

export default withAxiom(handler)

I was trying to create a function createLogger:

eg:

import { Logger } from 'next-axiom'
import pckJson from 'package.json'

function createLogger(logger: Logger) {
  const log = logger.with({
    timestamp: new Date(Date.now()).toISOString(),
    env: process.env.NODE_ENV,
    node_version: process.version,
    project_version: pckJson.version,
    next_version: pckJson.dependencies.next,
  })
  return log
}

export { createLogger }

Ability to flush logs or disable buffer for tests

In logger.ts, all log.<level> calls pass through throttledSendLogs:

throttledSendLogs = throttle(this.sendLogs, 1000);

which batches up calls to flush logs every 1 second.

When unit testing an application that has calls using the axiom logger, this leads to failures in e.g. jest because the calls to console.log (no environment variables specified) happen after the tests have finished:

  ●  Cannot log after tests are done. Did you forget to wait for something async in your test?
    Attempted to log "info - My log message here".

      at console.log (node_modules/.pnpm/@[email protected]/node_modules/@jest/console/build/CustomConsole.js:172:10)
      at prettyPrint (node_modules/.pnpm/[email protected][email protected]/node_modules/next-axiom/src/logger.ts:200:15)
      at node_modules/.pnpm/[email protected][email protected]/node_modules/next-axiom/src/logger.ts:115:38

I'm interested in a way to either:

  • Manually flush the buffer in an afterAll() hook
  • Disable buffering entirely (via environment variables or otherwise)

So that I can use this logger without having to sleep(1000) in all my tests.

Looking at the source code I didn't see any obvious way to accomplish this without adding some new code. Do you all have thoughts on a preferred method to make this work?

EBADPLATFORM with M1 Mac

I've been using next-axiom with my m1 mac for local development that I deploy to vercel via pushing code to branches/main in github. This was working until I had to delete the node_module folder and reinstall the packages and now it says it cannot install it on an m1 mac. I don't recall having any issues installing it approximately a week ago. Is there something I'm missing?

npm ERR! code EBADPLATFORM
npm ERR! notsup Unsupported platform for @next/[email protected]: wanted {"os":"linux","arch":"x64"} (current: {"os":"darwin","arch":"arm64"})
npm ERR! notsup Valid OS: linux
npm ERR! notsup Valid Arch: x64
npm ERR! notsup Actual OS: darwin
npm ERR! notsup Actual Arch: arm64

NextJS 13: support for server-side components

Describe the problem you'd like to have solved

I would like to update next-axiom to be able to handle the new server-side components from NextJS 13.

Describe the ideal solution

Still investigating

Make web-vitals and logs work without Vercel

People want to use this library but are either self-hosting or don't use Vercel (#62, #55).

The idea is to make it work by providing an API token with ingest permission and using that to ingest web-vitals and logs.

TypeError: Cannot read properties of undefined (reading '_log')

Sometimes I'm seeing a popup that looks like this:
Screen Shot 2022-08-31 at 17 12 29

Screen Shot 2022-08-31 at 17 13 23

And there's no way for me to know where this error is coming from, or what's causing this.

There should probably be a more meaningful error message that would help people understand what's going on.

But meanwhile - can you help me figure out how to find the source of the problem and fix it?

Log ingestion FetchError

Hi folks 👋🏼

We are using [email protected]. Hosting on Vercel with the Axiom integration installed.

We are seeing a lot of FetchErrors (reason: write EPROTO 139882530146240:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:331) when sending to https://vercel-vitals.axiom.co/api/v1/send?configurationId=icfg_[OMITTED]&projectId=[OMITTED]&type=logs from getStaticProps (hit by on-demand revalidation call, not during built-time).

image

What could be the cause for this? I am not even sure if it is an issue on our side or maybe on Axioms? 🤔
I can't find anything for using Axiom in getStaticProps.

Any hints or tips?

PS: I have also asked this is Discord.

EDIT
This is the high level code if it helps:

export function withIsr<
  // ...
>(handler: IsrGetStaticProps<P, Q, D>, options: WithIsrOptions): GetStaticProps<P, Q, D> {
  return async (context) => {
    // ...
    const logger = new Logger(
      {
        // ...
      },
      undefined,
      false,
      'lambda',
    );

    // ...

    try {
      const result = await handler(extendedContext);
      await logger.flush();
      return result;
    } catch (error) {
      logger.error('Error in ISR getStaticProps', { error });
      await logger.flush();
      throw error;
    }
  };
}

Logging on non-Nextjs frontend?

My company has a NextJS web app running on Vercel, We also have a Chrome Extension version with duplicate front-end code utilizing the same api backend.

Would we be able to use the your logging functionality on both front-end implementations? (Assuming we set the correct environment variables for the Chrome extension in production)

Usage with TRPC - how does this look?

Hey, I'm building an application with the T3 stack and wanted to check if there is a better way to use Axiom with TRPC's router in a Next API route. Let me know if you see room for improvement or want more context on this.

  1. Wrap the handler function in [trpc].ts with withAxiom like the docs say to.
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { appRouter } from "../../../server/router";
import { createContext } from "../../../server/router/context";
import { withAxiom } from 'next-axiom'

// export API handler
export default withAxiom(
  createNextApiHandler({
    router: appRouter,
    createContext,
  })
);
  1. Inside context.ts, add anisAxiomAPIRequest type guard to make sure req.log exists and confirm the request is an AxiomAPIRequest, not NextApiRequest. This will get us type safety both at compile time and runtime. Feel free to make this check more exhaustive (eg check the with function exists on log).

    Extra context: This is where the NextAPIRequest/AxiomAPIRequest is transformed into part of TRPC's own req object.

// 1 new import
import { AxiomAPIRequest } from "next-axiom/dist/withAxiom";

const isAxiomAPIRequest = (
  req?: NextApiRequest | AxiomAPIRequest
): req is AxiomAPIRequest => {
  return Boolean((req as AxiomAPIRequest)?.log);
};

export const createContext = async (
  opts?: trpcNext.CreateNextContextOptions
) => {
  const req = opts?.req;
  const res = opts?.res;

  if (!isAxiomAPIRequest(req)) {
    throw new Error("this is not the request type I expected");
  }

  const session =
    req && res && (await getServerSession(req, res, nextAuthOptions));

  const log = session ? req.log.with({ userId: session.user.id }) : req.log;

  return {
    req,
    res,
    session,
    prisma,
    log,
  };
};
  1. Inside your TRPC queries and mutations, use and re-assign the logger as needed. Here, req is a TRPC request, not a NextApiResponse or AxiomAPIRequest, but we can access the logger on req.ctx.log with the expected type information.
.mutation("create-signed-url", {
  async resolve(req) {

    // add some data to all following log messages by creating a new logger using `with`
    req.ctx.log = req.ctx.log.with({ data })

    // or log a message
    req.ctx.log.info(
      'Here\'s some info', { mediaInfo }
    )
  }
})
  1. Inside your main router in server/router/index.ts, add middleware to copy the reference to the newest logger back on to the AxiomAPIRequest (ctx.req) so that Axiom will flush the correct instance of the logger when the request is about to be finished.
export const appRouter = createRouter()
  .middleware(async ({ ctx, next }) => {
    const result = await next();
    (ctx.req as AxiomAPIRequest).log = ctx.log;
    return result
  })
  .merge("example.", exampleRouter)
  .merge("auth.", authRouter);

Type error when wrapping Route Handlers

next.config.mjs

/** @type {import('next').NextConfig} */

import withVideos from 'next-videos';
import { withAxiom } from 'next-axiom';

const config = {
  images: {
    domains: [
      'flagcdn.com',
      'static-cdn.jtvnw.net',
      'avatars.steamstatic.com',
      'apex-team-logo.s3.us-west-1.amazonaws.com',
      'apex-user-profile.s3.us-west-1.amazonaws.com',
    ],
  },

  staticPageGenerationTimeout: process.env.NEXT_PUBLIC_ENV === 'local' || process.env.NEXT_PUBLIC_ENV === 'dev' ? 0 : 120, // 2 min
};

export default withVideos(withAxiom(config));

\app\api\cron\apex\route.ts

export const GET = withAxiom((request: AxiomRequest) => {
  processNextMatch(database.db, request);
});

error:

.next/types/app/api/cron/apex/route.ts:26:4
Type error: Type 'typeof import("C:/Users/chris/Documents/Github/realm-gg/realm-app/app/api/cron/apex/route")' does not satisfy the constraint '{ GET?: Function | undefined; HEAD?: Function | undefined; OPTIONS?: Function | undefined; POST?: Function | undefined; PUT?: Function | undefined; ... 10 more ...; maxDuration?: number | undefined; }'.
  Types of property 'GET' are incompatible.
    Type 'NextConfig' is missing the following properties from type 'Function': apply, call, bind, prototype, and 5 more.

  24 |   maxDuration?: number
  25 |
> 26 | }, TEntry, ''>>()
     |    ^
  27 |
  28 | // Check the prop type of the entry function
  29 | if ('GET' in entry) {

I have tried many variations of next.config plugin chaining, as well as const and function in Route Handler... always an issue. Not sure. Please help :)

This is a CRON btw.

Cannot see Web Vitals in Vercel project

Hello, I love the Vercel integration! I followed the instructions but cannot get the web vitals metrics on the dashboard (FCP and all).

Added the following to pages/_app.tsx

export { reportWebVitals } from 'next-axiom';

Wrapped next.config.js:
image

Vercel logs work, as well as Axiom log functions (I see the output in the stream as a 'message').

However I don't see WebVitals metrics.

The frontend is sending them to Vercel:
image

Is this expected?

How to i set up axiom with getServerSideProps while using Next-Redux-Wrapper ??

i'm using next-redux-wrapper to get redux store on the server side., i'm trying to console.log() the token in production to debug an issue i'm having
So i'm using axiom like this

import { wrapper } from '../redux/store'
import { log } from 'next-axiom';

export const getServerSideProps = wrapper.getServerSideProps((store) => async () => {

  const token = store.getState().auth.token;
  console.log(token);
 log.info('CONSOLE.LOGGING MY TOKEN', { Type: 'YOUR TOKEN ', Token: token })
  if (token) return {
    redirect: { destination: '/dashboard', permanent: false, }
  } // Redirect to Dashboard if there is a token

  return { props: {} }
})

But i don't think i'm going about it the right way, please can you help me out

404 on _axiom/logs and _axiom/web-vitals

Hi there, i'm trying to set this up in a standard vercel project using the integration, and in my production deployment I get 404's on both the /logs and /web-vitals requests from my frontend.

Screenshot 2022-12-20 at 10 43 37 PM

Looks like axiom has spun up some lambdas in my project but my build output doesnt show them.

Screenshot 2022-12-20 at 10 43 53 PM

A look at the log stream for the apis shows this message: INVALID_REQUEST_METHOD: This Request was not made with an accepted method, so I guess the lambda does exist it just doesnt know how to handle a post request 🤔

What have I done wrong? I've just followed the standard setup instructions from the vercel integration page.

withAxiom() route wrapper doesn't parse fields

export const POST = withAxiom(async (req: AxiomRequest) => {
  const ENDPOINT_LOGGER = req.log.with({
    endpoint: {
      route: "/api/dashboard",
      method: "POST",
      searchParams: req.nextUrl.searchParams.toString(),
    },
  });
  
  ENDPOINT_LOGGER.info("test");
...
}

When wrapping my route handlers with withAxiom(), I would expect for the args (endpoint.route, etc.) to be their own fields within Axiom. However, the args seem to be being parsed as part of the message (instead of being split into their own field).

Allow sending logs and web vitals from non-production deployments

👋

We would like to be able to send logs and web vitals from non-production Next.js deployments on Vercel.

Our use case is a canary deployment that we would like to open up to users for early feedback and testing. We would ideally receive logs and web vitals from that deployment so we can compare them with our production deployment and spot issues sooner rather than later.

Is this something you would consider supporting?

Is it possible to disable ingesting Vercel's log drains?

I'm implementing Axiom logs on my application, but for backwards compatibility, I'll keep on using Vercel's logs for a while.

I have a logging layer that logs into Vercel and now will also log into Axiom, but if I keep it like this, my logs will be duplicated, since Axiom ingests Vercel's log drains.

So, is there a way where I can disable Axiom from also pulling the log drains?

403 Forbidden error

I’m receiving a 403 error in production (“message”: “Forbidden”) and am wondering if it’s because I didn’t add an API token.

Following your next-axiom instructions, I also added the NEXT_PUBLIC_AXIOM_INGEST_ENDPOINT to my project so that it points to a custom dataset. However, where/how do I add the corresponding API token so that the ingest endpoint can be accessed?

Since this is a custom dataset, I don’t have the Vercel integration installed via the Vercel dashboard.

next build crashes if rewrites object contains just the `fallback` key

I'm having a trouble integrating axiom within my existing nextjs (@12.2.2) app. Looks like withAxiom throws when next.config.js contains a following rewrites configuration:

async rewrites() {
    return {
      fallback: [
        {
          source: '/:region/:name([\\w-]{1,})-:id(\\d{1,})',
          destination: '/activity-card/:name/:id',
        },
      ],
    };
  },

with the exact error message being

xxx:build: > Build error occurred
xxx:build: TypeError: Cannot read properties of undefined (reading 'concat')
xxx:build:     at /Volumes/Dev/repos/yyy/node_modules/next-axiom/dist/withAxiom.js:88:71
xxx:build:     at step (/Volumes/Dev/repos/yyy/node_modules/next-axiom/dist/withAxiom.js:44:23)
xxx:build:     at Object.next (/Volumes/Dev/repos/yyy/node_modules/next-axiom/dist/withAxiom.js:25:53)
xxx:build:     at fulfilled (/Volumes/Dev/repos/yyy/node_modules/next-axiom/dist/withAxiom.js:16:58)
xxx:build: error Command failed with exit code 1.

Looking at the withAxiom source code

rewrites.afterFiles = rewrites.afterFiles.concat(axiomRewrites);
I see that only afterFiles field is supported. Why is that so?

`withAxiom` does not support next.js' `basePath`

I have my next.js app set up with the basePath option meaning that it's running on example.com/foo instead of example.com. Unfortunately, withAxiom sets up its endpoints in a way that does not seem to support basePath:

source: `${proxyPath}/web-vitals`,

where proxyPath = export const proxyPath = '/_axiom';.

I can see in the devtools' network tab that the request is being fired at example.com/_axiom/web-vitals. Would it be possible to support the basePath option so that axiom's requests would be fired at, e.g., example.com/foo/_axiom/web-vitals?

[Q&A] Where do I put my API token?

I just started using Axiom and next-axiom and I'm a little lost... So any help is appreciated 👍

From the docs I found the ingest api url should be like: https://cloud.axiom.co/api/v1/datasets/$DATASET_NAME/ingest. However, I'm getting status 403, so my question is where do I need to put my API token? Just in the .env file or somewhere else?

Can't receive logs from the frontend, while logs from backend work

I have installed Vercel Axiom integration into my project and wrapped my Next.js config in withAxiom.

I can see my backend logs in place, everything works there. But I can not see any frontend logs using

import { log } from `next-axiom`;

// pages/index.js
function home() {
    ...
    log.debug('User logged in', { userId: 42 })
    ...
}

Every time I trigger the log from the frontend I receive:

{
  "request": {
    "destination": "https://vercel-vitals.axiom.co/api/v1/send?
    "method": "POST",
    "path": "/_axiom/logs",
    "scheme": "https",
    "statusCode": 403,
    ...
  },
...
}

It's not the full log, but you got the problem.

I'm using Next 13. I noticed that Web-Vitals are not supported with Next 13, but frontend logging should still work, right?

Am I doing something wrong?

NextJS 13: Support Web Vitals

Describe the problem you'd like to have solved

The new version of Next JS doesn't support yet reportWebVitals as it were in NextJS 12. I would like to find a different
way to handle web-vitals so that it would work with the new version of nextjs.

Alternatives and current workarounds

check out web-vitals npm package from google.

Sending front end logs with "fields" attribute results in a 400 (on Vercel)

I am seeing repeated 400 errors with axiom logs for front-end logs in production.

For instance, this call (where connectors is an empty array):

log.debug("getConnectors", { connectors });

Generates a request with this body

'[{"level":"debug","message":"getConnectors","_time":"2023-05-24T10:02:53.039Z","fields":{"connectors":[]},"vercel":{"environment":"production","source":"frontend"}}]'

This throws a 400 and returns {}.

If I manually trigger this same request using curl using this body:

'[{"level":"debug","message":"getConnectors","_time":"2023-05-24T10:02:53.039Z","vercel":{"environment":"production","source":"frontend"}}]'

I get a 200 back.

If I send a message that generates this body, everything is also fine:

[{"level":"debug","message":"Page loaded /my/path","_time":"2023-05-24T10:02:46.300Z","fields":{},"vercel":{"environment":"preview","source":"frontend"}}]

Is it not possible to log a Javascript object/array to Axiom or is this a bug?

Vitals Dashboard

I don't think this is the right place to post this feedback but I didn't know where to do it, so sorry for creating an issue for this.

It would be good to have a way to create/import a dashboard template for Vitals like the one you have for Vercel's integration without having to create all the graphs and stats manually. It would help a lot the people like me who are not hosting his Next.js app on Vercel.

Web-vitals 401 error

Hello,

I'm developing on the website www.theninja-rpg.com, which is bootstrapped with T3, adapted to use drizzle as ORM and clerk for auth.

I also have axiom setup and deployed using the vercel integration. Looking at the console, I see the following:

image

Am I doing something wrong? The project source is available at: https://github.com/MathiasGruber/TheNinjaRPG .. I'm pretty sure I've just followed the setup guide, but maybe there is some conflics with e.g. clerk?

Improving definition of AxiomRequest type

Currently, the AxiomRequest type is defined as follows:

export type AxiomRequest = (NextRequest | Request) & { log: Logger };

However, this definition poses difficulties when trying to use Next.js-specific APIs like req.nextUrl, which are not available in the Request type.

I propose updating the AxiomRequest type to the following:

export type AxiomRequest = NextRequest & { log: Logger };

This change will ensure that the AxiomRequest type aligns with Next.js APIs.

Please let me know if I'm missing any important considerations or if you have any suggestions for alternative solutions.

Thank you

Fix type of `Logger.flush()`

The Logger class' flush method has an any type, making my typescript-eslint configuration scream at me. I'd recommend allowing TypeScript to just infer types whenever possible and remove the any type here.

next-axiom/src/logger.ts

Lines 197 to 199 in 9ec2a79

flush: any = async () => {
return Promise.all([this.sendLogs(), ...this.children.map((c) => c.flush())]);
};

axiom/web-vitals 403 error on localhost

I setup next-axiom as outlined but I'm seeing the following browser console error on localhost:

POST http://localhost:3000/_axiom/web-vitals 403 (Forbidden) - webVitals.js

Is this a bug or should I just conditionally export reportWebVitals in _app.ts on production only?

I'm only interested in the production logs on Vercel which work fine.

Screenshot 2023-01-10 at 7 20 09 PM

Not working with Next 13

 WARN  Issues with peer dependencies found
.
└─┬ next-axiom 0.14.0
└── ✕ unmet peer next@^12.1.4: found 13.0.0

Next-Axiom Typescript Issues

I am getting an error with the following NextJS 13 Route Handler endpoint.

export const POST = withAxiom(
  async (
    req: AxiomRequest,
    { params }: { params: { chatConversationId: string } }
  ) => {
...
}

The file path for this is chatConversation/[chatConversationId]/route.ts, so the error seems to be the fact that I am trying to access the params in the dynamic route segment in NextJS.

When deploying this to Vercel, I get the following error:

Invalid configuration "POST":
    Expected "Function", got "NextConfig".

The POST function seems to return a NextConfig when passing in the params whereas in my other routes that do not have dynamic route segments it returns a NextHandler.

How do I fix this?

403 on Vercel

Hello everyone,

I'm using:

My application is being deployed to Vercel.
I've setup the integration with Axiom (it was as seamless as they come, indeed), the environment variable was created automatically, and Axiom started ingesting data (server-side logs, etc).
Then I moved to using the withAxiom HOC, in order to enable client-side log and reportWebVitals.

But, whenever those trigger, I can see a 403 error:
image
Both requests hit this url: https://<my-domain>/_axiom/<web-vitals|logs>

And the response (for either) is an empty object:
image

Can anyone help me shed some light on this?
Thank you!

withAxiomRouteHandler does not pass next route context

when using ^1.0.0-rc.1

For a route like GET api/posts/[id]

The route Handler does not pass the params that come form the context as expected in the docs

export const GET = withAxiomRouteHandler((request: AxiomRequest, { params }) => { ... })

where params would be in this case of type { params: { id: string } } based on the path

I looked at the line
and it looks like you need to do this

``ts
return async (req: Request | NextRequest, ctx) => { // <- add ctx
let region = '';
if ('geo' in req) {
region = req.geo?.region ?? '';
}

const report: RequestReport = {
  startTime: new Date().getTime(),
  path: req.url,
  method: req.method,
  host: req.headers.get('host'),
  userAgent: req.headers.get('user-agent'),
  scheme: 'https',
  ip: req.headers.get('x-forwarded-for'),
  region,
};
const isEdgeRuntime = globalThis.EdgeRuntime ? true : false;

const logger = new Logger({ req: report, source: isEdgeRuntime ? 'edge' : 'lambda' });
const axiomContext = req as AxiomRequest;
axiomContext.log = logger;

try {
  const result = await handler(axiomContext, ctx); // <- pass ctx

Can't see the logs printed out in production

Hi! I'm new to Axiom, this looks like an awesome tool, thank you for building it!

I'm trying to set it up with Next.js and Vercel, and ran into an issue - in my production deployment, I don't see the logs printed out in the devtools console or in the function logs in Vercel's UI.

In your README it says:

When env vars are not detected, Pretty printing to console is enabled by default, to disable it set the environment variable:
AXIOM_PRETTY_PRINT_ENABLED=false

My guess was that if I'd set this variable to true in production, it should enable printing the logs into the console, but it doesn't look like it's working. Even with this variable set to true, I don't see errors in my devtools.

Can you help me out? How can I enable pretty printing logs in production?

[Question] Adding custom fields to request logs

Is it possible to add a custom field to all request logs?

We are running behind Cloudflare and would like to include the value of cf-connecting-ip in our logs.

We could do this in our middleware by manually logging the value, but I'm wondering if there's a way to get the IP included in the logs that are automatically output by Next/Vercel on request.

Typescript support?

Perhaps I'm missing something obvious here, but I can't see anywhere in the docs where we can add the type declaration to the NextApiRequest type to be able to do req.log.

Sending Client Logs on Non-enterprise netlify account

Hey - I have followed the setup instructions but any logs sent clientside are not flowing through to axiom.
This is locally, and also on non-enterprise netlify.

  • I can verify the rewrites are being added to my next config (and when going to the rewrites url /_axiom/logs i get a not-found api response rather than my 404 page which i guess is from sending a GET request to an API that is expecting POST
  • These log error messages are not running https://github.com/axiomhq/next-axiom/blob/main/src/withAxiom.ts#L31, which leads me to believe that all variables are correctly there
  • My AXIOM_TOKEN and AXIOM_DATASET are both set and validated they are there
  • Logs in api routes work
  • There are no network calls to the /_axiom/logs endpoint from my frontend
image

Any ideas? Seems like theres a few others having this problem but it looks like in v 0.17 it was stable in non vercel platforms?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.