Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/content/integrations/angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,10 @@ import { hub } from '@logtide/core';
export class CheckoutComponent {
purchase() {
hub.addBreadcrumb({
type: 'ui',
category: 'ui',
message: 'Purchase button clicked',
timestamp: Date.now(),
});

try {
Expand Down
10 changes: 4 additions & 6 deletions src/content/integrations/elysia.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ faqs:
- question: "How do I add LogTide logging to an Elysia application?"
answer: "Install @logtide/elysia with bun add @logtide/elysia, then call app.use(logtide({ dsn, service, environment })) in your Elysia setup. Use .as('global') on the plugin to ensure all routes, including those registered after the plugin, are covered."
- question: "Does the LogTide Elysia plugin automatically log every request?"
answer: "Yes. The plugin hooks into Elysia's onRequest lifecycle to start a span and extract any incoming traceparent header, and into afterResponse to log the completed request with its duration, with no per-route code required."
answer: "Yes. The plugin hooks into Elysia's onRequest lifecycle to start a span and extract any incoming traceparent header, and into onAfterHandle to log the completed request with its duration, with no per-route code required."
- question: "How does LogTide handle Elysia errors and exceptions?"
answer: "The plugin registers an onError lifecycle hook that captures errors with full request context automatically. You can still add your own onError handler to return a custom response; the error is already recorded by LogTide before your handler runs."
- question: "Does LogTide flush pending logs when the Elysia server stops?"
answer: "Yes. The plugin registers an onStop lifecycle hook that flushes any buffered log events before the process exits, ensuring no logs are lost during graceful shutdown."
answer: "Buffered events are flushed automatically on the batching interval. For graceful shutdown, call hub.flush() (or hub.close()) before the process exits to ensure no logs are lost — the plugin does not register a shutdown hook itself."
---

LogTide's Elysia SDK provides a Bun-optimized plugin for automatic request logging, scoped context, lifecycle hooks, and W3C trace propagation.
Expand All @@ -37,9 +37,8 @@ LogTide's Elysia SDK provides a Bun-optimized plugin for automatic request loggi

- **Bun-optimized**: Takes advantage of Bun's performance
- **Plugin architecture**: Use `.as('global')` for app-wide coverage
- **Lifecycle hooks**: onRequest, afterResponse, onError, onStop
- **Lifecycle hooks**: onRequest, onAfterHandle, onError
- **Scoped context**: Per-request scope via store decorators
- **Auto-shutdown**: Flushes pending logs when the server stops

## Prerequisites

Expand Down Expand Up @@ -106,9 +105,8 @@ app
| Hook | Behavior |
|------|----------|
| `onRequest` | Creates scope, extracts traceparent, starts span |
| `afterResponse` | Logs completion with duration |
| `onAfterHandle` | Logs completion with duration |
| `onError` | Captures errors with request context |
| `onStop` | Flushes pending events |

## Error Handling

Expand Down
7 changes: 3 additions & 4 deletions src/content/integrations/fastify.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ faqs:
- question: "How do I integrate LogTide with a Fastify application?"
answer: "Install @logtide/fastify and register the plugin with await fastify.register(logtide, { dsn, service, environment }). The plugin follows Fastify plugin conventions and hooks into the lifecycle automatically — no extra configuration is required to start capturing request logs."
- question: "Which Fastify lifecycle hooks does LogTide use?"
answer: "The plugin hooks into onRequest to create a scoped context and extract the traceparent header, onResponse to log the completed request with duration and status code, onError to capture exceptions with full request context, and onClose to flush any pending log events on server shutdown."
answer: "The plugin hooks into onRequest to create a scoped context and extract the traceparent header, onSend to optionally capture the response body, onResponse to log the completed request with duration and status code, and onError to capture exceptions with full request context."
- question: "Does LogTide replace Fastify built-in pino logging?"
answer: "LogTide operates alongside Fastify's built-in pino logger rather than replacing it. You can keep pino for local development output while LogTide ships structured logs to your self-hosted LogTide instance for centralised search and alerting."
- question: "How does per-request scoping work in the Fastify plugin?"
Expand All @@ -37,9 +37,8 @@ LogTide's Fastify SDK provides a native plugin that hooks into Fastify's lifecyc
## Why use LogTide with Fastify?

- **Native plugin architecture**: Follows Fastify plugin conventions
- **Lifecycle hooks**: Automatic instrumentation via onRequest, onResponse, onError
- **Lifecycle hooks**: Automatic instrumentation via onRequest, onSend, onResponse, onError
- **Per-request scoping**: Isolated context per request through decorators
- **Auto-shutdown**: Flushes logs on server close via onClose hook
- **Zero overhead**: Asynchronous batching keeps Fastify fast

## Prerequisites
Expand Down Expand Up @@ -113,9 +112,9 @@ The plugin hooks into Fastify's lifecycle automatically:
| Hook | Behavior |
|------|----------|
| `onRequest` | Creates scope, extracts traceparent, starts span |
| `onSend` | Optionally captures the response body |
| `onResponse` | Logs completion with duration and status |
| `onError` | Captures errors with request context |
| `onClose` | Flushes pending events on shutdown |

## Error Handling

Expand Down
42 changes: 28 additions & 14 deletions src/content/integrations/nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ faqs:
- question: "Does @logtide/nextjs support both server-side and client-side logging?"
answer: "Yes. You initialize the server side in instrumentation.ts using registerLogtide from @logtide/nextjs/server, and the client side in app/layout.tsx using initLogtide from @logtide/nextjs/client. You can use separate DSNs for each via LOGTIDE_DSN and NEXT_PUBLIC_LOGTIDE_DSN environment variables."
- question: "How do I capture client-side React errors in Next.js with LogTide?"
answer: "Wrap your error UI with the LogtideErrorBoundary component from @logtide/nextjs/client inside your app/error.tsx file. This automatically captures and forwards React rendering errors to LogTide."
answer: "Wrap your component tree with the LogtideErrorBoundary component from @logtide/nextjs/client (for example in a client component rendered from app/layout.tsx). It automatically captures and forwards React rendering errors to LogTide, and accepts an optional fallback to render in place of the crashed subtree."
- question: "Can I track page navigation as breadcrumbs in a Next.js App Router application?"
answer: "Yes. Import trackNavigation from @logtide/nextjs/client and call it inside a useEffect that watches the pathname from usePathname. Place this LogtideNavigationTracker component in your providers or layout to record every client-side route change."
---
Expand Down Expand Up @@ -122,30 +122,42 @@ Server-side errors in API routes, Server Components, and Server Actions are capt

Use `LogtideErrorBoundary` for client-side React error capture:

`LogtideErrorBoundary` wraps your component tree and reports any rendering
error it catches to LogTide. It accepts an optional `fallback` (a node, or a
`(error) => node` function) to render in place of the crashed subtree:

```tsx
// app/error.tsx
// app/providers.tsx
'use client';

import { LogtideErrorBoundary } from '@logtide/nextjs/client';

export default function ErrorPage({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
export function Providers({ children }: { children: React.ReactNode }) {
return (
<LogtideErrorBoundary error={error}>
<div>
<h2>Something went wrong</h2>
<button onClick={reset}>Try again</button>
</div>
<LogtideErrorBoundary fallback={<div>Something went wrong</div>}>
{children}
</LogtideErrorBoundary>
);
}
```

Then wrap your app with it in `app/layout.tsx`:

```tsx
// app/layout.tsx
import { Providers } from './providers';

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
```

## Navigation Tracking

Track client-side navigation as breadcrumbs:
Expand Down Expand Up @@ -203,8 +215,10 @@ export async function updateUser(formData: FormData) {
const userId = formData.get('userId') as string;

hub.addBreadcrumb({
type: 'custom',
category: 'action',
message: 'Update user action triggered',
timestamp: Date.now(),
});

try {
Expand Down
2 changes: 2 additions & 0 deletions src/content/integrations/nodejs.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,11 @@ try {
```typescript
// Add breadcrumbs for debugging context
hub.addBreadcrumb({
type: 'custom',
category: 'auth',
message: 'User authenticated',
level: 'info',
timestamp: Date.now(),
});

// Framework SDKs create per-request scopes automatically.
Expand Down
17 changes: 9 additions & 8 deletions src/content/integrations/nuxt.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ faqs:
- question: "How do I add LogTide logging to my Nuxt application?"
answer: "Install @logtide/nuxt, add it to the modules array in nuxt.config.ts, and set the dsn option pointing to your LogTide DSN. The module handles initialization on both the server and client automatically with no additional setup required."
- question: "Does @logtide/nuxt support separate logging for server-side and client-side code?"
answer: "Yes. You can provide a separate clientDsn for browser-side logging and control each side independently with the clientEnabled and serverEnabled options. Server-side logs use LOGTIDE_DSN while client-side logs use NUXT_PUBLIC_LOGTIDE_DSN."
answer: "Yes. The module auto-initializes on both the Nitro server and the Vue client. Your dsn is injected through Nuxt runtime config — server code reads the private runtimeConfig.logtide and the browser reads runtimeConfig.public.logtide, both populated from the same dsn (or apiUrl/apiKey) set in nuxt.config.ts."
- question: "How do I log events from Vue components in a Nuxt application?"
answer: "Import useLogtide from #imports inside your Vue component, then call methods like captureLog, captureError, and addBreadcrumb on the returned composable. This works in both client-side and universal rendering contexts."
- question: "Can I override the LogTide DSN at deploy time without rebuilding my Nuxt app?"
Expand Down Expand Up @@ -79,23 +79,22 @@ export default defineNuxtConfig({

logtide: {
dsn: process.env.LOGTIDE_DSN,
// Or, instead of a dsn:
// apiUrl: process.env.LOGTIDE_API_URL,
// apiKey: process.env.LOGTIDE_API_KEY,

service: 'nuxt-app',
environment: process.env.NODE_ENV,
release: '1.0.0',

// Separate client DSN (optional)
clientDsn: process.env.NUXT_PUBLIC_LOGTIDE_DSN,

// Toggle sides (default: both true)
clientEnabled: true,
serverEnabled: true,

// Tracing
tracesSampleRate: 1.0,
},
});
```

The same configuration is applied to both the server (Nitro) and the client (Vue) — there is no separate client/server toggle.

## Server-Side Usage

```typescript
Expand All @@ -122,8 +121,10 @@ const logtide = useLogtide();

async function handleSubmit() {
logtide.addBreadcrumb({
type: 'ui',
category: 'ui',
message: 'Form submitted',
timestamp: Date.now(),
});

try {
Expand Down
7 changes: 4 additions & 3 deletions src/content/integrations/react.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,18 @@ Wrap your application or specific components with an Error Boundary to capture r
import React from 'react';
import { LogtideErrorBoundary } from '@logtide/browser';

function MyErrorPage({ error, reset }: { error: Error; reset: () => void }) {
function MyErrorPage({ error }: { error: Error }) {
return (
<div className="error-container">
<h2>Something went wrong!</h2>
<pre>{error.message}</pre>
<button onClick={reset}>Try again</button>
</div>
);
}

export default function App() {
return (
<LogtideErrorBoundary fallback={(error, reset) => <MyErrorPage error={error} reset={reset} />}>
<LogtideErrorBoundary fallback={(error) => <MyErrorPage error={error} />}>
<Dashboard />
</LogtideErrorBoundary>
);
Expand All @@ -108,8 +107,10 @@ import { hub } from '@logtide/core';
function CheckoutButton() {
const handleCheckout = async () => {
hub.addBreadcrumb({
type: 'ui',
category: 'ui',
message: 'Checkout button clicked',
timestamp: Date.now(),
});

try {
Expand Down
2 changes: 2 additions & 0 deletions src/content/integrations/solidjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ import { hub } from '@logtide/core';
function CheckoutButton() {
const handleCheckout = async () => {
hub.addBreadcrumb({
type: 'ui',
category: 'ui',
message: 'Checkout button clicked',
timestamp: Date.now(),
});

try {
Expand Down
2 changes: 2 additions & 0 deletions src/content/integrations/sveltekit.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ export const actions = {
const data = await request.formData();

hub.addBreadcrumb({
type: 'ui',
category: 'form',
message: 'Settings form submitted',
timestamp: Date.now(),
});

try {
Expand Down
2 changes: 2 additions & 0 deletions src/content/integrations/vue.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ import { hub } from '@logtide/core';

async function handleAction() {
hub.addBreadcrumb({
type: 'ui',
category: 'ui',
message: 'User clicked action',
timestamp: Date.now(),
});

try {
Expand Down