Custom Tagging
Custom tags allow you to attach metadata to captured connections based on process environment variables, container labels, or Kubernetes labels and annotations. This is especially useful for:
Multi-tenant environments: Tag traffic by team, customer, or tenant
Environment identification: Distinguish between production, staging, and development traffic
Cost allocation: Track usage by department, project, or business unit
Service organization: Identify traffic by service name, version, or component
Qplane filtering: Filter and organize captured traffic in the Qplane UI by custom dimensions
Custom tags appear in the tags object of Connection events (event store) alongside default tags like bin, host, ip, protocol, and strategy. Tags are connection-level metadata and do not appear in HTTP transaction objects (object store).
Configuration
Custom tags are defined in the tags section of your qtap configuration:
tags:
- key: team
source: env
location: TEAM
- key: service
source: container.label
location: service
- key: environment
source: k8s.label
location: envField Reference
key
string
Yes
The name of the tag as it will appear in the tags object
location
string
Yes
The specific environment variable name, label key, or annotation key to extract
Tag Sources
Qtap supports extracting tag values from multiple sources:
env
Environment variable from the monitored process
source: env
location: APP_NAME
container.label
Docker container label
source: container.label
location: service
k8s.label
Kubernetes pod label
source: k8s.label
location: team
k8s.annotation
Kubernetes pod annotation
source: k8s.annotation
location: version
Examples
Environment Variables
Extract tags from environment variables set on your applications:
version: 2
services:
event_stores:
- type: stdout
tags:
- key: team
source: env
location: TEAM
- key: app
source: env
location: APP_NAME
- key: environment
source: env
location: ENVIRONMENT
stacks:
default_stack:
plugins:
- type: http_capture
config:
level: summary
format: json
tap:
direction: egress
ignore_loopback: true
http:
stack: default_stackWhen you run your application with environment variables:
TEAM=platform APP_NAME=api-gateway ENVIRONMENT=production python ./app.pyThe captured connections will include:
{
"tags": {
"app": ["api-gateway"],
"bin": ["python"],
"environment": ["production"],
"host": ["qpoint"],
"ip": ["192.168.1.100"],
"protocol": ["http2"],
"strategy": ["observe"],
"team": ["platform"]
}
}Container Labels
Extract tags from Docker container labels:
tags:
- key: service
source: container.label
location: service
- key: version
source: container.label
location: versionRun containers with labels:
docker run --label service=web-frontend --label version=v2.1.0 myapp:latestTags in captured connections:
{
"tags": {
"service": ["web-frontend"],
"version": ["v2.1.0"],
"bin": ["node"],
"host": ["qpoint"]
}
}Kubernetes Labels
Extract tags from Kubernetes pod labels:
tags:
- key: team
source: k8s.label
location: team
- key: app
source: k8s.label
location: appPod manifest with labels:
apiVersion: v1
kind: Pod
metadata:
name: api-server
labels:
app: api-server
team: backend
spec:
containers:
- name: api
image: myapp:latestTags in captured connections:
{
"tags": {
"app": ["api-server"],
"team": ["backend"],
"bin": ["node"],
"host": ["k8s-node-01"]
}
}Kubernetes Annotations
Extract tags from Kubernetes pod annotations:
tags:
- key: version
source: k8s.annotation
location: app.version
- key: owner
source: k8s.annotation
location: ownerPod manifest with annotations:
apiVersion: v1
kind: Pod
metadata:
name: api-server
annotations:
app.version: "2.1.0"
owner: "platform-team"
spec:
containers:
- name: api
image: myapp:latestCombining Tag Sources
You can combine tags from multiple sources:
tags:
# From environment variables
- key: environment
source: env
location: ENVIRONMENT
# From container labels
- key: service
source: container.label
location: service
# From Kubernetes labels
- key: team
source: k8s.label
location: team
# From Kubernetes annotations
- key: version
source: k8s.annotation
location: versionAll tags from different sources are merged together in the Connection event.
Static Tags (CLI Flag)
In addition to dynamic tags extracted from the YAML configuration, you can add static tags to all connections using the --tags CLI flag:
qtap --config=/path/to/qtap.yaml \
--tags='region:us-west,deployment:production,cluster:main'Static tags are useful for:
Identifying the qtap instance or node
Tagging by region, datacenter, or availability zone
Marking deployment environment at the infrastructure level
Static tags and dynamic tags (from YAML) are merged together:
{
"tags": {
"app": ["api-gateway"], // from env var (YAML)
"team": ["platform"], // from env var (YAML)
"region": ["us-west"], // from CLI --tags
"deployment": ["production"], // from CLI --tags
"cluster": ["main"], // from CLI --tags
"bin": ["python"], // default
"host": ["qpoint"], // default
"protocol": ["http2"], // default
"strategy": ["observe"] // default
}
}Tag Behavior
Missing Values
If a tag's source value doesn't exist, the tag is simply omitted from the output (no errors are logged):
tags:
- key: team
source: env
location: TEAM # If TEAM env var not set, tag won't appearIf the TEAM environment variable is not set on the process, the team tag won't appear in the Connection event.
Tag Merging
When the same tag key is defined in multiple sources, all values are merged into an array:
Example with environment variable and CLI flag:
tags:
- key: team
source: env
location: TEAMTEAM=platform-yaml ./my-appqtap --tags='team:platform-cli' ...Result:
{
"tags": {
"team": ["platform-yaml", "platform-cli"]
}
}This applies to all tag sources:
YAML-defined tags (env, container.label, k8s.label, k8s.annotation)
CLI
--tagsflagDefault qtap tags (bin, host, ip, protocol, strategy)
Even default tags can be extended:
qtap --tags='bin:my-custom-bin,host:my-custom-host' ...Result:
{
"tags": {
"bin": ["curl", "my-custom-bin"],
"host": ["qpoint", "my-custom-host"]
}
}All tag values from all sources are preserved in the array.
Use Cases
Multi-Tenant SaaS Platform
Tag traffic by tenant and tier for cost allocation:
tags:
- key: tenant_id
source: env
location: TENANT_ID
- key: tier
source: env
location: SERVICE_TIERRun application:
TENANT_ID=customer-123 SERVICE_TIER=premium python ./app.pyMicroservices Environment
Identify traffic by service, version, and team:
tags:
- key: service
source: k8s.label
location: app
- key: version
source: k8s.annotation
location: version
- key: team
source: k8s.label
location: teamCost Tracking by Department
Tag traffic for cost allocation across departments:
tags:
- key: department
source: env
location: DEPARTMENT
- key: cost_center
source: env
location: COST_CENTER
- key: project
source: env
location: PROJECT_IDRun application:
DEPARTMENT=engineering COST_CENTER=R001 PROJECT_ID=api-v2 ./my-appEnvironment-Specific Tagging
Distinguish between production, staging, and development:
tags:
- key: environment
source: env
location: ENV
- key: region
source: env
location: AWS_REGIONRun in production:
ENV=production AWS_REGION=us-west-2 ./my-appRun in staging:
ENV=staging AWS_REGION=us-east-1 ./my-appViewing Tags in Qplane
When qtap is connected to Qplane, custom tags appear in the Qplane UI and can be used for:
Filtering connections: Filter by team, environment, service, etc.
Grouping traffic: Group connections by custom dimensions
Creating dashboards: Visualize traffic patterns by custom tags
Setting alerts: Alert on traffic patterns for specific tags
Custom tags make it easy to organize and filter large volumes of captured traffic across multiple teams, services, and environments.
Best Practices
Security Considerations
Avoid tagging sensitive data: Don't extract environment variables or labels that contain secrets, credentials, or personally identifiable information (PII).
# AVOID - these could contain sensitive data
tags:
- key: api_key
source: env
location: API_KEY # ❌ Never tag secrets
- key: user_email
source: env
location: USER_EMAIL # ❌ Avoid PII
# Good - safe metadata
tags:
- key: service
source: env
location: SERVICE_NAME # ✅ Safe
- key: team
source: env
location: TEAM # ✅ SafeUse Static Tags for Infrastructure
Use the --tags CLI flag for infrastructure-level tags that don't change per process:
# Tag by region and cluster
qtap --tags='region:us-west-2,cluster:production,zone:a'
# Tag by datacenter and rack
qtap --tags='datacenter:dc1,rack:r42'Use YAML tags for application-level tags that vary per process:
# Tag by application attributes
tags:
- key: service
source: env
location: SERVICE_NAME
- key: version
source: env
location: APP_VERSIONComplete Example
Here's a complete configuration combining multiple tag sources:
version: 2
services:
event_stores:
- type: s3
config:
bucket: my-qtap-events
region: us-west-2
object_stores:
- type: s3
config:
bucket: my-qtap-objects
region: us-west-2
tags:
# Application-level tags from environment
- key: service
source: env
location: SERVICE_NAME
- key: version
source: env
location: APP_VERSION
- key: environment
source: env
location: ENVIRONMENT
# Team ownership from Kubernetes
- key: team
source: k8s.label
location: team
- key: cost_center
source: k8s.annotation
location: cost-center
stacks:
default_stack:
plugins:
- type: http_capture
config:
level: summary
format: json
tap:
direction: egress
ignore_loopback: true
audit_include_dns: false
http:
stack: default_stackStart qtap with static infrastructure tags:
qtap --config=/etc/qtap/config.yaml \
--tags='region:us-west-2,cluster:production'Run your application with environment variables:
SERVICE_NAME=api-gateway \
APP_VERSION=2.1.0 \
ENVIRONMENT=production \
python ./app.pyThe resulting Connection events will include all tags:
{
"meta": {
"connectionId": "conn-123",
"endpointId": "api.example.com"
},
"tags": {
"service": ["api-gateway"],
"version": ["2.1.0"],
"environment": ["production"],
"team": ["platform"],
"cost_center": ["engineering-001"],
"region": ["us-west-2"],
"cluster": ["production"],
"bin": ["python"],
"host": ["k8s-node-01"],
"ip": ["10.0.1.50"],
"protocol": ["http2"],
"strategy": ["observe"]
},
"timestamp": "2025-11-03T18:30:00Z",
"direction": "egress-external",
"source": {
"exe": "/usr/bin/python3",
"address": {
"ip": "10.0.1.50",
"port": 45678
}
},
"destination": {
"address": {
"ip": "52.1.2.3",
"port": 443
}
}
}Last updated