Skip to main content

Performance diagnostics

CamusDB can expose opt-in diagnostics for a standalone node. While the diagnostics are enabled, the server exports Prometheus metrics. It can also export sampled OpenTelemetry traces.

You can therefore connect a workload result to a stage on the server. Those stages are the handling of a request, the SQL execution, a scan, the commit of a transaction, and the WAL activity.

For a quick inspection from SQL, use SHOW ENGINE STATS. It reports the metrics of the embedded Kahuna engine and the embedded Kommander engine. It is independent from the exporter path on this page.

Diagnostics are off by default. With diagnostics.enabled: false, CamusDB registers no exporter, no endpoint, and no background collector. The current diagnostics path serves a standalone node.

Enable diagnostics​

Add a diagnostics section to the selected config.yml file:

diagnostics:
enabled: true
prometheus_enabled: true
prometheus_path: /metrics
otlp_endpoint:
trace_sample_ratio: 0.01
include_runtime_metrics: true

The settings are these:

SettingDefaultMeaning
diagnostics.enabledfalseThe main switch. While it is false, CamusDB exports nothing.
diagnostics.prometheus_enabledfalseBind the Prometheus scrape endpoint on the HTTP listener.
diagnostics.prometheus_path/metricsThe scrape path. It must start with /.
diagnostics.otlp_endpointemptyAn optional absolute URL of an OTLP collector, for the traces.
diagnostics.trace_sample_ratio0.01The head sample ratio for the traces. It must be from 0 to 1.
diagnostics.include_runtime_metricstrueInclude the .NET runtime metrics, such as the metrics of the garbage collector and of the thread pool.

Protect the Prometheus endpoint. You can also bind it on a trusted interface only. It exposes operational metadata, and it adds no authentication of its own.

CAMUS_CONFIG_PATH=/path/to/config.yml points the server at another configuration file. CAMUS_DIAGNOSTICS_RUN_ID attaches a stable run id as an OpenTelemetry resource attribute. The attribute is camus.run_id.

Server metrics​

CamusDB exports the metrics of the CamusDB.Server meter:

InstrumentPrometheus nameTypeTags
camus.request.countcamus_request_count_totalcounteroperation, transport, outcome
camus.request.durationcamus_request_duration_millisecondshistogramoperation, transport, outcome
camus.request.in_flightcamus_request_in_flightup-downtransport
camus.execute.durationcamus_execute_duration_millisecondshistogramoperation, statement
camus.sql.parse.cachecamus_sql_parse_cache_totalcounterresult
camus.sql.parse.durationcamus_sql_parse_duration_millisecondshistogramnone
camus.query.rowscamus_query_rows_totalcounterscan, stage
camus.query.scan.durationcamus_query_scan_duration_millisecondshistogramscan
camus.query_cache.requestscamus_query_cache_requests_totalcounterresult
camus.transaction.countcamus_transaction_count_totalcounteroperation, outcome
camus.transaction.activecamus_transaction_activeup-downtransaction_mode
camus.transaction.commit.durationcamus_transaction_commit_duration_millisecondshistogramoutcome
camus.transaction.staged_mutationscamus_transaction_staged_mutationshistogramnone

The set of tag values is bounded. CamusDB never uses SQL text, a row key, an id, a message, or a user value as a metric tag.

Dependency metrics​

The diagnostics exporter also subscribes to the meters of the embedded dependencies and of the runtime:

  • Kahuna metrics. They include the KV write batches, the write entries, the counters of durable transactions, and the gauges of the transaction admission.
  • Kommander metrics. They include the Raft WAL batches, the WAL operations, the batch size, the duration of the executor, and the depth of the client queue.
  • Row-level TTL counters. They include the expired rows, the skips after a re-check, the completed spans, and the planned runs.
  • .NET runtime metrics. They include the garbage collector, the heap, the allocations, the thread pool, and the process.

These signals help when one of five things limits a run:

  • The fsync latency of the WAL.
  • The density of a storage batch.
  • Pressure in the runtime.
  • The cost of a scan.
  • The concurrency of the requests.

Range splitting also publishes counters through the Kahuna meter. When key-range sharding is enabled, inspect them with:

SHOW ENGINE STATS LIKE 'kahuna.range%';

The most useful rows are kahuna.range.splits, kahuna.range.split.indivisible_refusals, kahuna.range.split.no_relief_skips, kahuna.range.split.settle_skips, and kahuna.range.merge.warm_skips. Use them together with SHOW RANGES: SHOW RANGES shows the current placement, while these counters explain what the splitter attempted.

SQL engine stats​

SHOW ENGINE STATS exposes a live snapshot of the metrics of the embedded engines, for one node:

SHOW ENGINE STATS;
SHOW ENGINE STATS LIKE 'raft.wal%';
SHOW ENGINE STATS LIKE 'kahuna.kv.write%';

Use the statement when you need operational visibility from SQL immediately. You need no scrape endpoint, and no trace collector.

engine_metrics_enabled controls the statement. diagnostics.enabled does not control it.

See Engine Stats for the permissions, the result columns, and some metric examples.

Traces​

CamusDB can emit sampled traces from the CamusDB.Server activity source, while diagnostics.otlp_endpoint holds a value. A typical trace of a request contains spans for the parse, the execution, the storage reads, and the commit of the transaction.

diagnostics.trace_sample_ratio samples the traces. The metadata of an error uses stable attributes for the outcome and for the error code. CamusDB adds no SQL text and no row value to a span.

The snapshot script​

The source tree of CamusDB includes a helper script. It gives local diagnostics from one command:

scripts/bottleneck-snapshot.sh /tmp/camus-bottleneck \
--workers 64 \
--duration 5m \
--rows 100000 \
--mode closed

The script does five things. It starts a standalone server in the Release configuration, with the diagnostics enabled. It seeds a deterministic data set for the workload. It runs CamusDB.Workload. It scrapes /metrics. It then writes a bundle:

server-command.txt
config-used.yml
server.log
server-metrics.txt
workload/manifest.json
workload/summary.json
workload/summary.md
workload/intervals.csv
workload/errors.json
workload/reconciliation.json
workload/bottleneck-report.md

The generated bottleneck-report.md aligns the throughput and the latency at the client with the metrics of the server stages and of the dependencies. Use it to select the next thing to investigate. Do that before you change a configuration.

The overhead check​

The source tree also includes a second script:

scripts/diagnostics-overhead.sh /tmp/camus-diagnostics-overhead \
--runs 5 \
--duration 60s

It alternates a run with the diagnostics disabled and a run with them enabled. It then reports the median difference in throughput. Measure the overhead on the machine, on the shape of data, and on the build of the server that you plan to compare.