Elastic Backend
Uses Elasticsearch DSL for log queries, aggregations for metrics, and Elastic APM for distributed tracing.
TINKR_BACKEND=elastic
Authentication
Tinkr authenticates to Elasticsearch using an API key. Create one in Kibana:
Stack Management → Security → API Keys → Create API Key
Grant the key:
readon indiceslogs-*,filebeat-*,traces-*,apm-*monitoron cluster
Or use a username/password for simpler setups.
Environment variables
| Variable | Required | Description |
|---|---|---|
ELASTIC_URL | Yes | Elasticsearch base URL (e.g. https://elastic.acme.internal:9200) |
ELASTIC_API_KEY | Yes (or user/pass) | Base64-encoded API key from Kibana |
ELASTIC_USERNAME | Alt to API key | Elasticsearch username |
ELASTIC_PASSWORD | Alt to API key | Elasticsearch password |
ELASTIC_INDEX_PATTERN | No | Log index pattern (default: logs-*,filebeat-*) |
Profile configuration
[profiles.elastic-prod]
backend = "elastic"
url = "env:ELASTIC_URL"
index_pattern = "logs-*,filebeat-*"
ELASTIC_URL=https://elastic.acme.internal:9200
ELASTIC_API_KEY=VnVhQ2ZHY0JDZGJrZXctATxxxxxxxxxxxxxxxx==
Log query (Elasticsearch DSL)
Tinkr queries using the Elasticsearch DSL:
{
"query": {
"bool": {
"must": [
{ "match": { "service.name": "payments-api" } },
{ "match": { "log.level": "ERROR" } },
{ "range": { "@timestamp": { "gte": "now-1h", "lte": "now" } } }
]
}
},
"sort": [{ "@timestamp": { "order": "desc" } }],
"size": 100
}
Field mapping (ECS-aligned):
| Tinkr field | Elasticsearch field |
|---|---|
service | service.name |
level | log.level |
timestamp | @timestamp |
message | message |
If your indices use a different field layout, set ELASTIC_INDEX_PATTERN to target the right indices.
Metrics (aggregations)
Tinkr uses Elasticsearch date-histogram aggregations to compute metric time series:
{
"query": { "term": { "service.name": "payments-api" } },
"aggs": {
"over_time": {
"date_histogram": { "field": "@timestamp", "fixed_interval": "5m" },
"aggs": { "error_count": { "filter": { "term": { "log.level": "ERROR" } } } }
}
}
}
Distributed tracing (Elastic APM)
Tinkr queries the traces-* and apm-* indices for root spans (spans with no parent.id):
{
"query": {
"bool": {
"must": [
{ "term": { "service.name": "payments-api" } },
{ "range": { "@timestamp": { "gte": "now-1h" } } }
],
"must_not": [{ "exists": { "field": "parent.id" } }]
}
},
"sort": [{ "transaction.duration.us": { "order": "desc" } }],
"size": 20
}
To send traces from your application, use the Elastic APM agent:
# Python
import elasticapm
client = elasticapm.Client(service_name="payments-api", server_url="http://apm-server:8200")
Or use the OpenTelemetry SDK with the OTLP exporter pointing to the Elastic APM server (which accepts OTLP natively since 7.16).
Elastic Cloud (hosted)
For Elastic Cloud, use the Cloud ID + API key:
ELASTIC_URL=https://xxxxxxxxxxxx.es.us-east-1.aws.elastic-cloud.com:9243
ELASTIC_API_KEY=VnVhQ2ZHY0JDZGJrZXctATxxxxxxxxxxxxxxxx==
Local development
# Run Elasticsearch + Kibana locally
docker run -p 9200:9200 -e "discovery.type=single-node" elasticsearch:8.x
export TINKR_BACKEND=elastic
export ELASTIC_URL=http://localhost:9200
export ELASTIC_USERNAME=elastic
export ELASTIC_PASSWORD=changeme
uv run tinkr-server