Quickstart

LiveVerification Required

LogDB OTLP ingest and query quickstart.

Run a local LogDB process, send OTLP JSON compatibility logs and traces, capture record IDs, query retained records, and see how the local tenant policy gates access.

Current availability

Private Beta. Public beta is scheduled for .

Result

You will have a local LogDB workflow that accepts one log and two trace records, returns logdb_... record IDs, queries a retained log by exact record ID, queries retained trace spans by trace ID with pagination, and confirms that requests without x-logdb-tenant are rejected.

Maturity Status

Ingest And Query Workflow

Live

Local OTLP JSON compatibility ingest and POST /v1/query search are implemented for this first-success path.

Review Boundary

Verification Required

This tutorial proves local behavior only. S3 publication, BYOC, public replay APIs, external sinks, performance, support, security, availability, scale, and GA claims still need evidence review.

Prerequisites

Required tools

Required

  • cargo --version for the Rust toolchain
  • curl --version for HTTP requests
  • sed for extracting the first returned record ID
  • A local LogDB source checkout

Product setup

Required

  • LogDB source at /path/to/logdb or an equivalent local checkout.
  • LOGDB_BIND_ADDRESS set to an unprivileged loopback port, such as 127.0.0.1:4318.
  • LOGDB_DATA_DIR set to a disposable tutorial directory.

Tenant policy

Required

  • Use x-logdb-tenant: local on OTLP JSON compatibility ingest and query requests.
  • Use Authorization: Bearer local-dev-token for the local development tenant.
  • The tenant claimed inside OTLP resource attributes must match the authenticated tenant.

Optional helpers

Optional

  • jq can make JSON inspection easier, but the copy/paste workflow uses only shell, curl, and sed.
  • An OpenTelemetry Collector binary is only needed for the later collector smoke path, not this quickstart.

See local prerequisites for the shared tool baseline.

Start The Service

Use one terminal for the LogDB service and a second terminal for the workflow commands. The query route reads segment bundles from the local data directory by default.

Run LogDB locally

Service terminal

cd /path/to/logdb/LogDB
export LOGDB_BIND_ADDRESS=127.0.0.1:4318
export LOGDB_DATA_DIR="${TMPDIR:-/tmp}/logdb-docs-024"
mkdir -p "$LOGDB_DATA_DIR"
cargo run

Expected output

Cargo builds the LogDB crate, opens the local data directory, and starts the HTTP service on 127.0.0.1:4318.
Keep this terminal open while you run the workflow commands.

Check readiness

Workflow terminal

export LOGDB_ENDPOINT=http://127.0.0.1:4318
curl -s "$LOGDB_ENDPOINT/health"

Expected output

"Healthy"

Complete The Workflow

Configure tutorial values

Copy/paste

Set one endpoint, the local development tenant credentials, and the trace ID used by the trace query.

export LOGDB_ENDPOINT=http://127.0.0.1:4318
export LOGDB_TENANT=local
export LOGDB_TOKEN=local-dev-token
export LOGDB_DATASET=checkout
export LOGDB_TRACE_ID=4bf92f3577b34da6a3ce929d0e0e4736

Expected output

These values point at the local development policy. The dataset comes from the OTLP resource attribute service.name=checkout.

Send an OTLP JSON log batch

Copy/paste

Post one OpenTelemetry-shaped JSON compatibility log batch and keep the response for record ID extraction.

LOG_RESPONSE="$(curl -s -X POST "$LOGDB_ENDPOINT/v1/otlp/logs" \
  -H 'content-type: application/json' \
  -H "x-logdb-tenant: $LOGDB_TENANT" \
  -H "authorization: Bearer $LOGDB_TOKEN" \
  --data '{
    "resourceLogs": [{
      "resource": {
        "attributes": [
          {"key": "tenant_id", "value": {"stringValue": "local"}},
          {"key": "service.name", "value": {"stringValue": "checkout"}}
        ]
      },
      "scopeLogs": [{
        "logRecords": [{
          "timeUnixNano": "1783947600000000000",
          "body": {"stringValue": "payment accepted"}
        }]
      }]
    }]
  }')"

printf '%s\n' "$LOG_RESPONSE"

Expected output

{"status":"accepted","signal":"log","accepted_records":1,"record_ids":["logdb_..."]}

Capture the log record ID

Copy/paste

Extract the first deterministic logdb_... record ID from the accepted response.

