Skip to content

feat(js): add JavaScript instrumentation watcher and initial registry#577

Merged
jaydeluca merged 8 commits into
open-telemetry:mainfrom
MeloveGupta:feat/js-instrumentation-watcher
Jun 24, 2026
Merged

feat(js): add JavaScript instrumentation watcher and initial registry#577
jaydeluca merged 8 commits into
open-telemetry:mainfrom
MeloveGupta:feat/js-instrumentation-watcher

Conversation

@MeloveGupta

Copy link
Copy Markdown
Contributor

What

Adds a Phase 1 watcher for the opentelemetry-js-contrib ecosystem that walks the repository and generates per-package versioned YAML entries in the registry.

How it works

The watcher clones (or reuses) the opentelemetry-js-contrib repo, discovers all active packages/instrumentation-* directories, and for each package reads:

  • package.json - name, version, description, source path, node engine
  • .github/component_owners.yml - component owners per package
  • auto-instrumentations-node/package.json deps - bundle membership
  • README ### Supported Versions section - supported library version ranges
  • .tav.yml - tested version ranges (handles both versions: and jobs: structures used across the ecosystem)

Registry layout

JS packages version independently so the registry is per-package, not per-release:

ecosystem-registry/javascript/{package}/v{version}.yaml

Output

Running the watcher against the current js-contrib HEAD produces 46 registry entries, all active instrumentation packages.

Example entry

name: instrumentation-express
npm_package: '@opentelemetry/instrumentation-express'
version: 0.66.0
description: OpenTelemetry instrumentation for `express` http web application framework
source_path: packages/instrumentation-express
repository: open-telemetry/opentelemetry-js-contrib
node_engine: ^18.19.0 || >=20.6.0
in_auto_instrumentations_node: true
component_owners:
  - JamieDanielson
  - pkanal
  - raphael-theriault-swi
supported_versions:
  - package: express
    version_range: '>=4.0.0 <6'
    source: README.md
tested_versions:
  - package: express
    range: '>=4.16.2 <6'
    mode: latest-minors
    source: .tav.yml

Known gaps (Phase 2)

  • Telemetry data (spans/metrics/attributes) - only 8/47 packages have structured data and all use different heading formats
  • Stability level - not in any structured field upstream
  • supported_versions for packages that use non-standard README formats (e.g. instrumentation-aws-sdk)

Tests

8 unit tests covering package parsing, inventory management, and version path formatting. All passing.

Related to #9

@MeloveGupta MeloveGupta requested review from a team as code owners May 23, 2026 22:40
@netlify

netlify Bot commented May 23, 2026

Copy link
Copy Markdown

Deploy Preview for otel-ecosystem-explorer canceled.

Name Link
🔨 Latest commit d6f2686
🔍 Latest deploy log https://app.netlify.com/projects/otel-ecosystem-explorer/deploys/6a3c2713cdca210008a34d12

@MeloveGupta

Copy link
Copy Markdown
Contributor Author

Hey @jaydeluca ,
All checks passing are passing and the watcher runs against the current js-contrib HEAD and produces 46 registry entries, one per active instrumentation package.

Could you review it?
Next I can add a test for the package scanner next, or start looking at how the db-builder would need to be extended to consume the javascript registry path...

@vitorvasc

Copy link
Copy Markdown
Member

Hi @MeloveGupta, thanks for your contribution!

Just a tip: you don't need to tag the approvers / maintainers every time you open a PR - GitHub already does this automatically. It might take a bit since maintainers have a lot going on, but don't worry, your PR will get reviewed. If it's been over a week with no activity, feel free to tag someone then.

Thanks!

Comment on lines +21 to +22
"PyYAML>=6.0.1",
"GitPython>=3.1.40",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just removed the need for these dependencies from the other modules in #600 could you take a look and do the same thing for this new watcher?

