Request Context

Table of contents

  1. Request Context
    1. Log Tracer
    2. Header Propagation
    3. Configuration
    4. getRequestContext
      1. Usage
    5. runWithContext
      1. Usage

Request Context

Orka by default exposes a Request Context to the app.

It can be used for setting/getting variables that can be accessible in every code file (within the request’s life). It uses nodeJS async_hooks to store this information.

By default it appends in the request context: requestId, visitor (if you have the option config.visitor.cookie), ddSpan(if you have DataDog enabled), and propagatedHeaders that holds Istio trace context headers (if you have the option config.requestContextl.enabled). The requestId is retrieved using the option config.traceHeaderName

Log Tracer

If the Request Context is enabled, orka by default appends requestId, correlationId and visitor to all the application logs automatically.

Header Propagation

Header propagation enabled by default as long as the current nodejs version supports AsyncLocalStorage (async_hooks).

If option config.requestContext.propagatedHeaders is enabled, orka propagates some Istio trace context headers and cloudflare cf-ray from incoming http requests to:

  • outbound http requests
  • rabbitmq messages
  • kafka messages

By default the following headers are propagated:

  • “cf-ray”
  • “x-request-id”
  • “x-b3-traceid”
  • “x-b3-spanid”
  • “x-b3-parentspanid”
  • “x-b3-sampled”
  • “x-b3-flags”
  • “x-ot-span-context”
  • “x-depth”

This list can be modified by changing config.requestContext.propagatedHeaders.headers.

Configuration

If you don’t specify anything in your config.requestContext it defaults to:

{
  "requestContext": {
    "enabled": true,
    "logKeys": ["requestId", "visitor", "correlationId", "propagatedHeaders"],  // These are the keys that will be appended automatically to your logs
    "propagatedHeaders": {
      "enabled": true,
      "headers": ["cf-ray", "x-request-id", "x-b3-traceid", "x-b3-spanid", "x-b3-parentspanid", "x-b3-sampled", "x-b3-flags", "x-ot-span-context"]
    }
  }
}

getRequestContext

This method can be used to access the request context within your app.

Returns: A Map<string, any> with the current request context

e.g.

import { getRequestContext } from '@workablehr/orka';

Usage

Using the request context on another file:

// src/app.js
builder({...})
  .useDefaults()
  .start()

// src/services/a-service.js called after a HTTP call
import {getRequestContext, getLogger} from '@workablehr/orka'

export const method = async () => {
  const ctx = getRequestContext();
  const id = ctx.get('requestId');
  // id = a-uid
  getLogger('log').info('An informative log');
  // Logs for json
  // {
  //   "timestamp":"2020-11-18T19:38:14.810Z",
  //   "severity":"INFO",
  //   "categoryName":"log",
  //   "message":"An informative log",
  //   "context":{
  //     "requestId": "a-uid"
  //   }
  // }
  // Logs for console
  // ["2020-11-18T19:38:14.810Z"] [INFO] [log] [a-uid] An informative log
};

Example of setting a variable in request context:

// src/app.js
builder({...})
  .useDefaults()
  .start()

// src/config/routes.js
import {getRequestContext} from '@workablehr/orka'

module.exports = {
  get: {
    '/test': async (ctx, next) => {
      await service.method();
    },
  },
  prefix: {
    '/foo': async (ctx, next) => {
      getRequestContext().set('var', 'test');
      await next();
    }
  }
};

// src/services/a-service.js called after a HTTP call
import {getRequestContext} from '@workablehr/orka'

export const method = async () => {
  console.log(getRequestContext().get('var')); // prints test
};

runWithContext

This method can be used to execute a callback within a context.

e.g.

import { runWithContext } from '@workablehr/orka';

Usage

Using the request context on another file:


// src/handler.js
import {runWithContext} from '@workablehr/orka'

module.exports = {
  test: () => {
    const store = Map([['requestId', 'trace-id']])
    return runWithContext(store, service.method, 'arg1', 'arg2');
  }
};

// src/services/a-service.js called after a HTTP call
import {getRequestContext} from '@workablehr/orka'

export const method = async (arg1, arg2) => {
  console.log(getRequestContext().get('requestId')); // trace-id
};