Skip to content

Trace

Use .trace() to measure the time spent in each request lifecycle and its handlers. It helps you find the slow part before changing code.

Trace uses callback listeners to report when each lifecycle event starts and ends. An onStop callback finishes before the next lifecycle event runs.

First install the trace capability with .use(trace()), imported from elysia/trace. Then register a .trace() callback on the instance to subscribe to lifecycle events.

You may listen to each lifecycle by adding an on prefix followed by the lifecycle name, for example onHandle to listen to the handle event.

import { Elysia } from 'elysia'
import { trace } from 'elysia/trace'
const app = new Elysia()
.use(trace())
.trace(async ({ onHandle }) => {
onHandle(({ begin, onStop }) => {
onStop(({ end }) => {
console.log('handle took', end - begin, 'ms')
})
})
})
.get('/', () => 'Hi')
.listen(3000)

Please refer to Life Cycle Events for more information:

Lifecycle groups expose child events for their registered hooks. handle represents the route handler itself; use onEvent on a hook group to measure each hook.

You can use onEvent to listen to each child event in order

import { Elysia } from 'elysia'
import { trace } from 'elysia/trace'
const sleep = (time = 1000) =>
new Promise((resolve) => setTimeout(resolve, time))
const app = new Elysia()
.use(trace())
.trace(async ({ onBeforeHandle }) => {
onBeforeHandle(({ total, onEvent }) => {
console.log('total children:', total)
onEvent(({ onStop }) => {
onStop(({ elapsed }) => {
console.log('child took', elapsed, 'ms')
})
})
})
})
.get('/', {
beforeHandle: [
function prepare() {},
async function delay() {
await sleep()
}
]
}, () => 'Hi')
.listen(3000)

In this example, total children will be 2 because there are 2 children in the beforeHandle event.

Then we listen to each child event by using onEvent and print the duration of each child event.

The callback passed to .trace() receives the request’s trace context:

import { Elysia } from 'elysia'
import { trace } from 'elysia/trace'
const app = new Elysia()
.use(trace())
// This is trace parameter
// hover to view the type
.trace((parameter) => {
})
.get('/', () => 'Hi')
.listen(3000)

trace accepts the following parameters:

A per-request UUID string, useful for correlating logs.

Elysia’s Context, eg. set, store, query, params

Shortcut for context.set, to set headers or the status of the context

Shortcut for context.store, to access data in the context

Timestamp of when the request is called

An event listener for each life-cycle event.

You may listen to the following life-cycle events:

  • onRequest - get notified of every new request
  • onParse - array of functions to parse the body
  • onTransform - transform request and context before validation
  • onBeforeHandle - custom requirement to check before the main handler, can skip the main handler if a response is returned.
  • onHandle - function assigned to the path
  • onAfterHandle - interact with the response before sending it back to the client
  • onMapResponse - map returned value into a Web Standard Response
  • onError - handle errors thrown while processing a request
  • onAfterResponse - cleanup function after the response is sent

A listener for each life-cycle event

import { Elysia } from 'elysia'
import { trace } from 'elysia/trace'
const app = new Elysia()
.use(trace())
.trace(({ onBeforeHandle }) => {
// This is trace listener
// hover to view the type
onBeforeHandle((parameter) => {
})
})
.get('/', () => 'Hi')
.listen(3000)

Each lifecycle listener accepts the following

The name of the function. If the function is anonymous, the name will be anonymous

The time when the function is started

The time when the function ends. The promise will be resolved when the function ends

Error that was thrown in the lifecycle. The promise will be resolved when the function ends

onStop - callback?: (detail: TraceEndDetail) => any

Section titled “onStop - callback?: (detail: TraceEndDetail) => any”

A callback that will be executed when the lifecycle ends

import { Elysia } from 'elysia'
import { trace } from 'elysia/trace'
const app = new Elysia()
.use(trace())
.trace(({ onBeforeHandle, set }) => {
onBeforeHandle(({ onStop }) => {
onStop(({ elapsed }) => {
set.headers['X-Elapsed'] = elapsed.toString()
})
})
})
.get('/', () => 'Hi')
.listen(3000)

It’s recommended to mutate context in this function as there’s a lock mechanism to ensure the context is mutated successfully before moving on to the next lifecycle event

A parameter that is passed to the onStop callback

The time when the function is ended

Error that was thrown in the lifecycle

Elapsed time of the lifecycle or end - begin

Type to search the documentation.

    Up arrowDown arrow to navigateEnter to selectEscape to close