docs

Bentocache

Trace Bentocache and @adonisjs/cache operations with @unhandled/instrumentation-bentocache, including keys, hits and tiers.

@unhandled/instrumentation-bentocache records one span per Bentocache operation. It also covers @adonisjs/cache, which runs a BentoCache underneath. Your app needs bentocache 1.6.0 or later (below 2.0).

Install

Terminal
npm install @unhandled/instrumentation-bentocache

Register with the AdonisJS agent

Add the integration to config/unhandled.ts. Installing the package alone does nothing.

ts
import env from '#start/env'
import { defineConfig } from '@unhandled/agent-adonisjs'
import { bentocache } from '@unhandled/instrumentation-bentocache/integration'

export default defineConfig({
  dsn: env.get('UNHANDLED_DSN'),
  integrations: [bentocache({ requireParentSpan: true })],
})

bentocache({ enabled: false }) turns it off without removing it. If bentocache cannot be resolved, the agent fails at startup with an IntegrationSetupError whose cause is a BentocacheNotInstalledError naming the missing package.

Register standalone

With any other OpenTelemetry setup, register the instrumentation before bentocache is imported:

ts
import { registerInstrumentations } from '@opentelemetry/instrumentation'
import { BentocacheInstrumentation } from '@unhandled/instrumentation-bentocache'

const instrumentation = new BentocacheInstrumentation({ includeKeys: true })
registerInstrumentations({ instrumentations: [instrumentation] })

In ESM apps the module hook needs the import-in-the-middle loader. If your setup misses the import, patch the module yourself with instrumentation.patch(await import('bentocache')).

Options

OptionDefaultEffect
enabledtrueIntegration only. false skips it.
requireParentSpanfalseOnly create spans when a span is already active.
includeKeystruefalse leaves cache.key and cache.keys off every span.
keySanitizermasks IDs(key) => string | undefined. Replaces the default sanitizer.

The default sanitizer splits the key on : and replaces every UUID, all-digit segment and hex segment of 8 or more characters with *. products:4821:price becomes products:*:price. Keys include the prefix you configured in Bentocache. The sanitizer is also exported as sanitizeCacheKey if you want to build on it.

Turn on requireParentSpan if cache calls made outside requests and jobs would otherwise show up as background spans.

What it records

One INTERNAL span per operation, named cache.<operation>: cache.get, cache.set, cache.getOrSet, cache.factory, cache.delete, cache.deleteMany, cache.clear and cache.expire. Operations that run during another one, such as the factory and the write inside a getOrSet, are its children. A failure records the exception and sets ERROR status.

AttributeWhen
cache.operationAlways
cache.storeAlways
cache.keyWith includeKeys, when the operation has a key
cache.keysWith includeKeys, when the operation has several keys (deleteMany)
cache.hitget and getOrSet
cache.tierget hits: l1 or l2
cache.gracedget hits: whether the value came from the grace period

cache.operation puts the span in the cache category, and cache.hit drives the hit rate on the cache page.

Bentocache's own L2 calls (Redis, database) and bus messages run with tracing suppressed, so they do not add Redis or SQL spans under every cache call. This works by wrapping the BentoCache constructor. If the module's exports are read-only, the wrapper is skipped with a diagnostic warning and those internal spans appear.