Skip to content

SDKs

LogVista provides a TypeScript SDK package (@orphnet/logvista-sdks) with first-class adapters for Hono, Nuxt, Node.js, and browsers. The SDK handles batching, retries, redaction, and auto-capture so you can focus on your application.

Installation

bash
bun add @orphnet/logvista-sdks

When developing against an unreleased version of the SDK:

bash
# 1. In the SDK repo — link the package
cd /path/to/logging-packages
bun link

# 2. In your project — use the linked package
cd /path/to/my-project
bun link @orphnet/logvista-sdks

# 3. In the SDK repo — rebuild on changes
bun run dev

Changes to the SDK source are immediately available in your project after the incremental build. Run bun unlink @orphnet/logvista-sdks in your project when done.

The package ships as a single npm module with subpath exports:

ImportRuntimeDescription
@orphnet/logvista-sdksAnyCore logger, transports, types
@orphnet/logvista-sdks/honoCloudflare WorkersHono middleware with auto-capture
@orphnet/logvista-sdks/nuxtNuxt 3Nuxt module with composables
@orphnet/logvista-sdks/nodeNode.js / BunNode adapter with graceful shutdown
@orphnet/logvista-sdks/browserBrowserBrowser adapter with sendBeacon flush

Prerequisites

Before using the SDK, you need:

  1. A LogVista account and workspace
  2. A project with an API key (sk_... prefix)
  3. The API key must have logs:write scope

See Getting Started and API Keys for setup instructions.


Core Concepts

Logger Instance

Every SDK adapter creates a LogVista instance with a .logger property. The logger provides:

  • Category methodslogger.ai(), logger.http(), logger.database(), etc.
  • Level methodslogger.info(), logger.error(), logger.fatal(), etc.
  • Raw methodlogger.log() for full control
ts
import { createLogVista } from '@orphnet/logvista-sdks'

const logvista = createLogVista({
  apiKey: 'sk_...',
  apiUrl: 'https://api.logvista.orph.dev',
  projectId: 'my-project',
})

const logger = logvista.logger

Log Levels

Levels are ordered by severity. The level config option sets the minimum threshold — logs below it are dropped before reaching the transport.

LevelSeverityUse Case
trace0High-volume diagnostics
debug1Development debugging
log2General purpose
info3Informational events (default)
warn4Potential issues
error5Errors requiring attention
fatal6Unrecoverable failures

Categories

Each log belongs to a category with typed sub-types. Categories map to the Log Categories system in the API.

CategoryTypesUse Case
aillm, interaction, step, action, response, summary, embedding, tool-callAI/LLM operations
httprequest, response, redirectHTTP traffic
systemstartup, shutdown, error, debug, info, warnApplication lifecycle
databasequery, transaction, migration, slow-query, connectionDatabase operations
authlogin, logout, token-refresh, permission-denied, registrationAuthentication events
queueenqueue, dequeue, process, retry, dead-letterQueue/job processing
cachehit, miss, set, evict, invalidateCache operations
customany stringCustom events

Fire-and-Forget Semantics

The SDK never throws and never blocks your application:

  • Logger calls return synchronously
  • Transport delivery is asynchronous
  • Failed batches retry with exponential backoff
  • After max retries, logs are dropped (with onDrop callback)
  • Transport errors fire onError callback but never propagate

Hono Adapter

The Hono adapter provides middleware that auto-captures HTTP requests and responses while making the logger available on Hono's context.

Basic Setup

ts
import { Hono } from 'hono'
import { logvistaMiddleware } from '@orphnet/logvista-sdks/hono'

const app = new Hono()

app.use('*', logvistaMiddleware({
  apiKey: 'sk_...',
  apiUrl: 'https://api.logvista.orph.dev',
  projectId: 'my-api',
}))

app.get('/users', (c) => {
  const logger = c.get('logger')
  logger.database('query', { message: 'Listing users', data: { table: 'users' } })
  return c.json({ users: [] })
})

export default app

Auto-Capture

By default, the middleware logs every HTTP request and response:

Request log:

json
{
  "level": "info",
  "category": "http",
  "type": "request",
  "message": "GET /users",
  "data": {
    "method": "GET",
    "path": "/users",
    "headers": { "authorization": "[REDACTED]", "content-type": "application/json" },
    "userAgent": "Mozilla/5.0 ..."
  }
}

Response log:

json
{
  "level": "info",
  "category": "http",
  "type": "response",
  "message": "GET /users → 200 (12ms)",
  "data": {
    "method": "GET",
    "path": "/users",
    "status": 200,
    "duration": 12,
    "contentLength": "256"
  }
}

Response log levels adjust automatically: info for 2xx/3xx, warn for 4xx, error for 5xx.

Auto-Capture Configuration

