Skip to content

RecallGraph/foxx-tracer

development
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 

foxx-tracer

An OpenTracing library for Foxx Microservices.

# In your foxx application root
npm install --save @recallgraph/foxx-tracer

See https://recallgraph.github.io/foxx-tracer/ for the full API documentation. A quickstart guide is given below.

Why foxx-tracer

Most tracing libraries in the nodeverse are asynchronous, and so do not work in the synchronous V8 runtime that ArangoDB uses to run its Foxx services. foxx-tracer bridges this gap by being a 100% synchronous, dedicated module built for the Foxx runtime.

As a result, it relies on a number of features only available in a Foxx environment. It also depends on a companion collector service which itself is a Foxx microservice. These dependencies make this module incompatible with Node.js and browser-based runtimes.

Quickstart

Instrument Your Code

  1. Add foxx-tracer as a dependency of the service for which you want to enable tracing.
    npm install --save @recallgraph/foxx-tracer
  2. In your service, before mounting any trace-enabled routes, you need to initialize the tracer, trace headers and middleware. This is best done in your service's startup script (usually main.js).
    const { utils: { setEndpointTraceHeaders, initTracer }, middleware } = require('foxx-tracer')
    
    // Initialize the tracer
    initTracer()
    
    // Use the tracing middleware for all endpoints.
    // You may also do this selectively for only those endpoints that you want to trace.
    module.context.use(middleware)
    
    // Create a router.
    const router = createRouter()
    /*
       Create a request handler endpoint using one of the router's several instance methods:
       const endpoint = router.[get|post|put|patch|delete|all|use](...)
    */
    
    // Attach trace headers to the endpoint
    setEndpointTraceHeaders(endpoint)
  3. To wrap a function in a new span, use attachSpan.
    const { utils: { attachSpan } } = require('foxx-tracer')
    
    attachSpan(function() {}, 'opName', {/* options */}, onSuccess /* optional */, onError /* optional */)
  4. To instrument a db query (with query stats collection and reporting), use instrumentedQuery.
     const { utils: { instrumentedQuery } } = require('foxx-tracer')
    
    const query = aql.query(/* query */)
    const cursor = instrumentedQuery(query, 'queryName', {/* options */})
  5. To correctly propagate the current span context across transaction boundaries, use executeTransaction.
     const { utils: { executeTransaction } } = require('foxx-tracer')
    
    const result = executeTransaction({/* transaction specification */})
  6. To correctly propagate the current span context across task invocations, use executeTask.
     const { utils: { executeTask } } = require('foxx-tracer')
    
    executeTask({/* task options */})

Runtime Setup

  1. Install the collector service and follow its setup instructions. Add any reporter plugins that you need.

  2. In your application's settings, there is a param named sampling-probability. You can set this to a value between 0 and 1 (both inclusive) to tell the tracer how often to record a trace for incoming requests. For example, if sampling-probability = 0.1, then roughly 1 out of 10 requests will be traced.

    Regardless of this param's value, a trace can be force-recorded or force-suppressed using the x-force-sample header parameter. See Recording Traces for details.

  3. Finally, you need to assign the collector dependency so that foxx-tracer knows where to send the recorded traces. The manifest.json file should have a dependencies object containing the following:

    {
        "dependencies": {
            "traceCollector": {
                "name": "@RecallGraph/foxx-tracer-collector",
                "version": "^0.0.5",
                "description": "Opentrace-compatible collector to send span records to.",
                "required": false,
                "multiple": false
            }
        }
    }

    Optional: If, for some reason, you cannot name your dependency as traceCollector (in the unlikely case that it clashes with another dependency key), you can rename it to any other valid manifest key. But then, additional configuration is required to tell the tracer where to find the collector. The manifest.json should now have an additonal setting in configuration, containing the following:

    {
        "configuration": {
            "reporters-foxx": {
                "type": "json",
                "required": true,
                "default": {
                    "collector": "customCollectorDependencyKey"
                },
                "description": "Settings for the foxx reporter."
            }
        }
    }

Recording Traces

For the endpoints to which the trace middleware was attached, there are 4 trace-specific headers available that can be used for the following:

  1. Propagate a running trace from the client to your application.
  2. Force the application to record or suppress a trace for the request, regardless of the sampling-probability setting.

See the Trace Header documentation for details.

Reference Implementation

To get a better idea of how to instrument your Foxx service using foxx-tracer, take a look at the source of the RecallGraph project.