Skip to content

Integration Elasticsearch Extension

aryehcitron@gmail.com edited this page May 24, 2026 · 12 revisions

The Kronikol.Extensions.Elasticsearch package adds Elasticsearch operation tracking to your test diagrams. Every index, search, document, and cluster operation appears as a classified entry in your sequence diagrams — showing the complete data flow between your services and their search indices.

Using a shared library or abstraction layer? If your code doesn't use the Elasticsearch client directly — e.g. it goes through a shared search library, wrapper, or custom abstraction — this extension won't be able to intercept the underlying calls. See Tracking Custom Dependencies for alternative approaches including RequestResponseLogger.LogPair(), TrackingProxy<T>, and MessageTracker.


How It Works

The extension hooks into the Elastic .NET client's OnRequestCompleted callback. After every Elasticsearch REST API call completes, the callback receives ApiCallDetails containing the HTTP method, URI, status code, and optionally the request/response bodies. The extension classifies the operation, builds a diagram label, and logs it to RequestResponseLogger.

ElasticsearchTrackingCallbackHandler implements ITrackingComponent directly (it is not a DelegatingHandler since it uses a callback pattern).


Install

dotnet add package Kronikol.Extensions.Elasticsearch

Verbosity Levels

Level Method shown URI shown Request body Response body
Raw Search /orders Full request URI Yes Yes
Detailed Search → orders elasticsearch:///orders Yes Controlled by LogResponseContent (v2.37.0+)
Summarised Search elasticsearch:/// No No

The default is Detailed.

Diagram Label Examples

Operation Raw Detailed Summarised
Search Search /orders Search → orders Search
Index document IndexDocument /orders/123 Index → orders Index
Get document GetDocument /orders/123 Get ← orders Get
Delete document DeleteDocument /orders/abc Delete orders Delete
Bulk Bulk /orders Bulk → orders Bulk
Create index CreateIndex /orders CreateIndex orders CreateIndex

Classified Operations

Operation HTTP Method Path Pattern
IndexDocument POST /{index}/_doc or PUT /{index}/_doc/{id}
GetDocument GET /{index}/_doc/{id}
DeleteDocument DELETE /{index}/_doc/{id}
UpdateDocument POST /{index}/_update/{id}
Search POST/GET /{index}/_search
MultiSearch POST /_msearch
Count POST /{index}/_count
Bulk POST /_bulk or /{index}/_bulk
CreateIndex PUT /{index}
DeleteIndex DELETE /{index}
IndexExists HEAD /{index}
PutMapping PUT /{index}/_mapping
GetMapping GET /{index}/_mapping
Refresh POST /{index}/_refresh
Reindex POST /_reindex
DeleteByQuery POST /{index}/_delete_by_query
UpdateByQuery POST /{index}/_update_by_query
PutIndexTemplate PUT /_index_template/{name}
GetIndexTemplate GET /_index_template/{name}
UpdateAliases POST /_aliases
Scroll /_search/scroll or /_scroll
ClusterHealth GET /_cluster/health
CatApis GET /_cat/*

Setup

Option A: Extension Method (Recommended)

var settings = new ElasticsearchClientSettings(new Uri("http://localhost:9200"))
    .WithTestTracking(new ElasticsearchTrackingOptions
    {
        ServiceName = "Elasticsearch",
        CallerName = "My API",
        Verbosity = ElasticsearchTrackingVerbosity.Detailed,
        CurrentTestInfoFetcher = CurrentTestInfo.Fetcher
    });

var client = new ElasticsearchClient(settings);

WithTestTracking automatically calls DisableDirectStreaming() (required to capture request/response bodies) and registers the OnRequestCompleted callback.

Option B: Manual Setup

var handler = new ElasticsearchTrackingCallbackHandler(new ElasticsearchTrackingOptions
{
    ServiceName = "Elasticsearch",
    CallerName = "My API",
    CurrentTestInfoFetcher = () => /* ... */
});

var settings = new ElasticsearchClientSettings(new Uri("http://localhost:9200"))
    .DisableDirectStreaming()
    .OnRequestCompleted(details => handler.HandleApiCallDetails(details));

Configuration Reference

ElasticsearchTrackingOptions

Property Type Default Description
ServiceName string "Elasticsearch" The participant name shown in the diagram for the Elasticsearch cluster
CallerName string "Caller" The participant name shown for the service making requests
Verbosity ElasticsearchTrackingVerbosity Detailed Controls how much detail appears in the diagram (Raw, Detailed, Summarised)
CurrentTestInfoFetcher Func<(string Name, string Id)>? null Returns the current test's name and ID. Required — if null, operations are not logged
CurrentStepTypeFetcher Func<string?>? null Optional — returns the current BDD step type (Given/When/Then)
HttpContextAccessor IHttpContextAccessor? null Optional — enables dual-resolution of test identity from HTTP headers. Auto-resolved by DI extensions (v2.26.3+). See HTTP Tracking Setup#Dual-Resolution Test Identity (v2.23.0+)
ExcludedOperations HashSet<ElasticsearchOperation> { ClusterHealth, CatApis } Operations to skip logging. Health checks and cat APIs are excluded by default to reduce noise
SetupVerbosity ElasticsearchTrackingVerbosity? null Verbosity override for the Setup phase. See Phase-Aware Tracking
ActionVerbosity ElasticsearchTrackingVerbosity? null Verbosity override for the Action phase. See Phase-Aware Tracking
TrackDuringSetup bool true When false, tracking is suppressed during Setup. See Phase-Aware Tracking
TrackDuringAction bool true When false, tracking is suppressed during Action. See Phase-Aware Tracking
LogResponseContent bool true Include response body in diagrams at Detailed verbosity (v2.37.0+). At Raw, the response body is always included regardless. Set to false to restore previous behaviour where response was only shown at Raw

v2.23.0+ Dual-Resolution: ElasticsearchTrackingCallbackHandler accepts an optional IHttpContextAccessor? httpContextAccessor constructor parameter for resolving test identity from HTTP request headers when running inside the SUT's request pipeline. v2.26.3+: Set HttpContextAccessor on ElasticsearchTrackingOptions instead — the tracker reads it automatically. See HTTP Tracking Setup#Dual-Resolution Test Identity (v2.23.0+) for details.

Customizing Excluded Operations

new ElasticsearchTrackingOptions
{
    ExcludedOperations = new HashSet<ElasticsearchOperation>
    {
        ElasticsearchOperation.ClusterHealth,
        ElasticsearchOperation.CatApis,
        ElasticsearchOperation.Refresh  // Also skip refresh calls
    }
}

To track everything including health checks:

new ElasticsearchTrackingOptions
{
    ExcludedOperations = [] // Empty = track all operations
}

Body Capture

The extension requires DisableDirectStreaming() to capture request and response bodies. This buffers bodies in memory, which is acceptable for tests but has a small performance overhead.

Verbosity Request body Response body
Raw Captured Captured
Detailed Captured Captured (v2.37.0+, controlled by LogResponseContent)
Summarised Not captured Not captured

Invocation Validation

ElasticsearchTrackingCallbackHandler implements ITrackingComponent and auto-registers with TrackingComponentRegistry on construction. At report generation time, unused components are automatically detected and surfaced as console warnings and in the diagnostic report (when DiagnosticMode=true). This never throws or fails tests.

See Diagnostics and Debugging for full details on the TrackingComponentRegistry API.

Home


Demo


Getting Started

Common Tasks

Integration Guides

Extensions

Configuration

Features

Reference

Clone this wiki locally