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 methods — logger.ai(), logger.http(), logger.database(), etc.
  • Level methods — logger.info(), logger.error(), logger.fatal(), etc.
  • Raw method — logger.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
apiKeystring—API 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 | null—Transform or drop logs
onError(error, logs) => void—Transport failure callback
onDrop(logs, reason) => void—Dropped 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