"""
Manages storage of JS instrumentation metadata in the registry.

Registry layout (per maintainer direction):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Registry layout (per maintainer direction):
Registry layout:

Comment on lines +32 to +34

Each package is versioned independently — there is no single
aggregated version file like the Java watcher uses.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Each package is versioned independentlythere is no single
aggregated version file like the Java watcher uses.

# limitations under the License.
#

"""Tests for InventoryManager."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to add a new job to the https://github.com/open-telemetry/opentelemetry-ecosystem-explorer/blob/main/.github/workflows/build-and-test.yml#L53 workflow to run the tests for this module in CI

"source": "README.md",
})

return results

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whenever possible with watchers we want to sort things so that the data is always written in a deterministic way

Suggested change
return results
return sorted(results, key=lambda x: (x["package"], x["version_range"]))

if isinstance(versions, dict) and versions:
results.append(self._build_tav_entry(pkg_name, versions))

return results No newline at end of file

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return results
return sorted(results, key=lambda x: (x["package"], x["range"]))

Comment on lines +155 to +160
entry: dict = {
"package": pkg_name,
"range": versions.get("include", ""),
"mode": versions.get("mode", ""),
"source": ".tav.yml",
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do the same pattern we're using for exclude and only add this when not empty

Suggested change
entry: dict = {
"package": pkg_name,
"range": versions.get("include", ""),
"mode": versions.get("mode", ""),
"source": ".tav.yml",
}
entry: dict = {
"package": pkg_name,
"range": versions.get("include", ""),
"source": ".tav.yml",
}
mode = versions.get("mode", "")
if mode:
entry["mode"] = mode

COMPONENT_OWNERS_FILE = ".github/component_owners.yml"


class PackageScanner:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this class has enough logic in it that i think it deserves some tests

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Python watcher to sync metadata for opentelemetry-js-contrib instrumentation packages into the repo’s versioned registry, plus an initial generated snapshot of the JS registry output.

Changes:

  • Introduces js-instrumentation-watcher (repo clone/pull, package discovery, metadata parsing, registry writes).
  • Wires the new watcher into the uv workspace and root pyproject.toml.
  • Adds initial ecosystem-registry/javascript/<package>/v<version>.yaml entries for current active packages.

Reviewed changes

Copilot reviewed 59 out of 60 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
uv.lock Adds js-instrumentation-watcher as a workspace package and locks its deps.
pyproject.toml Registers js-instrumentation-watcher in the root workspace/dependencies.
ecosystem-registry/javascript/instrumentation-winston/v0.62.0.yaml Initial generated registry entry for instrumentation-winston.
ecosystem-registry/javascript/instrumentation-web-exception/v0.11.0.yaml Initial generated registry entry for instrumentation-web-exception.
ecosystem-registry/javascript/instrumentation-user-interaction/v0.62.0.yaml Initial generated registry entry for instrumentation-user-interaction.
ecosystem-registry/javascript/instrumentation-undici/v0.28.0.yaml Initial generated registry entry for instrumentation-undici.
ecosystem-registry/javascript/instrumentation-typeorm/v0.18.0.yaml Initial generated registry entry for instrumentation-typeorm.
ecosystem-registry/javascript/instrumentation-tedious/v0.37.0.yaml Initial generated registry entry for instrumentation-tedious.
ecosystem-registry/javascript/instrumentation-socket.io/v0.65.0.yaml Initial generated registry entry for instrumentation-socket.io.
ecosystem-registry/javascript/instrumentation-sequelize/v0.11.0.yaml Initial generated registry entry for instrumentation-sequelize.
ecosystem-registry/javascript/instrumentation-runtime-node/v0.31.0.yaml Initial generated registry entry for instrumentation-runtime-node.
ecosystem-registry/javascript/instrumentation-router/v0.62.0.yaml Initial generated registry entry for instrumentation-router.
ecosystem-registry/javascript/instrumentation-restify/v0.63.0.yaml Initial generated registry entry for instrumentation-restify.
ecosystem-registry/javascript/instrumentation-redis/v0.66.0.yaml Initial generated registry entry for instrumentation-redis.
ecosystem-registry/javascript/instrumentation-pino/v0.64.0.yaml Initial generated registry entry for instrumentation-pino.
ecosystem-registry/javascript/instrumentation-pg/v0.70.0.yaml Initial generated registry entry for instrumentation-pg.
ecosystem-registry/javascript/instrumentation-oracledb/v0.43.0.yaml Initial generated registry entry for instrumentation-oracledb.
ecosystem-registry/javascript/instrumentation-openai/v0.16.0.yaml Initial generated registry entry for instrumentation-openai.
ecosystem-registry/javascript/instrumentation-net/v0.62.0.yaml Initial generated registry entry for instrumentation-net.
ecosystem-registry/javascript/instrumentation-nestjs-core/v0.64.0.yaml Initial generated registry entry for instrumentation-nestjs-core.
ecosystem-registry/javascript/instrumentation-mysql2/v0.64.0.yaml Initial generated registry entry for instrumentation-mysql2.
ecosystem-registry/javascript/instrumentation-mysql/v0.64.0.yaml Initial generated registry entry for instrumentation-mysql.
ecosystem-registry/javascript/instrumentation-mongoose/v0.64.0.yaml Initial generated registry entry for instrumentation-mongoose.
ecosystem-registry/javascript/instrumentation-mongodb/v0.71.0.yaml Initial generated registry entry for instrumentation-mongodb.
ecosystem-registry/javascript/instrumentation-memcached/v0.61.0.yaml Initial generated registry entry for instrumentation-memcached.
ecosystem-registry/javascript/instrumentation-lru-memoizer/v0.62.0.yaml Initial generated registry entry for instrumentation-lru-memoizer.
ecosystem-registry/javascript/instrumentation-long-task/v0.62.0.yaml Initial generated registry entry for instrumentation-long-task.
ecosystem-registry/javascript/instrumentation-langchain/v0.6.0.yaml Initial generated registry entry for instrumentation-langchain.
ecosystem-registry/javascript/instrumentation-koa/v0.66.0.yaml Initial generated registry entry for instrumentation-koa.
ecosystem-registry/javascript/instrumentation-knex/v0.62.0.yaml Initial generated registry entry for instrumentation-knex.
ecosystem-registry/javascript/instrumentation-kafkajs/v0.27.0.yaml Initial generated registry entry for instrumentation-kafkajs.
ecosystem-registry/javascript/instrumentation-ioredis/v0.66.0.yaml Initial generated registry entry for instrumentation-ioredis.
ecosystem-registry/javascript/instrumentation-hapi/v0.64.0.yaml Initial generated registry entry for instrumentation-hapi.
ecosystem-registry/javascript/instrumentation-graphql/v0.66.0.yaml Initial generated registry entry for instrumentation-graphql.
ecosystem-registry/javascript/instrumentation-generic-pool/v0.61.0.yaml Initial generated registry entry for instrumentation-generic-pool.
ecosystem-registry/javascript/instrumentation-fs/v0.37.0.yaml Initial generated registry entry for instrumentation-fs.
ecosystem-registry/javascript/instrumentation-express/v0.66.0.yaml Initial generated registry entry for instrumentation-express.
ecosystem-registry/javascript/instrumentation-document-load/v0.63.0.yaml Initial generated registry entry for instrumentation-document-load.
ecosystem-registry/javascript/instrumentation-dns/v0.61.0.yaml Initial generated registry entry for instrumentation-dns.
ecosystem-registry/javascript/instrumentation-dataloader/v0.35.0.yaml Initial generated registry entry for instrumentation-dataloader.
ecosystem-registry/javascript/instrumentation-cucumber/v0.34.0.yaml Initial generated registry entry for instrumentation-cucumber.
ecosystem-registry/javascript/instrumentation-connect/v0.61.0.yaml Initial generated registry entry for instrumentation-connect.
ecosystem-registry/javascript/instrumentation-cassandra-driver/v0.63.0.yaml Initial generated registry entry for instrumentation-cassandra-driver.
ecosystem-registry/javascript/instrumentation-bunyan/v0.63.0.yaml Initial generated registry entry for instrumentation-bunyan.
ecosystem-registry/javascript/instrumentation-browser-navigation/v0.11.0.yaml Initial generated registry entry for instrumentation-browser-navigation.
ecosystem-registry/javascript/instrumentation-aws-sdk/v0.73.0.yaml Initial generated registry entry for instrumentation-aws-sdk.
ecosystem-registry/javascript/instrumentation-aws-lambda/v0.70.0.yaml Initial generated registry entry for instrumentation-aws-lambda.
ecosystem-registry/javascript/instrumentation-amqplib/v0.65.0.yaml Initial generated registry entry for instrumentation-amqplib.
ecosystem-automation/js-instrumentation-watcher/tests/test_package_parser.py Unit tests for parsing package.json, README supported versions, and .tav.yml.
ecosystem-automation/js-instrumentation-watcher/tests/test_inventory_manager.py Unit tests for registry write/read path behavior.
ecosystem-automation/js-instrumentation-watcher/tests/init.py Adds a tests package marker file.
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/repository_manager.py Repo setup logic (env override vs clone/pull).
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/package_scanner.py Discovers packages and loads bundle membership / component owners.
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/package_parser.py Extracts metadata from package.json/README/.tav.yml.
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/main.py Watcher entrypoint.
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/inventory_manager.py Writes per-package versioned YAML to registry.
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/instrumentation_sync.py Orchestrates scanning/parsing/writing and produces a summary.
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/main.py Enables python -m js_instrumentation_watcher.
ecosystem-automation/js-instrumentation-watcher/src/js_instrumentation_watcher/init.py Package init file.
ecosystem-automation/js-instrumentation-watcher/pyproject.toml Defines the new watcher package, deps, and console script entrypoint.

Comment on lines +86 to +89
try:
data = json.loads(auto_node_path.read_text())
deps = data.get("dependencies", {})
return set(deps.keys())
Comment on lines +107 to +113
try:
data = yaml.safe_load(owners_path.read_text())
components = data.get("components", {})
result = {}
for path, owners in components.items():
result[path] = owners if isinstance(owners, list) else []
return result
Comment on lines +139 to +140

return results
Comment on lines +233 to +235
results.append(self._build_tav_entry(pkg_name, versions))

return results No newline at end of file
Comment on lines +188 to +191
Returns:
List of dicts with package, range, mode, source, and optionally
exclude fields. Empty fields are omitted.
"""
Comment on lines +25 to +38
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)

REGISTRY_DIR = "ecosystem-registry/javascript"


def main() -> None:
"""Main entry point for the JS instrumentation watcher."""
base_dir = os.environ.get("JS_CONTRIB_REPOS_DIR", "tmp_repos")

logger.info("Starting JS instrumentation watcher...")
Comment on lines +22 to +23
import pytest
import yaml
@jaydeluca

Copy link
Copy Markdown
Member

going to mark this is as draft to help with bookkeeping. Feel free to open back up when review comments are addressed

@jaydeluca jaydeluca marked this pull request as draft June 5, 2026 17:36
@MeloveGupta MeloveGupta marked this pull request as ready for review June 22, 2026 19:34
@MeloveGupta

MeloveGupta commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

Hey @jaydeluca , I've pushed fixes for all the review feedback.
Summary of changes:

  • Removed PyYAML/GitPython from pyproject.toml
  • supported_versions and tested_versions are now sorted deterministically so upstream YAML reordering doesn't churn the registry
  • mode is now omitted when empty, same pattern as exclude
  • Added type guards in package_scanner.py for malformed package.json / component_owners.yml
  • Moved logging config inside main()
  • Switched to logger.exception() so parse failures keep their stack trace
  • Added test coverage for PackageScanner (10 new tests)
  • Added the CI job for this module

All 23 tests passing, watcher still produces 46 correct registry entries against current js-contrib HEAD.
Can you review these changes and let me know if any other changes are required from my side :)

@jaydeluca jaydeluca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@jaydeluca jaydeluca added this pull request to the merge queue Jun 24, 2026
Merged via the queue into open-telemetry:main with commit 50f0190 Jun 24, 2026
23 checks passed
@otelbot

otelbot Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution @MeloveGupta! 🎉 We would like to hear from you about your experience contributing to OpenTelemetry by taking a few minutes to fill out this survey.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants