-
Notifications
You must be signed in to change notification settings - Fork 38
feat(automation): integrate .NET instrumentation watcher #421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Pittu-Sharma
wants to merge
29
commits into
open-telemetry:main
Choose a base branch
from
Pittu-Sharma:feat/dotnet-instrumentation-watcher
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 8 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
c26bddb
feat: integrate .NET instrumentation watcher
Pittu-Sharma adf5fc4
style: run prettier format check fixes
Pittu-Sharma 9daeef2
Refactor .NET instrumentation watcher to use NuGet V3 Search API
Pittu-Sharma bc9f0fb
trigger ci: re-run workflows
Pittu-Sharma 1b14238
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 8b02341
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 1628d32
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 1f360f7
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma c27f3c7
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 5091e8b
Address mentor feedback: Use NuGet service index, include prerelease,…
Pittu-Sharma 8d3b2fd
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 7e7065b
fix(dotnet-watcher): address mentor review feedback
Pittu-Sharma 6ab4f7b
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 8e46aa2
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 917a264
fix(.net-watcher): correct versioning and filter deprecated packages
Pittu-Sharma 1236676
Merge branch 'feat/dotnet-instrumentation-watcher' of https://github.…
Pittu-Sharma 5945063
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 13190d8
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 880f805
refactor(api): address copilot feedback on resilience and caching
Pittu-Sharma 462a137
chore: remove unused files, revert glow badge changes, and fix result…
Pittu-Sharma b7ca795
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 46a7bd5
Merge branch 'main' from upstream to resolve conflicts
Pittu-Sharma fcf9570
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma fd28c6d
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 779e4c9
Merge branch 'main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma 1b17c11
chore: remove accidental files from other branches in PR #421
Pittu-Sharma ed77be6
chore: revert all accidental UI changes to match main
Pittu-Sharma 7fa0e87
Merge branch 'upstream/main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma cb27902
Merge branch 'upstream/main' into feat/dotnet-instrumentation-watcher
Pittu-Sharma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # .NET Integration Roadmap | ||
|
|
||
| This document outlines the proposed strategy and roadmap for fully integrating the `.NET` ecosystem | ||
| into the OpenTelemetry Ecosystem Explorer. | ||
|
|
||
| ## Phase 1: Metadata Collection (Completed) | ||
|
|
||
| - [x] Create a `dotnet-instrumentation-watcher` component within `ecosystem-automation`. | ||
| - [x] Design a programmatic scraper to dynamically fetch `.NET` repositories | ||
| (`open-telemetry/opentelemetry-dotnet-contrib`) and parse `.csproj` structures since | ||
| centralized catalog APIs do not exist. | ||
| - [x] Synchronize this data into `ecosystem-registry/dotnet/` with versioned snapshot capability. | ||
| - [x] Ensure structural data uses proper classifications (e.g., `instrumentation`, `exporter`, | ||
| `extension`). | ||
|
|
||
| ## Phase 2: Database Integration (Upcoming) | ||
|
|
||
| - [ ] Extend `explorer-db-builder` to support `.NET` specific processing logic alongside Java Agent | ||
| logic. | ||
| - [ ] Create a `dotnet` specific database writer inside | ||
| `explorer-db-builder/src/explorer_db_builder/database_writer.py`. | ||
| - [ ] Transform `modules` lists generated by the watcher into Explorer-compatible schema elements | ||
| for the SQLite frontend ingest payload. | ||
|
|
||
| ## Phase 3: Frontend Implementation (Upcoming) | ||
|
|
||
| - [ ] Add a new navigation card on the `ecosystem-explorer` Home Page mapping to `/dotnet`. | ||
| - [ ] Create `.NET` specific exploration React components in `ecosystem-explorer/src/pages/dotnet`. | ||
| - [ ] Implement UI data hooks in `use-instrumentations.ts` to fetch and render `.NET` libraries. | ||
| - [ ] Audit accessibility (`aria-labels`, focus indicators) for any new `.NET` specific UI | ||
| components introduced. | ||
14 changes: 0 additions & 14 deletions
14
ecosystem-automation/configuration-watcher/tests/__init__.py
This file was deleted.
Oops, something went wrong.
30 changes: 30 additions & 0 deletions
30
ecosystem-automation/dotnet-instrumentation-watcher/pyproject.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| [project] | ||
| name = "dotnet-instrumentation-watcher" | ||
| version = "0.1.0" | ||
| description = "Automation tool for watching and collecting OpenTelemetry .NET instrumentation metadata" | ||
| requires-python = ">=3.11" | ||
| dependencies = [ | ||
| "PyYAML>=6.0.1", | ||
| "requests>=2.31.0", | ||
| "semantic-version>=2.10.0", | ||
| "watcher-common", | ||
| ] | ||
|
|
||
| [project.scripts] | ||
| dotnet-instrumentation-watcher = "dotnet_instrumentation_watcher.main:main" | ||
|
|
||
| [project.optional-dependencies] | ||
| dev = [ | ||
| "pytest>=8.0.0", | ||
| "pytest-cov>=4.1.0", | ||
| ] | ||
|
|
||
| [build-system] | ||
| requires = ["hatchling"] | ||
| build-backend = "hatchling.build" | ||
|
|
||
| [tool.uv.sources] | ||
| watcher-common = { workspace = true } | ||
|
|
||
| [tool.hatch.build.targets.wheel] | ||
| packages = ["src/dotnet_instrumentation_watcher"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
...mation/dotnet-instrumentation-watcher/src/dotnet_instrumentation_watcher/dotnet_client.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| # Copyright The OpenTelemetry Authors | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
| """NuGet API client for fetching .NET instrumentation data.""" | ||
|
|
||
| import logging | ||
| from typing import Any, Dict, List | ||
|
|
||
| import requests | ||
| from requests.adapters import HTTPAdapter | ||
| from urllib3 import Retry | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class NuGetAPIError(Exception): | ||
| """Custom exception for NuGet API errors.""" | ||
|
|
||
| pass | ||
|
|
||
|
|
||
| class DotNetInstrumentationClient: | ||
| """Client for fetching .NET instrumentation metadata from NuGet.""" | ||
|
|
||
| SEARCH_URL = "https://azuresearch-usnc.nuget.org/query" | ||
|
Pittu-Sharma marked this conversation as resolved.
Outdated
|
||
| OWNER = "OpenTelemetry" | ||
| TIMEOUT = 30 | ||
|
|
||
| def __init__(self): | ||
| """Initialize the client.""" | ||
| self._session = requests.Session() | ||
|
|
||
| retry_strategy = Retry( | ||
| total=3, | ||
| backoff_factor=1, | ||
| status_forcelist=[429, 500, 502, 503, 504], | ||
| ) | ||
|
|
||
| adapter = HTTPAdapter(max_retries=retry_strategy) | ||
| self._session.mount("https://", adapter) | ||
|
|
||
| def fetch_instrumentation_list(self) -> Dict[str, Any]: | ||
| """ | ||
| Fetch instrumentation list by querying NuGet for packages owned by OpenTelemetry. | ||
| """ | ||
| all_packages = self._fetch_all_packages_by_owner(self.OWNER) | ||
| modules = [] | ||
|
|
||
| for pkg in all_packages: | ||
| # Skip deprecated packages | ||
| if pkg.get("deprecation"): | ||
| logger.info(f" Skipping deprecated package: {pkg.get('id')}") | ||
| continue | ||
|
|
||
| package_id = pkg.get("id", "") | ||
| version = pkg.get("version", "") | ||
| description = pkg.get("description", "") | ||
|
|
||
| # Filter and classify packages | ||
| if "Instrumentation" in package_id: | ||
| component_type = "instrumentation" | ||
| elif "Exporter" in package_id: | ||
| component_type = "exporter" | ||
| elif "Extensions" in package_id or "Resources" in package_id or "Sampler" in package_id: | ||
| component_type = "extension" | ||
| else: | ||
| # Skip core packages like OpenTelemetry, OpenTelemetry.Api unless they match patterns | ||
| # but we might want to include them as 'core' if needed. | ||
| # For now, let's stick to the previous classification logic. | ||
| continue | ||
|
|
||
| modules.append( | ||
| { | ||
| "name": package_id, | ||
| "description": description or f"{package_id} for OpenTelemetry", | ||
| "type": component_type, | ||
| "version": version, | ||
| } | ||
| ) | ||
|
|
||
| # Sort by name for consistency | ||
| modules.sort(key=lambda x: x["name"]) | ||
|
|
||
| return {"modules": modules} | ||
|
|
||
| def get_core_version(self) -> str: | ||
| """ | ||
| Get the latest version of the core OpenTelemetry package. | ||
| This is used as the 'ecosystem version' for the registry. | ||
| """ | ||
| params = { | ||
| "q": "PackageId:OpenTelemetry", | ||
| "prerelease": "false", | ||
| "take": 1, | ||
| } | ||
| try: | ||
| response = self._session.get(self.SEARCH_URL, params=params, timeout=self.TIMEOUT) | ||
| response.raise_for_status() | ||
| data = response.json() | ||
| if data.get("data"): | ||
| return data["data"][0]["version"] | ||
| return "1.0.0" | ||
| except (requests.RequestException, KeyError, IndexError) as e: | ||
| logger.error(f"Error fetching core version: {e}") | ||
| return "1.0.0" | ||
|
Pittu-Sharma marked this conversation as resolved.
Outdated
|
||
|
|
||
| def _fetch_all_packages_by_owner(self, owner: str) -> List[Dict[str, Any]]: | ||
| """Fetch all packages for a specific owner using pagination.""" | ||
| packages = [] | ||
| skip = 0 | ||
| take = 20 | ||
|
|
||
| while True: | ||
| params = { | ||
| "q": f"owner:{owner}", | ||
| "prerelease": "false", | ||
|
Pittu-Sharma marked this conversation as resolved.
Outdated
|
||
| "skip": skip, | ||
| "take": take, | ||
| } | ||
| try: | ||
| response = self._session.get(self.SEARCH_URL, params=params, timeout=self.TIMEOUT) | ||
| response.raise_for_status() | ||
| data = response.json() | ||
|
|
||
| batch = data.get("data", []) | ||
| packages.extend(batch) | ||
|
|
||
| if len(batch) < take: | ||
| break | ||
|
|
||
| skip += take | ||
| except requests.RequestException as e: | ||
| raise NuGetAPIError(f"Error fetching packages from NuGet: {e}") from e | ||
|
|
||
| return packages | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.