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

opentelemetry-instrumentation-jest

v0.1.7

Published

Adds opentelemetry tracing instrumentation for Jest tests. Traces each test in a nicely wrapped up root trace.

Downloads

489

Readme

opentelemetry-instrumentation-jest

Adds opentelemetry tracing instrumentation for Jest tests. Traces each test in a nicely wrapped up root trace.

Installation

Install the package with

npm install opentelemetry-instrumentation-jest

or

yarn add opentelemetry-instrumentation-jest

Usage

You must do two things to set this library up:

  • start using this library's custom Jest environment
  • start using this library's custom Jest runtime (via an undocumented option)
  • register this library's instrumentations inside a setupFilesAfterEnv jest setup file.

Your jest config should look like this:

// in jest.config.js
module.exports = {
  // ...
  testEnvironment: "opentelemetry-instrumentation-jest/dist/src/node-environment",
  runtime: "opentelemetry-instrumentation-jest/dist/src/runtime",
  setupFilesAfterEnv: [
    "opentelemetry-instrumentation-jest/dist/src/register",
    // ...
  ],
  // ...
};

If you're already using a custom environment, see the Wrapping another environment.

Wrapping another environment

opentelemetry-instrumentation-jest exports environment entrypoints that correctly wrap the jest-environment-node, jest-environment-jsdom, and setup-polly-jest. If you need to use one of these environments, you can use one of the built in exports from this library:

| Environment | Instrumented Entrypoint | | ------------------------ | ----------------------------------------------------------------- | | jest-environment-node | "opentelemetry-instrumentation-jest/dist/src/node-environment" | | jest-environment-jsdom | "opentelemetry-instrumentation-jest/dist/src/jsdom-environment" | | setup-polly-jest | "opentelemetry-instrumentation-jest/dist/src/setup-polly-jest" |

If you're using a different environment however, you must wrap that environment yourself. In your custom environment file, pass the custom environment class to the instrumentEnvironment function from this library.

import NodeEnvironment from "jest-environment-node";
import { instrumentEnvironment } from "opentelemetry-instrumentation-jest";

class MyCustomEnvironment extends NodeEnvironment {
  // ...
}

// wrap the environment before returning it
export default instrumentEnvironment(MyCustomEnvironment);

The returned class will run the correct jest hooks for setting up spans around each test.

Instrumentation strategy

This library sucked to write and relies on nasty hacks to work. There's three main design goals with it:

  • wrap each test's execution in an independent opentelemetry trace, including that test's beforeEach etc hooks
  • ensure that any spans created during the test's execution belong to that main trace
  • ensure instrumentation libraries within the jest test vm work ok

Both otel and jest really fight against doing any this. For the first requirement, the only reliable way to hook into jest's execution at a low-enough layer that all beforeEaches etc are all visible is using a custom environment, which lives outside the the test context. Within the test context, I couldn't find a way to register the instrumentation early enough to capture all beforeAll/beforeEach calls and ensure that they too are included in a test's trace. Instead, we use a jest environment, which gets nice events for test_start and test_done which wrap the whole stack of stuff the test does.

Adding a test environment is annoying for usage though, as it means wrapping any other test environment you might be using already. And, just a test environment is insufficient -- we need to also set up a trace around each test's execution. Critically, this setup must be done within the same context as the code running the test (and the code under test) so that the parent tracking of all the spans and the trace exporter are all the normal one you might use in your own code. This means we need some code on the outside of jest's test context for the environment events, and on the inside to correctly monkeypatch and set up the otel context.

Otel itself has no way to activate a trace for everything that is happening within a node process for a bit. When jest runs a test, it is a global affair -- it's the only thing going on. This isn't normal for node, but for reading test trace output, is critical -- there shouldn't be some units of work which don't propagate the test trace parent and appear as other root traces. So, we need to resort to mutable context hacks to set a global root trace for each test. Nasty.

Worse (somehow) is the instrumentation strategy. Jest's require patches break require-in-the-middle, which is the monkeypatching library that all the opentelemetry instrumentation packages use to hook in and modify stuff. require-in-the-middle's hooks never get run when jest in place. So, to allow the instrumentations to modify required modules, this library mocks out require-in-the-middle itself, capturing all the module require calls that any instrumentation tries to make. Then, there's a custom runtime subclass which hooks into jest's require mechanism, and gives the hooks a chance to run. It's gross, and it feels bad to patch jest's require to allow a different library to patch require to then patch other libraries. Really says something about us you know.