Guia de logs

Envie logs estruturados do browser e do seu servidor em Next.js, Vue/Nuxt e TanStack.

Client

Crie o client uma vez no escopo do módulo e importe onde for logar. Toda chamada imprime local e faz POST em /api/v1/logs.

lib/dataxamas.client.ts
"use client";

import { Dataxamas } from "dataxamas";

// Module scope: one client per app. Creating it inside a component would
// re-install the global error handlers on every render.
export const dataxamas = new Dataxamas({
  token: process.env.NEXT_PUBLIC_DATAXAMAS_TOKEN as string,
  websiteId: process.env.NEXT_PUBLIC_DATAXAMAS_WEBSITE_ID as string,
});
app/checkout/checkout-button.tsx
"use client";

import { dataxamas } from "@/lib/dataxamas.client";

export function CheckoutButton({ plan }: { plan: string }) {
  return (
    <button
      type="button"
      onClick={() => {
        dataxamas.logs.info("Checkout opened", { plan });
      }}
    >
      Checkout
    </button>
  );
}
Segurança: um token dx_live_ grava logs e erros do website inteiro. Usá-lo no browser o coloca no bundle público, onde qualquer um pode ler. Prefira a rota proxy abaixo e só exponha o token no client se aceitar esse risco.

Servidor

No servidor o token fica numa variável de ambiente. O mesmo client também dá acesso a exceptions.captureException e instala handlers globais de uncaughtException / unhandledRejection do process.

lib/dataxamas.server.ts
import "server-only";

import { Dataxamas } from "dataxamas";

export const dataxamas = new Dataxamas({
  token: process.env.DATAXAMAS_TOKEN as string,
  websiteId: process.env.DATAXAMAS_WEBSITE_ID as string,
  environment: process.env.NODE_ENV,
  release: process.env.VERCEL_GIT_COMMIT_SHA,
});
app/api/checkout/route.ts
import { dataxamas } from "@/lib/dataxamas.server";

export async function POST(request: Request) {
  const body = await request.json();

  try {
    const order = await createOrder(body);

    await dataxamas.logs.success("Payment processed", { orderId: order.id, amount: order.amount });

    return Response.json(order);
  } catch (error) {
    dataxamas.exceptions.captureException(error, { route: "/api/checkout" });

    return Response.json({ error: "Checkout failed" }, { status: 500 });
  }
}
instrumentation.ts
// Imported once at boot, so the global error handlers are installed
// before the first request is served.
export async function register() {
  await import("@/lib/dataxamas.server");
}
Uma SPA Vue pura e um app TanStack Router puro não têm runtime de servidor — use seu próprio backend (Node, Express, Hono) com o mesmo client em escopo de módulo.

Rota proxy

Mantém o token no servidor: o browser posta na sua própria rota, que reenvia a entrada pelo SDK.

app/api/logs/route.ts — Next.js
import { dataxamas } from "@/lib/dataxamas.server";

const LEVELS = ["debug", "info", "warn", "log", "success"] as const;

type Level = (typeof LEVELS)[number];

export async function POST(request: Request) {
  const { level, message, data } = await request.json();

  if (!LEVELS.includes(level)) {
    return Response.json({ error: "Invalid level" }, { status: 400 });
  }

  await dataxamas.logs[level as Level](message, data);

  return new Response(null, { status: 204 });
}
src/routes/api/logs.ts — TanStack Start
import { createFileRoute } from "@tanstack/react-router";

import { dataxamas } from "@/lib/dataxamas.server";

const LEVELS = ["debug", "info", "warn", "log", "success"] as const;

type Level = (typeof LEVELS)[number];

export const Route = createFileRoute("/api/logs")({
  server: {
    handlers: {
      POST: async ({ request }) => {
        const { level, message, data } = await request.json();

        if (!LEVELS.includes(level)) {
          return Response.json({ error: "Invalid level" }, { status: 400 });
        }

        await dataxamas.logs[level as Level](message, data);

        return new Response(null, { status: 204 });
      },
    },
  },
});
lib/log.ts — browser
// No token in the browser bundle — the server route holds it.
type Level = "debug" | "info" | "warn" | "log" | "success";

export function log(level: Level, message: string, data?: unknown) {
  return fetch("/api/logs", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ level, message, data }),
    keepalive: true,
  });
}
Níveis disponíveis: debug, info, warn, log e success — todos com a assinatura (message, data?). Referência completa: DataxamasLogs.