ts
app.use('*', logvistaMiddleware({
  apiKey: 'sk_...',
  apiUrl: 'https://api.logvista.orph.dev',
  projectId: 'my-api',

  autoCapture: {
    requests: true,                      // Log incoming requests
    responses: true,                     // Log outgoing responses
    errors: true,                        // Log uncaught handler errors

    // Path filtering
    excludePaths: ['/health', '/ready', '/favicon.ico'],
    excludeMethods: ['OPTIONS'],
    includePaths: null,                  // Allow-list (overrides exclude)

    // Redaction
    redactHeaders: ['authorization', 'cookie', 'x-api-key'],
    redactBodyFields: ['password', 'token', 'secret'],

    // Body capture (opt-in — can be expensive)
    captureRequestBody: false,
    captureResponseBody: false,
    maxBodySize: 32768,                  // 32KB truncation limit

    // Extras
    captureQueryParams: true,
    timingHeader: 'X-Response-Time',     // null to disable
  },
}))

Lifecycle Hooks

Transform or skip auto-captured logs with lifecycle hooks:

ts
app.use('*', logvistaMiddleware({
  // ...
  onRequest: (c, log) => {
    // Add custom data
    return { ...log, data: { ...log.data, userId: c.get('userId') } }
  },
  onResponse: (c, log) => {
    // Skip 404 responses
    if (log.data?.status === 404) return null
    return log
  },
  onErrorLog: (c, error, log) => {
    // Enrich error logs
    return { ...log, data: { ...log.data, requestId: c.get('requestId') } }
  },
}))

Cloudflare waitUntil

The middleware wraps log flushing in executionCtx.waitUntil() so delivery happens after the response is sent:

ts
app.use('*', logvistaMiddleware({
  // ...
  waitUntil: true, // Default — logs don't block the response
}))

Typed Context

The logger is available on Hono's context with full TypeScript support:

ts
app.post('/chat', async (c) => {
  const logger = c.get('logger') // LogVistaLogger — fully typed

  logger.ai('llm', {
    message: 'GPT-4 call started',
    data: { model: 'gpt-4', prompt_tokens: 200 },
  })

  const result = await callLLM()

  logger.ai('response', {
    message: 'GPT-4 call completed',
    data: { completion_tokens: 150, duration: 820 },
  })

  return c.json(result)
})

Nuxt Module

The Nuxt module auto-registers server middleware, client plugins, composables, and a proxy endpoint for secure client-side logging.

Setup

ts
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@orphnet/logvista-sdks/nuxt'],

  logvista: {
    apiKey: process.env.LOGVISTA_API_KEY,
    apiUrl: 'https://api.logvista.orph.dev',
    projectId: 'my-nuxt-app',
    level: 'info',

    server: {
      enabled: true,
      autoCapture: {
        requests: true,
        responses: true,
        errors: true,
        excludePaths: ['/api/_health', '/_nuxt/**'],
        redactHeaders: ['authorization', 'cookie'],
      },
    },

    client: {
      enabled: true,
      autoCapture: {
        errors: true,         // window.onerror + unhandledrejection
        navigation: true,     // Route change tracking
        fetchErrors: true,    // Failed $fetch / fetch calls
      },
    },

    defaultMeta: {
      env: process.env.NODE_ENV,
      service: 'my-nuxt-app',
    },
  },
})

Client-Side — useLogger()

vue
<script setup>
const logger = useLogger()

async function submitForm() {
  logger.info('Form submitted', { data: { formId: 'contact' } })

  try {
    await $fetch('/api/contact', { method: 'POST', body: formData })
    logger.info('Form submission successful')
  } catch (error) {
    logger.error('Form submission failed', { data: { error: error.message } })
  }
}
</script>

Server-Side — useLogVista(event)

ts
// server/api/users.get.ts
export default defineEventHandler((event) => {
  const logger = useLogVista(event)

  logger.database('query', { message: 'Fetching user list' })
  const users = await db.query('SELECT * FROM users')

  logger.info(`Found ${users.length} users`)
  return users
})

Cloudflare Pages waitUntil

When deployed to Cloudflare Pages, the Nuxt server middleware automatically detects the Pages runtime and uses event.context.cloudflare.context.waitUntil() to flush logs after the response is sent. No configuration needed — it just works.

This ensures logs are delivered even after the response completes and the Pages Function starts winding down.

Client-Side Security

Client-side logs are routed through a Nitro proxy endpoint (POST /api/_logvista). The API key stays on the server — no credentials are exposed to the browser.

Auto-Captured Client Events

Route navigation:

json
{
  "level": "info",
  "category": "http",
  "type": "request",
  "message": "Navigation: /dashboard → /settings",
  "data": { "from": "/dashboard", "to": "/settings" }
}

Unhandled error:

json
{
  "level": "error",
  "category": "system",
  "type": "error",
  "message": "TypeError: Cannot read properties of undefined",
  "data": { "stack": "...", "url": "/settings" }
}

Failed fetch:

json
{
  "level": "warn",
  "category": "http",
  "type": "response",
  "message": "GET /api/users → 500",
  "data": { "url": "/api/users", "status": 500, "duration": 340 }
}

Node.js / Bun

For plain Node.js or Bun servers without a framework:

ts
import { createLogVista } from '@orphnet/logvista-sdks/node'

