Qpoint Data Schema Reference
Overview
Qpoint captures network traffic data in two distinct storage layers, each with different data structures and security characteristics:
EventStore: Anonymized connection metadata (summary information)
ObjectStore: Complete HTTP transaction payloads (may contain sensitive data)
This separation allows you to:
Store metadata in observability platforms (Axiom, OTLP backends)
Keep sensitive payloads in your own S3-compatible storage for data sovereignty
Link metadata to payloads using identifiers

EventStore Schema
EventStore contains anonymized metadata about network connections and HTTP transactions. These events do not include request/response bodies or sensitive headers.
Event Types
connection
TCP connection lifecycle and source attribution
No
artifact_record
Reference (and summary) for each stored HTTP artifact
No
issue
Error/anomaly detection
No
Connection Event
Establishes a network session with full source attribution via eBPF. Fields are grouped under meta, tags, source, destination, and other top-level properties:
Field Reference
Identifiers:
meta.connectionId(string): Unique identifier for this TCP connection. Links all events for this session.meta.endpointId(string): Destination domain or IP observed for this connection.
Source (your application):
source.address.ip/source.address.port: IP:port of the originating process.source.exe: Full executable path captured via eBPF.source.userId: UID of the process owner.
Destination (external service):
destination.address.*: IP and port of the peer endpoint.
Protocol detection & TLS probes:
l7Protocol:http1,http2, orotherif Qtap could not parse HTTP.socketProtocol: Typicallytcp.tlsVersion: Numeric TLS version (772 = TLS 1.3, 771 = TLS 1.2).meta.tlsProbeTypesDetected: TLS libraries hooked for this flow (openssl,gotls, etc.).
Context tags:
tags.bin: Process or container binary (e.g.,curl,tailscaled).tags.host,tags.ip,tags.protocol,tags.strategy: Additional grouping metadata added by Qtap.
Traffic metrics:
bytesSent,bytesReceived(optional): Directional byte counts for this socket. Only present when data transfer occurs on the connection.direction: Capture perspective (egress-external,egress-internal,ingress, etc.).
ArtifactRecord Event
Each stored object produces an artifact_record entry. Multiple records can share the same connectionId/requestId pair:
item.type
Description
Typical content
http_transaction
Full request+response artifact
Includes summary block with method/status/duration
req-headers, res-headers
Standalone header blobs
digest points to JSON containing only headers
req-body, res-body
Base64 body blobs
digest points to raw body object
Example (type: "http_transaction")
type: "http_transaction")Field Reference
Identifiers:
connectionId,endpointId,requestId: Match the corresponding connection and HTTP transaction.digest: Object key in your S3-compatible store (sha1 hex string).url: Direct fetch URL (Qtap substitutes{{DIGEST}}into the configuredaccess_url).
Summary (only on http_transaction records):
summary.connection_id(string): Connection ID matching the parent connection eventsummary.direction(string): Traffic direction (e.g., "egress-external")summary.duration_ms(number): Request duration in millisecondssummary.process_exe(string): Full path to the process executablesummary.request_host(string): Request authority/hostnamesummary.request_method(string): HTTP method (GET, POST, etc.)summary.request_protocol(string): HTTP version (http1, http2)summary.request_scheme(string): Request scheme (http, https)summary.request_content_type(string, optional): Content-Type of request body (only present when request includes a body)summary.response_content_type(string): Content-Type of responsesummary.response_status(number): HTTP status code
Use summary.response_status and summary.duration_ms to filter events without fetching full payloads from ObjectStore.
Other artifact types (req-headers, res-body, etc.) do not carry a summary block—they only include digest, type, timestamp, and the URL.
Issue Event
Issues are emitted by plugins such as detect_errors and appear as flat payloads (no nested issue/context objects). Example:
Key fields:
error: Name of the rule or issue type (e.g.,Server Errors).triggerConditions/triggerReasons: Why the rule fired.requestId: Use to pull the associated artifact.
ObjectStore Schema
ObjectStore contains complete HTTP transaction payloads, including headers and bodies. This data often contains:
Authentication tokens (JWTs, API keys)
Personally Identifiable Information (PII)
Business-sensitive data (financial info, user records)
Security: Store ObjectStore data in your own S3-compatible storage (MinIO, AWS S3, GCS) to maintain data sovereignty. Never send this to third-party observability platforms.
HttpTransaction Object
The complete HTTP request and response captured by Qtap.
Schema
Optional Top-Level Fields: When using Docker logging drivers (e.g., with Fluent Bit), you may see additional top-level fields like container_id, container_name, and source added by the Docker logging infrastructure.
Field Reference
Metadata (Source Attribution):
metadata.process_id,metadata.process_exe: Process identity.metadata.bytes_sent/metadata.bytes_received: Same byte counters as the connection event.metadata.connection_id,metadata.endpoint_id: Identifiers for correlation.Optional fields (only when Qtap observes them):
metadata.container_name,metadata.pod_name, etc. These were not present in the observed captures but can appear in containerized/Kubernetes deployments.
Request:
request.method(string): HTTP methodrequest.url(string): Complete URLrequest.scheme(string):httporhttpsrequest.path(string): URL pathrequest.authority(string): Host headerrequest.protocol(string): HTTP version (http1,http2)request.request_id(string): Unique transaction IDrequest.user_agent(string): User-Agent headerrequest.content_type(string): Content-Type header value (when request has a body)request.headers(object): All request headers (including Authorization)request.body(string): Base64-encoded request body (present when request includes body)
HTTP/2 Pseudo-Headers: Headers like :authority, :method, :path, :scheme are HTTP/2 pseudo-headers. For HTTP/1.1, these are represented as standard headers.
Response:
response.status,response.headers,response.body(base64). Body may be absent when capture level <full.
Timing & Direction:
transaction_time(string): ISO 8601 timestamp with nanosecond precisionduration_ms(number): Request duration in millisecondsdirection(string): Traffic direction (see Connection Event)
Decoding Bodies
Request and response bodies are base64-encoded to safely handle binary data:
Capture Levels
Qtap provides four capture levels that control what data appears in the HttpTransaction object:
none
No capture
Nothing
Disabled capture (can use with rules for selective capture)
summary
Basic info
metadata, request.method/url/status, duration_ms
High-level traffic monitoring
details
With headers
Everything in summary + request.headers + response.headers
Debugging without exposing bodies
full
Complete
Everything including request.body + response.body
Deep troubleshooting, audit trails
Example Configuration
Key Relationships
Identifier Hierarchy
connectionId: Links all events for a single TCP connection
One TCP connection can carry multiple HTTP requests (HTTP keep-alive)
Useful for correlating requests from the same socket
endpointId: The destination domain (e.g., "api.example.com")
NOT the source - this is the external service being called
Useful for grouping requests by destination
requestId: Unique per HTTP transaction
One-to-one mapping to HttpTransaction object
Primary key for correlating EventStore → ObjectStore
Source vs Destination
Critical distinction:
Source
Your application
Process, container, pod, user details
eBPF syscall hooks
Destination
External service
IP address, port, resolved hostname
Network layer
Why source has more detail:
Qtap uses eBPF to hook into the source process's system calls
Full process context (exe path, user, container ID) available via kernel
Destination is just an IP:port visible from network packets
Direction Values
The direction field indicates traffic flow relative to Qtap's capture point:
egress
All outbound traffic
Any request leaving your application
egress-external
Outbound to external networks
API calls to public internet
egress-internal
Outbound to internal networks
Service-to-service calls within cluster
ingress
Inbound traffic
Requests received by your server
all
Bidirectional
Capture both ingress and egress
Configure in qtap.yaml:
Protocol Detection
L7 Protocol Values
The l7Protocol field indicates whether Qtap successfully parsed the traffic as HTTP:
http1
HTTP/1.1 successfully parsed
✅ Connection Event + HttpTransaction + ArtifactRecord
http2
HTTP/2 successfully parsed
✅ Connection Event + HttpTransaction + ArtifactRecord
other
Non-HTTP protocol or parsing failed
⚠️ Connection Event only (no HTTP parsing)
Understanding l7Protocol: "other"
l7Protocol: "other"When you see l7Protocol: "other", Qtap detected a TCP connection but could not parse it as HTTP. This is expected and normal for non-HTTP protocols:
Common Protocols That Show as "other":
Database connections (MySQL port 3306, PostgreSQL port 5432, MongoDB port 27017, Redis port 6379)
SSH connections (port 22)
SMTP/email traffic (ports 25, 465, 587)
Custom binary protocols
gRPC with binary protobuf payloads (HTTP/2 framing detected, but content is binary)
DNS over HTTPS/TLS (HTTPS connection, but not standard HTTP request/response pattern)
What You Still Get:
✅ Connection Event with full metadata
✅ Process Attribution: Exact executable path (
source.exe)✅ Byte Counts:
bytesSentandbytesReceived✅ TLS Detection:
tlsVersionandtlsProbeTypesDetected(when applicable)✅ Endpoint: Destination IP/domain (
endpointId)
What You Don't Get:
❌ HttpTransaction object (no request/response parsing)
❌ ArtifactRecord events
❌ Request headers, bodies, or application-level data
Troubleshooting HTTP Traffic Showing as "other":
If you expect HTTP traffic but see l7Protocol: "other":
Check
tlsProbeTypesDetected- Is TLS detected? If empty, qtap may not have hooked the TLS libraryCheck
gotProtocolEvent: true- Was protocol detection attempted?Enable
--bpf-tracefor syscall-level debuggingVerify the application uses a supported TLS library (OpenSSL, Go TLS, Java SSL, Node TLS)
TLS Detection
is_tls: true- HTTPS traffic detectedtls_version: 772- TLS 1.3 (771 = TLS 1.2)tls_sni: "api.example.com"- Server Name Indication from handshaketls_probe_types_detected: ["openssl"]- OpenSSL library hooks attached
Supported TLS libraries:
openssl- OpenSSL library (all versions)gotls- Go's native TLS implementation (Pro version)javassl- Java SSL/TLS implementation (Pro version)nodetls- Node.js TLS implementation (Pro version)
Complete Example: Correlating Events
Scenario
Your application makes a POST request that returns a 500 error. Here's how the data flows:
1. Connection Event (EventStore)
2. Issue Event (EventStore)
3. ArtifactRecord Event (EventStore)
4. HttpTransaction Object (ObjectStore, retrieved from S3)
Query Pattern
Best Practices
Data Storage
EventStore → Observability Platform
Axiom, Datadog, Honeycomb, etc.
Safe for third-party platforms (no sensitive data)
Enables dashboards, alerts, and real-time monitoring
ObjectStore → Your S3
MinIO, AWS S3, Google Cloud Storage
Keep sensitive data in your infrastructure
Set TTL policies (recommended: 30-90 days)
Querying Strategy
Query EventStore first (fast, indexed)
Find relevant connections/requests by metadata
Filter by status codes, endpoints, duration, etc.
Fetch from ObjectStore only when needed (slower, S3 API calls)
Retrieve full payloads for specific incidents
Analyze auth tokens, request bodies, error details
Use identifiers to correlate
connection_id: Group all requests from same TCP sessionrequest_id: Link metadata to payloadendpoint_id: Filter by destination domain
Security Considerations
Never log ObjectStore data to stdout in production
Set appropriate S3 bucket policies (private, encrypted)
Use IAM roles, not static credentials
Implement TTL/lifecycle policies to auto-delete old data
Audit access to S3 payloads (contains auth tokens)
Performance Optimization
Use capture levels strategically:
summaryby default (low overhead)fullonly for errors or specific endpoints (via rules)
Filter noisy traffic at capture time (process filters, direction settings)
Batch S3 uploads with Fluent Bit for cost efficiency
Troubleshooting
Missing Fields
Problem: Expected fields not present in event
Solutions:
Container fields only present when running in Docker/containerd
Pod fields only present when running in Kubernetes
user/user_idonly available with sufficient permissions
l7Protocol: "other"
l7Protocol: "other"Problem: HTTP parsing failed, no HttpTransaction created
Diagnostics:
Check
tlsProbeTypesDetected- Empty array means TLS library not hookedCheck
gotProtocolEvent: false- Protocol detection didn't runEnable
--bpf-trace="mod:socket,exe.contains:yourapp"for syscall traces
Common causes:
Non-standard HTTP libraries
Custom TLS wrappers
Binary not using OpenSSL/BoringSSL
Empty Bodies
Problem: request.body or response.body is empty string
Check capture level:
Must be
level: fullto capture bodieslevel: headersonly captures headerslevel: summarycaptures neither
Verify with rules:
Additional Resources
Healthy Capture Patterns: appendix/healthy-capture-patterns.md - Examples of successful captures
BPF Trace Guide: appendix/bpf-trace.md - Syscall-level debugging
Configuration Examples: getting-started/qtap/configuration/configuration-examples.md
Traffic Processing with Plugins: getting-started/qtap/configuration/traffic-processing-with-plugins.md - Rulekit expressions and plugin configuration
Last updated