Observability and troubleshooting

Use engine statistics, initialization logs, and query plans to understand collection health and report behavior.

Find the first useful check

Symptom First check Next step
New events are not visible Same site and range; accepted versus processed counters Collection and freshness
One visit appears twice Both server and browser page-view collection enabled Choose one collection method
Live visitors decrease Identities leaving the recent sliding window Time and freshness
A filtered report is much slower Plan sources and required joint dimensions Explain a slow report
Country rows are missing Geolocation adapter or trusted country dimensions Website context
Startup takes longer after configuration changes Index necessity checks and backfill progress Explain startup duration
Reporting returns 403 Host policy and AuthorizeSite for the normalized site Sites and tenants
Reporting returns 503 Error body, concurrency, timeout, and response-size limits HTTP limits

Start with the affected dataset. The dashboard's primary traffic, performance samples, and latest benchmark are separate engines with separate counters and directories.

Monitor collection

var stats = analytics.GetStatistics(includePartitions: false);
Console.WriteLine($"Accepted: {stats.EventsAccepted}");
Console.WriteLine($"Processed: {stats.EventsProcessed}");
Console.WriteLine($"Queued: {stats.QueueLength}");
Console.WriteLine($"Dropped: {stats.EventsDropped}; Errors: {stats.Errors}");

Statistics cover the current engine instance. Lightweight polling with includePartitions:false avoids storage inspection.

Signal Meaning to investigate
QueueLength grows Processing or storage cannot keep pace with collection
EventsDropped grows Dropping queues are full
EventsRejected grows Input validation or future timestamp skew
EventsFiltered grows Collection policy is excluding events
Errors grows Extension, processing, storage, or maintenance failures
Flushes stops advancing during activity Aggregate-saving progress or storage health

Accepted and processed counters can differ while background work is active. Bot counters distinguish excluded and separately reported automated traffic.

Explain startup duration

Enable Information logging for ZoneTree.Analytics in an ASP.NET Core host to see initialization detail. The standalone core defaults to warning-level console output.

Merge this logging section into the host's appsettings.json, or the environment-specific settings used for the investigation:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "ZoneTree.Analytics": "Information"
    }
  }
}

For a standalone engine, set its logger before opening it:

options.Storage.Logger = new ZoneTree.Logger.ConsoleLogger
{
    LogLevel = ZoneTree.Logger.LogLevel.Info,
};

An engine opened outside dependency injection in an ASP.NET Core host can also use the integration's UseLogger extension to forward engine and storage messages to a host logger.

Backfill checks report whether stores are disabled, reusable, need repair of affected days, or require rebuilding. Work logs report durable checkpoints, resumed event or row counts, completion duration, and throughput. Each identifies the dataset directory.

These logs distinguish several engines in one host and explain why a restart can take longer after changing index configuration.

Explain a slow report

  1. Inspect the report's sources and covered ranges.
  2. Compare grouping, filters, and conditional-metric dimensions.
  3. Check matching rollups and equality-leading indexes.
  4. Check retention, activation dates, boundary reads, and requested session metrics.
  5. Measure concurrent reporting load and scan parallelism.

The number of rows displayed is not the number of records read. A filtered card can do far more work than the same unfiltered card.

The rollup guide includes code for inspecting sources, index dimensions, and warnings. Capture the exact site, range, filter values, metrics, and whether the read was cold or repeated with the timing.

If the plan reads raw events, first check whether the requested joint rollup is missing. If it already reads rollups but visits many irrelevant aggregate rows, consider an equality-leading rollup index. Increasing raw-scan parallelism does not address an aggregate-read bottleneck.

Explain unexpected numbers

Check site, range, time zone, identity policy, and filters first. Reports update automatically; dashboard refresh and background processing can make new activity appear in groups.

A sliding-window live count can decrease as identities age out. Cross-day anonymous counts depend on the configured rotation policy.

Use plan warnings to distinguish missing history from zero activity, and preserve null metrics when they do not apply.

Inspect storage when necessary

For routine health, prefer statistics and plans. Advanced storage access exposes owned partitions and logical index prefixes for inspection.

Direct writes and independently managed maintenance can bypass analytics invariants. Keep tree ownership and maintenance with the engine.