LOG_RECORD_ID="$(printf '%s' "$LOG_RESPONSE" | sed -nE 's/.*"record_ids":\["([^"]+)".*/\1/p')"
printf '%s\n' "$LOG_RECORD_ID"

Expected output

logdb_...

Query by exact record ID

Copy/paste

Search the retained local segment bundles by exact record ID using the same tenant header and bearer token.

curl -s -X POST "$LOGDB_ENDPOINT/v1/query" \
  -H 'content-type: application/json' \
  -H "x-logdb-tenant: $LOGDB_TENANT" \
  -H "authorization: Bearer $LOGDB_TOKEN" \
  --data @- <<JSON
{
  "dataset": "$LOGDB_DATASET",
  "filter": {
    "record_id": "$LOG_RECORD_ID"
  },
  "page": {
    "limit": 10
  }
}
JSON

Expected output

{
  "status": "ok",
  "api_version": "v1",
  "tenant_id": "local",
  "dataset": "checkout",
  "matched_records": 1,
  "results": [{
    "record": {
      "record_id": "logdb_...",
      "source": "v1.otlp_http",
      "signal": "log",
      "raw_payload": {"record": {"body": {"stringValue": "payment accepted"}}}
    }
  }],
  "used_indexes": ["record_id"]
}

Send an OTLP JSON trace batch

Copy/paste

Post two trace spans with the same trace ID so the query route can prove a retained trace selection.

TRACE_RESPONSE="$(curl -s -X POST "$LOGDB_ENDPOINT/v1/otlp/traces" \
  -H 'content-type: application/json' \
  -H "x-logdb-tenant: $LOGDB_TENANT" \
  -H "authorization: Bearer $LOGDB_TOKEN" \
  --data '{
    "resourceSpans": [{
      "resource": {
        "attributes": [
          {"key": "tenant_id", "value": {"stringValue": "local"}},
          {"key": "service.name", "value": {"stringValue": "checkout"}}
        ]
      },
      "scopeSpans": [{
        "spans": [
          {
            "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
            "spanId": "00f067aa0ba902b7",
            "name": "POST /checkout",
            "startTimeUnixNano": "1783947600000000000"
          },
          {
            "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
            "spanId": "00f067aa0ba902b8",
            "name": "SELECT inventory",
            "startTimeUnixNano": "1783947600000000100"
          }
        ]
      }]
    }]
  }')"

printf '%s\n' "$TRACE_RESPONSE"

Expected output

{"status":"accepted","signal":"trace","accepted_records":2,"record_ids":["logdb_...","logdb_..."]}

Query by trace ID

Copy/paste

Search the same dataset by exact trace ID and request one result so pagination is visible.

TRACE_QUERY_RESPONSE="$(curl -s -X POST "$LOGDB_ENDPOINT/v1/query" \
  -H 'content-type: application/json' \
  -H "x-logdb-tenant: $LOGDB_TENANT" \
  -H "authorization: Bearer $LOGDB_TOKEN" \
  --data @- <<JSON
{
  "dataset": "$LOGDB_DATASET",
  "filter": {
    "trace_id": "$LOGDB_TRACE_ID"
  },
  "page": {
    "limit": 1
  }
}
JSON
)"

printf '%s\n' "$TRACE_QUERY_RESPONSE"

Expected output

{
  "status": "ok",
  "tenant_id": "local",
  "dataset": "checkout",
  "matched_records": 2,
  "results": [{"record": {"signal": "trace"}}],
  "page": {"limit": 1, "cursor": null, "next_cursor": "1"},
  "used_indexes": ["identity.trace_id"]
}

Fetch the next trace page

Copy/paste

Use the returned cursor to fetch the second retained trace record.

curl -s -X POST "$LOGDB_ENDPOINT/v1/query" \
  -H 'content-type: application/json' \
  -H "x-logdb-tenant: $LOGDB_TENANT" \
  -H "authorization: Bearer $LOGDB_TOKEN" \
  --data @- <<JSON
{
  "dataset": "$LOGDB_DATASET",
  "filter": {
    "trace_id": "$LOGDB_TRACE_ID"
  },
  "page": {
    "limit": 1,
    "cursor": "1"
  }
}
JSON

Expected output

{
  "status": "ok",
  "matched_records": 2,
  "results": [{"record": {"signal": "trace"}}],
  "page": {"limit": 1, "cursor": "1", "next_cursor": null}
}

Check the tenant policy boundary

Copy/paste

Send a query without the local tenant headers to see the current local policy reject the request.

curl -s -X POST "$LOGDB_ENDPOINT/v1/query" \
  -H 'content-type: application/json' \
  --data '{"dataset":"checkout"}'

Expected output

{"status":"rejected","retryable":false,"error":{"kind":"missing_tenant","message":"x-logdb-tenant header is required",...}}

Verify Success

The quickstart is successful when log ingest returns a logdb_... record ID, the exact-record query returns matched_records:1 with used_indexes:["record_id"], the trace query returns matched_records:2 with next_cursor:"1", the second trace page clears next_cursor, and the missing-header request returns missing_tenant.

Clean Up

Stop the service

Copy/paste

