KamsoraAPM.Agent
1.5.0
dotnet add package KamsoraAPM.Agent --version 1.5.0
NuGet\Install-Package KamsoraAPM.Agent -Version 1.5.0
<PackageReference Include="KamsoraAPM.Agent" Version="1.5.0" />
<PackageVersion Include="KamsoraAPM.Agent" Version="1.5.0" />
<PackageReference Include="KamsoraAPM.Agent" />
paket add KamsoraAPM.Agent --version 1.5.0
#r "nuget: KamsoraAPM.Agent, 1.5.0"
#:package KamsoraAPM.Agent@1.5.0
#addin nuget:?package=KamsoraAPM.Agent&version=1.5.0
#tool nuget:?package=KamsoraAPM.Agent&version=1.5.0
KamsoraAPM.Agent
The in-process .NET agent for KamsoraAPM - a free, self-hostable APM and infrastructure observability platform purpose-built for .NET Core Web APIs.
What it does
- Captures HTTP server activities (ASP.NET Core), outbound HTTP calls (
HttpClient), and database calls (SqlClient + Npgsql + MySqlConnector + EF Core) automatically. - Forwards spans to your KamsoraAPM Collector over gRPC, using an OTLP-compatible wire format.
- Adds less than 2 ms of latency per HTTP request and less than 2 % CPU under load.
- Multi-tenant from day one - every span carries a
tenant_idvalidated server-side.
Install
dotnet add package KamsoraAPM.Agent
Wire it up
In your Program.cs:
builder.Services.AddKamsoraApm(o =>
{
o.CollectorEndpoint = "http://your-collector-host:5080";
o.TenantId = "<your-tenant-uuid>";
o.ApiKey = "<your-ingest-api-key>";
o.ServiceName = "my-service-name";
});
Or via appsettings.json:
{
"KamsoraApm": {
"Agent": {
"CollectorEndpoint": "http://your-collector-host:5080",
"TenantId": "<your-tenant-uuid>",
"ApiKey": "<your-ingest-api-key>",
"ServiceName": "my-service-name"
}
}
}
The tenant UUID and API key are minted from the KamsoraAPM dashboard's API Keys page (or - for the very first tenant - printed once in the dashboard's startup logs).
What gets captured automatically
| Source | Captured tags |
|---|---|
| ASP.NET Core HTTP server | http.request.method, http.route, url.path, http.response.status_code, user_agent.original, server.address |
HttpClient outbound |
http.request.method, url.full, http.response.status_code |
Microsoft.Data.SqlClient / System.Data.SqlClient |
db.system=mssql, db.statement, db.connection_string |
| Npgsql 6+ (PostgreSQL) | db.system=postgresql, db.statement (auto via Activity source) |
| MySqlConnector | db.system=mysql, db.statement |
| EF Core | One span per query, parent linked to surrounding HTTP request |
Any custom ActivitySource whose name starts with Kamsora. |
Forwarded verbatim |
Architecture
This package is the agent half of the KamsoraAPM stack. The full stack is:
- KamsoraAPM.Agent (this package) - in-process .NET library
- KamsoraAPM.HostMonitor - host-level CPU/RAM/disk/network/process daemon (Windows Service or systemd)
- KamsoraAPM.Collector - gRPC ingest, multi-tenant auth, writes to ClickHouse
- KamsoraAPM Dashboard - React SPA showing live traces, services, hosts, top processes
Everything except this NuGet package is self-hosted from the KamsoraAPM repo.
License
Apache 2.0. See the LICENSE file.
Links
- Source: https://github.com/kamsora/KamsoraAPM
- Issues / feedback: https://github.com/kamsora/KamsoraAPM/issues
- Docs: https://github.com/kamsora/KamsoraAPM#readme
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Google.Protobuf (>= 3.28.3)
- Grpc.Net.Client (>= 2.66.0)
- Microsoft.Diagnostics.NETCore.Client (>= 0.2.553101)
- Microsoft.Diagnostics.Tracing.TraceEvent (>= 3.1.16)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.3)
- Microsoft.Extensions.Hosting (>= 9.0.0)
- Microsoft.Extensions.Http (>= 9.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.0)
- OpenTelemetry (>= 1.12.0)
- OpenTelemetry.Api (>= 1.12.0)
- OpenTelemetry.Extensions.Hosting (>= 1.12.0)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.11.1)
- OpenTelemetry.Instrumentation.Http (>= 1.11.1)
- OpenTelemetry.Instrumentation.Runtime (>= 1.11.1)
- OpenTelemetry.Instrumentation.SqlClient (>= 1.10.0-beta.1)
- Polly (>= 8.5.0)
- System.IO.Hashing (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.5.0 - universal dependency tracing.
The Agent now listens to EVERY ActivitySource by default (empty
CaptureSources), so any OpenTelemetry-emitting dependency - SQL and
NoSQL drivers, cache clients (Redis), message queues, gRPC, and your
own custom sources - is captured with zero per-app configuration,
not just a curated prefix list. This also covers drivers on the
stabilized OpenTelemetry database conventions (e.g. Npgsql 9+).
Set CaptureSources explicitly to narrow capture if you want less.
The exporters' own gRPC calls to the Collector are now excluded from
capture, so observing every source cannot feed the export RPCs back
into the queue. Also syncs the reported kamsora.agent.version (was a
stale 0.1.0-m0 marker).
v1.4.0 - OTLP wire-format alignment (BREAKING vs v1.3.x mixed fleets).
The kamsora.common.v1.AnyValue message now matches OpenTelemetry's
AnyValue EXACTLY: int_value is plain int64 (was sint64/ZigZag) and
array/kvlist/bytes occupy fields 5/6/7 in OTLP order. This makes the
Collector's new standard-OTLP ingest endpoints losslessly compatible
with every OpenTelemetry SDK.
UPGRADE NOTE: run v1.4.0 Agents against a v1.4.0+ Collector. A v1.3.x
Agent talking to a v1.4 Collector (or vice versa) mis-decodes INTEGER
attribute values (they ZigZag-double or halve - e.g. HTTP status 200
reads as 400). String attributes are unaffected. Upgrade both sides
together.
v1.3.2 - M10 first wave: bandwidth + sampling.
Highlights:
* gRPC gzip compression now enabled on all signal exporters
(traces, logs, metrics, profiles). Typical bandwidth reduction
5-10x for log batches and 3-5x for span / metric batches.
* New option KamsoraApm:TraceSampleRatio (default 1.0). Set to
0.1 to keep ~10% of root traces by trace-id hash; child spans
stay coherent because the decision propagates through the
W3C TraceContext sample flag. Defaults preserve v1.3.1
behaviour (every trace captured).
* Internal: gRPC channel + auth-metadata construction is now
centralised so future signals (and the deferred profiling
v2 path) pick up the same compression + keepalive tuning.
v1.3.1 - HOTFIX: v1.3.0 introduced continuous CPU profiling that
defaulted to enabled. The EventPipe self-connect path interacted
badly with some host configurations (most likely a ThreadPool /
diagnostic-port race), causing the host's request loop to stop
responding shortly after startup. v1.3.1:
* Defaults EnableProfiling to FALSE (was true in v1.3.0).
* Only constructs the profiler hosted service when the option
is explicitly true, so the EventPipe + TraceEvent stack
never participates in the host's startup graph by default.
Tracing, metrics, and log capture are unaffected and work as in
v1.2.3. To experimentally re-enable profiling once we've shipped
the safer in-process EventListener path, set
KamsoraApm:EnableProfiling = true on a non-prod copy first.
v1.3.0 - M9 continuous CPU profiling (4th pillar).
Highlights:
* The Agent now self-connects to the runtime diagnostic port and
captures a short CPU sampling profile every minute via EventPipe.
Stacks are symbol-resolved through TraceLog, folded, converted to
pprof (Google's perftools.profiles.Profile format), and shipped
to the KamsoraAPM Collector over gRPC.
* New options:
- EnableProfiling (default true)
- ProfilingInterval (default 60s)
- ProfilingDuration (default 10s)
* Storing pprof verbatim keeps the captures interoperable with
Pyroscope, Parca, Grafana, and `go tool pprof` for offline
analysis.
* gRPC channel for profiles uses gzip compression - pprof payloads
compress 5-10x at the wire.
v1.2.3 - second log-pipeline fix. Removed the temporary console
diagnostics from v1.2.2 now that the upstream + downstream
breakages have been pinned down (OTel wiring on the Agent side;
FixedString-vs-byte[] serialization on the Collector side).
Combined with the matching Collector + ClickHouse schema update,
ILogger logs now reach kamsora_apm.logs and appear on the Logs
dashboard. Functionally identical to v1.2.2 otherwise.
v1.2.1 - fixes ILogger logs not flowing to the Collector. The
OpenTelemetry logger provider's SP-aware AddProcessor factory is
silently no-op in OTel 1.12 when configured via
ILoggingBuilder.AddOpenTelemetry(); moving the registration onto
the unified AddOpenTelemetry().WithLogging(...) builder restores
log export. Functionally identical to v1.2.0 otherwise.
v1.2.0 - M8 logs + metrics ingest.
Highlights:
* OpenTelemetry Logs integration via Microsoft.Extensions.Logging
(ILogger<T>). All structured logs flow to the KamsoraAPM
Collector over gRPC and appear on the new Logs dashboard with
severity filtering, body search, and per-trace correlation.
* OpenTelemetry Metrics integration. Runtime instrumentation
(GC, threadpool, exceptions) ships by default. Custom Meters
can be added via KamsoraApm:MetricSources.
* New options:
- EnableLogs (default true)
- EnableMetrics (default true)
- MetricSources (list of custom Meter names)
- MetricExportInterval (default 30s)
* Trace-log correlation: each log record carries the active
trace_id + span_id, so opening a trace surfaces its logs and
opening a log jumps to its trace.
v1.1.1 - fixes FileNotFoundException for Google.Protobuf at
AddKamsoraApm() startup by exposing Google.Protobuf as a public
package dependency (the bundled Contracts.dll needs it at runtime).
Functionally identical to v1.1.0 otherwise.
v1.1.0 - M6 consumer analytics.
Highlights:
* New IConsumerExtractor pipeline tags each inbound span with a
consumer id, powering the per-API-key Consumers + Errors
dashboards. Configurable via KamsoraApm:ConsumerExtractor with
four modes:
- JwtClaim (default, claim = "sub")
- Header (default header = "X-API-Consumer")
- ClientIp (honors X-Forwarded-For)
- None (disable consumer tagging)
All non-JwtClaim modes fall back to client IP by default; set
FallbackToClientIp = false to leave anonymous requests untagged.
* No new package dependencies - JWT payload is parsed inline.
v1.0.0 - initial release:
* Auto-instruments ASP.NET Core HTTP server, HttpClient, SqlClient
(MSSQL). Npgsql, MySqlConnector, and EF Core ActivitySources
are captured automatically.
* Multi-tenant: every span carries a tenant UUID validated by the
Collector.
* OTLP-compatible wire format over gRPC.
* <2 ms latency overhead per HTTP request under load.
See https://github.com/kamsora/KamsoraAPM for the Collector + dashboard.