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:
Children
Section titled “Children”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.
Trace parameter
Section titled “Trace parameter”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:
id - string
Section titled “id - string”A per-request UUID string, useful for correlating logs.
context - Context
Section titled “context - Context”Elysia’s Context, eg. set, store, query, params
set - Context.set
Section titled “set - Context.set”Shortcut for context.set, to set headers or the status of the context
store - Singleton.store
Section titled “store - Singleton.store”Shortcut for context.store, to access data in the context
time - number
Section titled “time - number”Timestamp of when the request is called
onEvent listeners
Section titled “onEvent listeners”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
Trace listener
Section titled “Trace listener”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
name - string
Section titled “name - string”The name of the function. If the function is anonymous, the name will be anonymous
begin - number
Section titled “begin - number”The time when the function is started
end - Promise<number>
Section titled “end - Promise<number>”The time when the function ends. The promise will be resolved when the function ends
error - Promise<Error | null>
Section titled “error - Promise<Error | null>”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
TraceEndDetail
Section titled “TraceEndDetail”A parameter that is passed to the onStop callback
end - number
Section titled “end - number”The time when the function is ended
error - Error | null
Section titled “error - Error | null”Error that was thrown in the lifecycle
elapsed - number
Section titled “elapsed - number”Elapsed time of the lifecycle or end - begin