Stop LogDB with Ctrl-C in the service terminal before removing local tutorial data.

# Press Ctrl-C in the terminal running cargo run.

Expected output

The local LogDB process exits.

Remove tutorial data

Copy/paste

Remove only the disposable data directory used by this quickstart.

rm -rf "${TMPDIR:-/tmp}/logdb-docs-024"

Expected output

The tutorial data directory is gone. Do not remove a shared LOGDB_DATA_DIR.

Troubleshooting

Common first-run failures
SymptomHow to recognize itLikely causeFix
Service does not startcargo run reports that the address is already in use or cannot bind.Another local process is using 127.0.0.1:4318.Choose a different loopback port in LOGDB_BIND_ADDRESS and update LOGDB_ENDPOINT to match.
Health check cannot connectcurl reports connection refused or times out against 127.0.0.1:4318.The service terminal stopped, is still compiling, or is bound to a different address.Wait for Cargo to finish, confirm the service terminal is still open, and re-check LOGDB_ENDPOINT.
Ingest returns missing_tenantThe response status is 401 Unauthorized and the JSON error kind is missing_tenant.x-logdb-tenant was omitted or empty.Send x-logdb-tenant: local on OTLP JSON compatibility and query requests.
Ingest returns missing_credentialsThe response status is 401 Unauthorized and the JSON error kind is missing_credentials.The bearer token header was omitted or malformed.Send authorization: Bearer local-dev-token with the local tenant header.
Ingest returns tenant_mismatchThe response status is 403 Forbidden and the error mentions tenant claims.The OTLP resource attribute tenant_id or service.logdb.tenant_id does not match x-logdb-tenant.Use local in both the header and OTLP resource attributes for this quickstart.
Query returns zero matchesThe response status is ok, but matched_records is 0 and results is empty.The record ID, trace ID, dataset, or data directory does not match the ingest request.Re-run ingest, re-extract LOG_RECORD_ID, and confirm LOGDB_DATASET=checkout.
Trace page does not return next_cursorThe first trace query does not show page.next_cursor set to 1.Only one trace span was accepted, or the query used a different trace ID.Re-run the documented trace ingest command and query with LOGDB_TRACE_ID=4bf92f3577b34da6a3ce929d0e0e4736.

Evidence

Source-backed quickstart checks
Workflow stepEvidenceStatus
Service startup and healthLogDB source repository: README.md, LogDB/src/main.rs, LogDB/src/config.rs, and AutomatedTests/Health/HealthEndpointTests.csSource-backed; local run still needs reviewer acceptance
OTLP JSON compatibility ingestLogDB source repository: README.md, LogDB/src/handlers/otlp_http_handler.rs, LogDB/src/ingestion/otlp_http.rs, and AutomatedTests/Otlp/OtlpHttpEndpointTests.csSource-backed
Tenant admission policyLogDB source repository: LogDB/src/ingestion/tenant_admission.rs and query/ingest endpoint testsSource-backed
Query by record ID and trace IDLogDB source repository: docs/query/http-query-api.md, LogDB/src/handlers/query_handler.rs, LogDB/src/query/api.rs, and AutomatedTests/Query/QueryApiEndpointTests.csSource-backed
Segment publication and local limitsLogDB source repository: docs/ingestion/live-wal-gateway.md, docs/storage/segment-bundle-v1.md, and docs/fact-sheets/logdb.mdSource-backed; claims remain review-bound

Limits

Local Ingest And Query

This quickstart uses OTLP HTTP JSON compatibility routes and the local segment query store under LOGDB_DATA_DIR.

Tenant Headers Required

The local development policy accepts tenant local with bearer token local-dev-token; the OTLP tenant claim must match the header.

Narrow Signal Scope

The workflow covers logs, traces, retained segment search, record IDs, trace IDs, and pagination only.

Gated Claims

S3 publication, BYOC deployment, public replay APIs, external sinks, scale, availability, support, and performance remain outside this quickstart.

Next Steps

  • Available now

    Review LogDB evidence

    Use the evidence index before strengthening ingest, query, S3, replay, BYOC, or GA claims.

  • Available now

    Read tutorial prerequisites

    Check the shared local tool baseline and product-specific setup expectations for first-success tutorials.

  • Available: DOCS-033

    Read OTLP and query reference

    OTLP HTTP/protobuf, optional gRPC, JSON compatibility, custom endpoint, tenant header, limit, error, and query filter details.

  • Available: DOCS-039

    Compare OTLP and S3 query scope

    Distinguish live ingest, optional gRPC, local query, S3 query reads, metrics/profile exclusions, and future publication work.

  • Available: DOCS-060

    Use OpenTelemetry Collector examples

    Extend the quickstart with collector configuration, curl payloads, retained-record query checks, tenant headers, and local policy warnings.