const logvista = createLogVista({
  apiKey: process.env.LOGVISTA_API_KEY!,
  apiUrl: 'https://api.logvista.orph.dev',
  projectId: 'my-service',
  shutdownOnExit: true, // SIGTERM/SIGINT → flush before exit
})

const logger = logvista.logger

logger.info('Service started')
logger.database('query', { message: 'Connected to database' })

// Manual shutdown (e.g., in test teardown)
await logvista.shutdown()

Browser (Vanilla)

For browser apps without Nuxt (React, Svelte, vanilla JS, etc.):

ts
import { createLogVista } from '@orphnet/logvista-sdks/browser'

const logvista = createLogVista({
  apiUrl: '/api/_logvista',   // Proxy through your backend
  projectId: 'my-app',

  autoCapture: {
    errors: true,             // window.onerror + unhandledrejection
    fetchErrors: true,        // Intercept failed fetch calls
  },

  flushOnVisibilityChange: true, // Flush via sendBeacon when tab hides
  flushOnUnload: true,           // Flush on beforeunload
})

const logger = logvista.logger
logger.info('App loaded')

TIP

Use navigator.sendBeacon() for reliable delivery when the user navigates away or closes the tab. The browser adapter handles this automatically.


Configuration Reference

Core Options

All adapters accept these core options:

OptionTypeDefaultDescription
apiKeystringAPI key (sk_...)
apiUrlstringrequiredLogVista API URL
projectIdstringrequiredProject ID
transportstring | Transport | Transport[]'batch'Transport type or instance(s)
levelLogLevel'info'Minimum log level
categoriesLogCategory[]nullAllow-list (null = all)
excludeCategoriesLogCategory[]nullDeny-list
sampling.ratenumber1.0Sampling rate (0.0–1.0)
sampling.overridesRecord<LogLevel, number>Per-level sampling
defaultMetaobject{}Metadata added to every log
sessionIdstringautoSession identifier
beforeSend(log) => log | nullTransform or drop logs
onError(error, logs) => voidTransport failure callback
onDrop(logs, reason) => voidDropped logs callback
debugbooleanfalseLog SDK internals

Batch Options

OptionTypeDefaultDescription
batch.sizenumber50Max buffer before flush
batch.flushIntervalnumber5000Flush interval (ms)
batch.maxRetriesnumber3Max retries per batch
batch.backoffstring | function'exponential'Backoff strategy
batch.backoffBasenumber1000Base delay (ms)

Extending Categories

Add custom categories to the type system via TypeScript declaration merging:

ts
// types/logvista.d.ts
declare module '@orphnet/logvista-sdks' {
  interface CategoryRegistry {
    billing: 'charge' | 'refund' | 'subscription'
    email: 'send' | 'bounce' | 'delivery'
  }
}

Now you get full type safety for your custom categories:

ts
logger.billing('charge', {
  message: 'Payment processed',
  data: { amount: 99.99, currency: 'USD' },
})

Custom Transports

Build your own transport to send logs anywhere:

ts
import type { Transport, LogEntry } from '@orphnet/logvista-sdks'

class DatadogTransport implements Transport {
  send(log: LogEntry): void {
    // Forward to Datadog, Sentry, etc.
  }

  async flush(): Promise<void> {
    // Flush buffered entries
  }
}

const logvista = createLogVista({
  apiUrl: 'https://api.logvista.orph.dev',
  projectId: 'my-project',
  // Use multiple transports simultaneously
  transport: [new BatchTransport(config), new DatadogTransport()],
})

Cloudflare Runtime Support

Both adapters handle waitUntil automatically for reliable log delivery on edge runtimes:

RuntimewaitUntil pathAdapter
Cloudflare Workers (Hono)c.executionCtx.waitUntil()Hono middleware
Cloudflare Pages (Nuxt)event.context.cloudflare.context.waitUntil()Nuxt server middleware
Node.js / BunN/A — process stays aliveBatch timer + shutdownOnExit
BrowserN/Anavigator.sendBeacon on unload

TIP

On Cloudflare runtimes, the batch transport timer may not survive past the response. waitUntil ensures the flush completes even after the response is sent. Both adapters detect the runtime and call waitUntil automatically — no configuration required.


Log Pipeline

Every log flows through this pipeline before reaching the transport:

logger.ai('llm', {...})


┌─ Level Gate ──────────┐
│ level >= minimum?      │ → no → drop
└───────┬───────────────┘

┌─ Category Filter ─────┐
│ in allow-list?         │ → no → drop
│ not in deny-list?      │
└───────┬───────────────┘

┌─ Sampling ────────────┐
│ passes rate check?     │ → no → drop
└───────┬───────────────┘

┌─ Enrichment ──────────┐
│ add defaultMeta        │
│ add timestamp/session  ���
│ run beforeSend()       │ → null → drop
└───────┬───────────────┘

┌─ Transport ───────────┐
│ fire-and-forget        │
└───────────────────────┘

LogVista — Edge-native structured logging API