npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@discue/open-telemetry-tracing

v1.3.0

Published

Simple scheduling and queueing

Downloads

384

Readme

GitHub tag Latest Stable Version License NPM Downloads NPM Downloads contributions - welcome Made with Node.js

open-telemetry-tracing

Kickstarts your OpenTelemetry implementation with first-class abstractions for

  • adding tracing capabilities to NodeJS environments
  • collecting and publishing of spans to local and cloud environments
  • creating spans and child spans
  • tracking successful completion of spans
  • recording exceptions in case of errors during span execution

Screenshot of traces collected by Jaeger.

Setup

OpenTelemetry and its Instrumentations will inject tracing functionality into well-known and supported packages.

To enable tracing, the tracing runtime needs to be loaded before your application. To do so, set the NODE_OPTIONS environment variable and require the file node_modules/@discue/open-telemetry-tracing/lib/instrumentation.cjs, which is the entry point for tracing.

  • NODE_OPTIONS=--require node_modules/@discue/open-telemetry-tracing/lib/instrumentation.cjs

Instrumentation

Instrumentations are the heart of tracing. Most of the tracing instrumentation is platform-agnostic. However, some parts of it can be platform-dependent.

This module features support for GCP and half-baked support for AWS (due to lack of usage of the platform in other projects). You can find the default instrumentations here:

If you feel instrumentations (or other features) are missing, please get in touch with us and / or open a PR 🙂.

How to create a span

Import the function createTracer function.

import { createTracer } from '@discue/open-telemetry-tracing';

Call the function createTracer and pass the filepath to the current file as an optional parameter.

const { withActiveSpan } = createTracer({
    filepath: import.meta.url
})

Wrap existing or new code inside a call to withActiveSpan. You can add spanEvents to add additional information for later analysis.

/**
 * 
 * @param {_types.Request} req 
 * @param {_types.Response} res 
 * @param {Object} options
 * @returns 
 */
async handleRequest(req, res, { resourceIds }) {
    // creates a new active span with name handle-delete-request
    // will watch execution and record failures
    //
    // pass an object with additional attributes as second parameter
    // to get more key value pairs added to the span
    await withActiveSpan('handle-delete-request', async (span) => {
        const resource = await this._service.get(resourceIds)
        if (resource == null) {
            // custom extension of the span with implementation-specific
            // event and status
            span.addEvent('Not found', { resourceIds })
                .setStatus({ code: SpanStatusCode.ERROR })

            return sendNotFound(res)
        } else {
            await this._service.delete(resourceIds)
            sendOk({ req, res, body: {}, links: {} })
        }
    })
}

See a full implementation e.g. in @stfsy/api-kit/http-post-resource-endpoint.

How to create a span synchronously

To wrap a synchronous function inside a span, use the withActiveSpanSync method. It also accepts a spanAttributes object as optional second parameter.

import { createTracer } from '@discue/open-telemetry-tracing';
import { nanoid } from "nanoid";

const { withActiveSpanSync } = createTracer({
    filepath: import.meta.url
})

/**
 * Creates a url-safe resource id.
 * 
 * @module newResourceId
 * @returns {String}
 */
export const newResourceId = () => {
    // wrap the sync call in a span and return the value
    // that way the tracing is transparent for all callers
    return withActiveSpanSync('create-resource-id', () => {
        return nanoId()
    })
}

See a full implementation e.g. in @stfsy/api-kit/resource-id.

How to create an orphaned span

That is a span that has no parent. Useful if you want to prevent deep nesting of spans. To create an orphan span call the withOrphanedSpan method of the module. The spanAttributes object is optional and can be omitted.

import { createTracer } from '@discue/open-telemetry-tracing';
import { SpanStatusCode } from '@opentelemetry/api';

const { withOrphanedSpan } = createTracer({
    filepath: import.meta.url
})

const { method, headers } = request
const incomingContentType = headers['content-type'] ?? ''
const spanAttributes = { method, incomingContentType }

// checks whether the content type is set
// sets span status accordingly
// adds content-type as a span attribute so it can be queried via UI e.g. Jaeger
await withOrphanedSpan('check-content-type-is-set', spanAttributes, (span) => {
    if (!incomingContentType ) {
        span.addEvent('Check failed').setStatus({ code: SpanStatusCode.ERROR })
        return sendUnsupportedMedia(response)

    } else {
        span.addEvent('Check succeeded').setStatus({ code: SpanStatusCode.OK })
    }

    return nextFunction()
})

See a full implementation e.g. in @stfsy/api-kit/content-type-middleware.

Configuration

The following environment variables can be set:

  • DSQ_OT_TRACING_SERVICE_NAME
    • default: api-kit
  • DSQ_OT_LOCAL_OLTP_URL
    • default: http://127.0.0.1:4318/v1/traces
    • note: for cloud environments automatically, this library will configure the right exporter
  • DSQ_OT_USE_SIMPLE_SPAN_PROCESSOR
    • default: false
  • DSQ_OT_ENABLE_DEBUG_LOGGING
    • default: false

Exports

  • /: The main export is the createTracer function. Import it via @discue/open-telemetry-tracing to create traces as shown above.
  • /status-codes: Returns valid status codes a span can have. Use this expor to not couple your application to the Open Telemetry libraries. Use it via @discue/open-telemetry-tracing/status-codes.
  • /instrumentation: The instrumentation script needs to be loaded via NODE_OPTIONS function. This export is used internally via @discue/open-telemetry-tracing/instrumentation to get ahold of the current tracer. Users of this library should not need to use this export.

Test

./test.sh

License

MIT