Table of Contents

OpenTelemetry

LeanLucene exposes activities and metrics through the standard BCL APIs. Your app can export them to any OpenTelemetry backend, including Aspire, Jaeger and Prometheus.

Source names

Kind Name
ActivitySource Rowles.LeanLucene
Meter Rowles.LeanLucene

Activities

Activity Tags
leanlucene.search query.type, search.total_hits, search.cache_hit
leanlucene.index.commit index.commit_generation, index.segment_count
leanlucene.index.flush index.segment_id, index.doc_count
leanlucene.index.merge index.segments_merged

Activities are only allocated when a listener is attached.

Metric instruments

leanlucene.search.duration, leanlucene.search.count, leanlucene.cache.hits, leanlucene.cache.misses, leanlucene.index.flush.duration, leanlucene.index.merge.duration, leanlucene.index.merge.segments, leanlucene.index.commit.duration, leanlucene.hnsw.search.duration, leanlucene.hnsw.search.nodes_visited, leanlucene.hnsw.build.duration, leanlucene.hnsw.build.nodes.

Wire MeterMetricsCollector

using Rowles.LeanLucene.Diagnostics;

var collector = new MeterMetricsCollector();

var writerConfig   = new IndexWriterConfig    { Metrics = collector };
var searcherConfig = new IndexSearcherConfig  { Metrics = collector };

In hosted apps, pass the DI-managed IMeterFactory into MeterMetricsCollector.

OTLP export

Let environment variables configure the endpoint. This keeps the same code working under Aspire AppHost, Aspire Runner and other OTLP collectors.

builder.Services
    .AddOpenTelemetry()
    .ConfigureResource(r => r.AddService("MySearchApp"))
    .WithTracing(t => t
        .AddSource("Rowles.LeanLucene")
        .AddOtlpExporter())
    .WithMetrics(m => m
        .AddMeter("Rowles.LeanLucene")
        .AddOtlpExporter());

For a local collector:

$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://localhost:4317"
$env:OTEL_EXPORTER_OTLP_PROTOCOL = "grpc"

Structured logs

LeanLucene does not log directly. Application logs can still be exported to the same OTLP endpoint:

builder.Logging.AddOpenTelemetry(logging =>
{
    logging.IncludeFormattedMessage = true;
    logging.IncludeScopes           = true;
    logging.ParseStateValues        = true;
    logging.AddOtlpExporter();
});

Use message templates, not string interpolation, so log values become structured attributes:

logger.LogInformation("Search {QueryType} returned {HitCount} hits", queryType, hits);

Aspire Runner

Aspire Runner defaults to HTTPS for the dashboard and OTLP. If your app uses http://localhost:4317, start the dashboard without HTTPS:

aspire-dashboard -s false

Or set OTEL_EXPORTER_OTLP_ENDPOINT to https://localhost:4317 and trust the certificate used by the dashboard.

A worked example lives in src/examples/Rowles.LeanLucene.Example.Telemetry.

See also