Rapp provides optional telemetry for monitoring cache performance. Telemetry is excluded from the NuGet package by default to ensure zero overhead in production deployments.
The NuGet package you install has zero telemetry overhead:
- No metric collection
- No counters
- No instrumentation code paths
- Pure serialization performance
To enable telemetry in your application, add the RAPP_TELEMETRY compilation symbol:
<PropertyGroup>
<DefineConstants>$(DefineConstants);RAPP_TELEMETRY</DefineConstants>
</PropertyGroup>dotnet build -p:DefineConstants="RAPP_TELEMETRY"<!-- Enable only in Development -->
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>$(DefineConstants);RAPP_TELEMETRY</DefineConstants>
</PropertyGroup>When telemetry is enabled, Rapp exposes the following metrics via System.Diagnostics.Metrics:
// Counter: rapp_cache_hits_total
RappMetrics.RecordHit();
// Counter: rapp_cache_misses_total
RappMetrics.RecordMiss();
// Counter: rapp_bytes_total
// Counter: json_bytes_equivalent
// Records serialization sizes for cost analysis
RappMetrics.RecordSerializationSize(binarySize, jsonSize);When RAPP_TELEMETRY is enabled, Rapp also calculates:
- rapp_bytes_total: Total bytes serialized/deserialized using Rapp
- json_bytes_equivalent: Equivalent size if JSON were used
Performance Warning: Calculating
json_bytes_equivalentrequires double-serialization (serializing to JSON in parallel) to measure the size difference. This introduces significant overhead and should only be used for analysis/debugging, never in latency-critical production paths.
These are recorded automatically by RappBaseSerializer:
- Deserialization errors: Data too short, corruption, etc.
- Schema mismatches: Type definition changed between serialization and deserialization
Even with telemetry compiled in, you can control it at runtime:
// Disable telemetry at runtime (reduces overhead)
RappConfiguration.EnableTelemetry = false;
// Enable detailed error information (development only)
RappConfiguration.EnableDetailedErrors = true;
// Throw exceptions on schema mismatch (testing only)
RappConfiguration.ThrowOnSchemaMismatch = true;When telemetry is enabled, use standard .NET monitoring tools:
// Using OpenTelemetry
services.AddOpenTelemetry()
.WithMetrics(metrics => metrics
.AddMeter("Rapp")
.AddPrometheusExporter());services.AddApplicationInsightsTelemetry();
// Rapp metrics are automatically collectedvar listener = new MeterListener();
listener.InstrumentPublished = (instrument, listener) =>
{
if (instrument.Meter.Name == "Rapp")
{
listener.EnableMeasurementEvents(instrument);
}
};
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
{
Console.WriteLine($"{instrument.Name}: {measurement}");
});
listener.Start();- Serialization overhead: 0% (metrics code removed at compile time)
- Binary size: Smallest possible
- JIT optimization: Maximum (no conditional branches for metrics)
- Serialization overhead: <0.5% (simple counter increments)
- Binary size: +2-3 KB for metrics infrastructure
- JIT optimization: Minimal impact with
EnableTelemetry = false
Recommended: Do not define RAPP_TELEMETRY
<!-- Production config - NO telemetry -->
<PropertyGroup>
<!-- No RAPP_TELEMETRY defined -->
</PropertyGroup>Benefits:
- Absolute minimum overhead
- Smallest binary size
- Maximum AOT optimization
Recommended: Enable telemetry conditionally
<PropertyGroup Condition="'$(Configuration)' != 'Release'">
<DefineConstants>$(DefineConstants);RAPP_TELEMETRY</DefineConstants>
</PropertyGroup>If your production environment requires observability:
<PropertyGroup>
<DefineConstants>$(DefineConstants);RAPP_TELEMETRY</DefineConstants>
</PropertyGroup>Then control at runtime:
// Only enable in monitoring endpoints
app.MapGet("/metrics", () =>
{
RappConfiguration.EnableTelemetry = true;
// Return metrics
});The Rapp.Dashboard package requires telemetry. When using the dashboard:
// Install Rapp.Dashboard (it automatically enables RAPP_TELEMETRY)
dotnet add package Rapp.DashboardThe dashboard project includes telemetry by default for visualization.
Check if telemetry is compiled in:
#if RAPP_TELEMETRY
Console.WriteLine("Telemetry: ENABLED");
#else
Console.WriteLine("Telemetry: DISABLED (zero overhead)");
#endifBefore:
public class MySerializer : IHybridCacheSerializer<T>
{
public void Serialize(T value, IBufferWriter<byte> target)
{
_metrics.RecordSerialization(); // Always runs
MemoryPackSerializer.Serialize(target, value);
}
}After (with Rapp):
// No code changes needed!
// Metrics are optional via RAPP_TELEMETRY
[RappCache]
[MemoryPackable]
public partial class MyClass { }JSON serializers often include metrics that can't be disabled. Rapp gives you the choice:
- Need metrics? Define
RAPP_TELEMETRY - Want zero overhead? Don't define it (default)
A: No. The published NuGet package has zero metrics overhead by default.
A: No. Metrics are a compile-time feature for maximum performance. This ensures production code has no overhead.
A: In production (no RAPP_TELEMETRY): 0% overhead
In development (with RAPP_TELEMETRY): <0.5% overhead
A: Yes. Both configurations (with and without telemetry) are fully AOT-compatible.
A: Yes. Use conditional compilation in your project file based on $(Configuration).
See the /Samples directory for complete examples:
- All samples have
RAPP_TELEMETRYenabled for demonstration - Production apps should remove this for zero overhead
| Configuration | Overhead | Use Case |
|---|---|---|
No RAPP_TELEMETRY (default) |
0% | Production deployments |
With RAPP_TELEMETRY + EnableTelemetry=false |
<0.1% | Development with opt-out |
With RAPP_TELEMETRY + EnableTelemetry=true |
<0.5% | Development/staging monitoring |
Default recommendation: Don't define RAPP_TELEMETRY in production for absolute maximum performance.