A .NET 10 library that provides OpenTelemetry instrumentation (runtime, process, custom CPU %) for .NET 10+ services.
This repository contains two NuGet packages:
- GMO.OpenTelemetry: Core library (net10.0)
- GMO.OpenTelemetry.Serilog: Serilog integration (net10.0)
- Prerequisites
- Getting Started
- Installing the packages
- Configuration
- Usage
- Building & Packaging
- CI/CD Pipeline
- Contributing
- License
- .NET 10 SDK
- OpenTelemetry .NET SDK (transparent package references)
Important: Always run dotnet format src/GMO.OpenTelemetry.sln before build, test, or commit. CI runs dotnet format --verify-no-changes and will fail if encoding or style differs.
Clone, format, and build:
git clone https://github.com/gideonogegaorg/OpenTelemetry.git
cd OpenTelemetry
dotnet format src/GMO.OpenTelemetry.sln
dotnet restore src/GMO.OpenTelemetry.sln
dotnet build src/GMO.OpenTelemetry.sln -c ReleasePackages are published to GitHub Packages. The feed requires authentication to read (username + Personal Access Token). Prefer environment variables for the PAT so credentials are never stored in nuget.config or any file that might be committed to a repo.
Terms: {REPO_OWNER} = the GitHub user or org that owns the feed (e.g. gideonogegaorg) (where the packages are published).
-
Create a PAT (Personal Access Token)
GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic). Create a token with scoperead:packages(and optionallyrepoif the packages are in a private repo). -
Add the feed using one of the options below.
Option A — nuget.config (recommended)
Set GITHUB_USERNAME and GITHUB_PAT in your environment, then add anuget.configthat defines the GMO source and credentials from those env vars. Replace{REPO_OWNER}in the source URL. If your tooling expands env vars in the config (e.g. a script or CI), thepackageSourceCredentialsvalues will be substituted.packageSourceMappingsendsGMO.*packages to the GitHub feed and everything else to nuget.org. Do not commit a config that contains literal secrets—only the template with%GITHUB_USERNAME%/%GITHUB_PAT%placeholders.# PowerShell $env:GITHUB_USERNAME = "your_github_username" $env:GITHUB_PAT = "your_pat_here" # Bash: export GITHUB_USERNAME=... GITHUB_PAT=...
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <add key="GMO" value="https://nuget.pkg.github.com/{REPO_OWNER}/index.json" /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> </packageSources> <packageSourceCredentials> <GMO> <add key="Username" value="%GITHUB_USERNAME%" /> <add key="ClearTextPassword" value="%GITHUB_PAT%" /> </GMO> </packageSourceCredentials> <packageSourceMapping> <packageSource key="GMO"> <package pattern="GMO.*" /> </packageSource> <packageSource key="nuget.org"> <package pattern="*" /> </packageSource> </packageSourceMapping> </configuration>
Option B — CLI (alternative)
Set username and PAT in your environment (do not put them innuget.config). Add the NuGet source via CLI so the credential is stored in your user-level config (e.g. Windows Credential Manager), not in repo files:# PowerShell $env:GITHUB_USERNAME = "your_github_username" $env:GITHUB_PAT = "your_pat_here" # Bash: export GITHUB_USERNAME=... GITHUB_PAT=...
dotnet nuget add source "https://nuget.pkg.github.com/{REPO_OWNER}/index.json" \ --name GMO \ --username $env:GITHUB_USERNAME \ --password $env:GITHUB_PAT
Replace
{REPO_OWNER}in the URL. Use%GITHUB_USERNAME%and%GITHUB_PAT%on Windows Command Prompt, or$GITHUB_USERNAMEand$GITHUB_PATin Bash. Omit--store-password-in-clear-textso the credential is stored encrypted. -
Restore in your app:
dotnet restore
With the feed added (Option A or B),
dotnet restorewill use it when your project referencesGMO.OpenTelemetryorGMO.OpenTelemetry.Serilog. Keep secrets in env vars or credential manager; do not commit a config with literal credentials.
Add OTLP configuration to your host's settings (e.g. appsettings.json):
"Telemetry": {
"Enabled": true,
"Otlp": {
"Endpoint": "https://otlp.nr-data.net:4317/v1/traces",
"Headers": "api-key=YOUR_LICENSE_KEY",
"Protocol": "Grpc"
},
"MetricsEndpoint": "https://otlp.nr-data.net:4317/v1/metrics"
}Register OpenTelemetry and the custom CPU % gauge in your startup:
builder.Services.AddOpenTelemetry()
.WithMetrics(b =>
{
b.AddRuntimeInstrumentation()
.AddProcessInstrumentation()
.AddMeter(GMO.OpenTelemetry.CustomMetrics.Name)
.AddOtlpExporter();
});
// Ensure CustomMetrics is constructed (implements IHostedService, starts automatically):
builder.Services.AddSingleton<CustomMetrics>();# Format first (required before every build, test, or commit)
dotnet format src/GMO.OpenTelemetry.sln
# Build
dotnet build src/GMO.OpenTelemetry.sln -c Release
# Run tests
dotnet test src/GMO.OpenTelemetry.sln -c Release --no-build
# Pack into NuGet packages
dotnet pack src/GMO.OpenTelemetry.sln -c Release -o nupkgs /p:PackageVersion=1.0.0GitHub Actions (.github/workflows/ci.yml) on push or PR to main or dev. Order: lint → build → test → tag (if successful) → publish.
- Lint:
dotnet format --verify-no-changes - Build: restore, build with version from run (year.month.build.revision;
devuses a DEV- prefixed informational version) - Test:
dotnet test(step passes when no test projects exist yet; add test projects to run tests) - Tag (on push only, after test passes): create and push tag
{branch}-{year}-{month}-{run_id} - Publish (on push to main/dev only, after tag): pack and push to GitHub Packages. main → version
{year}.{month}.{build}.{revision}; dev → same with-alphasuffix. RequiresGH_CLASSIC_PATsecret.
- Fork and create a branch
- Make changes following .editorconfig style (4 spaces, camelCase with
_prefix for private fields) - Run
dotnet format src/GMO.OpenTelemetry.slnbefore every build, test, or commit. Use--verify-no-changesto confirm nothing is left to fix. - Commit, push to your fork, and open a pull request against
main - Ensure CI passes (lint, build, test)
This project is licensed under the GNU General Public License v3.0. See LICENSE for the full text.