Integrating Qtap with Your Observability Stack

You already have an observability stack — Grafana + Loki, Datadog, Elastic, or similar — and S3-compatible object storage. This guide shows how Qtap slots into what you already run, without provisioning new infrastructure. Qtap speaks OTLP for events and S3 for payloads. If your stack can receive either, you're set.

circle-info

Need to build the full stack from scratch? See the Self-Hosted Grafana Observability Stackarrow-up-right guide instead.

How Qtap Fits In

┌──────────────────────────────────────────────────────────────────┐
│                        YOUR INFRASTRUCTURE                       │
│                                                                  │
│   ┌───────┐                                                      │
│   │ Qtap  │──── Events (OTLP) ──────► OTel Collector             │
│   │ Agent │                               │                      │
│   │       │                               ▼                      │
│   │       │                        Your Log Backend              │
│   │       │                     (Loki, Datadog, Elastic, …)      │
│   │       │                               ▲                      │
│   │       │                               │ artifact URLs        │
│   │       │                               ▼                      │
│   │       │── Objects (S3) ──────►  Your S3 Storage              │
│   │       │                      (MinIO, AWS S3, GCS, …)         │
│   └───────┘                                                      │
└──────────────────────────────────────────────────────────────────┘

Qtap produces two independent data streams. Events flow through your existing OTel pipeline. Objects go directly to your S3 storage. The access_url in each artifact_record event links the two together — click it to fetch the full HTTP transaction from S3.

Two Data Paths

Events
Objects

What

Lightweight metadata — method, URL, status, duration, process

HTTP transaction objects — metadata at summary level; headers and bodies at full level

Sensitivity

Low — safe to send to any backend

Varies — summary objects contain only metadata; full objects may contain API keys, tokens, PII

Protocol

OTLP (gRPC or HTTP)

S3 API

Destination

Any OTLP-compatible backend via OTel Collector

Any S3-compatible object storage

Volume

Every observed request

Every captured request (content varies by capture level)

The link between them: When Qtap stores an object in S3, it emits an artifact_record event containing a url field built from your access_url template. The {{DIGEST}} placeholder is replaced with the SHA1 hash of the stored object, creating a direct link from your log UI to the full HTTP transaction.

Configuring Qtap

One complete qtap.yaml that connects to your existing OTel Collector and S3 storage:

circle-exclamation
Placeholder
What to set

endpoint (event_stores)

Your OTel Collector address (e.g., otel-collector:4317)

endpoint (object_stores)

Your S3 storage address (e.g., s3.amazonaws.com)

bucket

Your S3 bucket name

region

Your S3 region

access_url

URL template that your dashboard users can reach (see Connecting to Your S3 Storage)

S3_ACCESS_KEY / S3_SECRET_KEY

Environment variable names holding your S3 credentials

Connecting to Your OTel Collector

If you already have an OTel Collector running, point Qtap's event_stores endpoint at it — no other changes needed. Qtap sends OTLP logs on the standard gRPC port (4317).

If your collector doesn't yet forward to a log backend, add the relevant exporter. For example, to forward to Loki:

This works with any OTLP-compatible backend — replace the exporter with whatever your stack uses (Datadog, Elastic, Honeycomb, etc.). See Backend-Specific Configurations for detailed examples.

Connecting to Your S3 Storage

Qtap's S3 object store works with any S3-compatible storage. Set the endpoint to match your provider:

Provider

Endpoint Example

access_url Example

MinIO

minio.internal:9000

https://minio.internal/{{BUCKET}}/{{DIGEST}}

AWS S3

s3.amazonaws.com

https://s3.amazonaws.com/{{BUCKET}}/{{DIGEST}}

Google Cloud Storage

storage.googleapis.com

https://storage.cloud.google.com/{{BUCKET}}/{{DIGEST}}

Garage

garage.internal:3900

http://garage.internal:3902/{{BUCKET}}/{{DIGEST}}

The access_url Template

The access_url determines the clickable link embedded in every artifact_record event. It supports three template variables:

  • {{DIGEST}} — SHA1 hash of the stored object (always required)

  • {{BUCKET}} — The bucket name from your config

  • {{ENDPOINT}} — The S3 endpoint from your config

The URL must be reachable by whoever is reading your logs. For internal dashboards, use an internal hostname. For shared access, consider:

  • Presigned URLs — Generate time-limited signed URLs for private buckets

  • Public bucket — Allow anonymous reads (development only)

  • Reverse proxy — Place nginx or similar in front of your S3 for access control

What You'll See

Qtap stores an HTTP transaction object in S3 and emits an artifact_record event for every captured request. At summary level, the object contains only metadata. At headers or full level, it includes the complete request/response headers and bodies.

The artifact_record Event

Search your log backend for event_type="artifact_record" to find stored objects:

The Stored Object

Click the url to fetch the full HTTP transaction from your S3 storage:

This works in any log UI — search for artifact_record events, click the URL, and you have the full request and response.

circle-info

All capture levels generate artifact_record events and store objects in S3. The difference is content: summary objects contain only metadata (method, URL, status), while headers and full objects include the complete request/response headers and bodies.

Common Configurations

These snippets show just the services: block — the rest of the config (rulekit, stacks, tap) stays the same as the full example above.

Loki + MinIO

Datadog + AWS S3

Elastic + Google Cloud Storage

Verification Checklist

  1. Check OTel Collector — Look for received log entries in your collector's output

  2. Query your log backend — Search for service_name="qtap" events

  3. List S3 objects — Verify objects appear in your bucket after generating traffic

  4. Test object linking — Find an artifact_record event and open the URL to confirm the full HTTP transaction is accessible

Next Steps

Last updated