Skip to content

Instantly share code, notes, and snippets.

@defanator
Created May 14, 2025 12:55
Show Gist options
  • Save defanator/cb8788ecc2fc5089fcea53b7fa54839d to your computer and use it in GitHub Desktop.
Save defanator/cb8788ecc2fc5089fcea53b7fa54839d to your computer and use it in GitHub Desktop.
alloy conversion from native loki to OTLP
networks:
grafana:
name: grafana
services:
loki:
container_name: loki
image: docker.io/grafana/loki:3.5.0
command: -config.file=/etc/loki/loki.yml
volumes:
- ./loki.yml:/etc/loki/loki.yml
ports:
- "3100:3100"
networks:
- grafana
grafana:
container_name: grafana
image: docker.io/grafana/grafana-enterprise:12.0.0
environment:
- GF_PATHS_PROVISIONING=/etc/grafana/provisioning
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
entrypoint:
- sh
- -euc
- |
mkdir -p /etc/grafana/provisioning/datasources
cat <<EOF > /etc/grafana/provisioning/datasources/ds.yaml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
basicAuth: false
isDefault: true
version: 1
editable: false
- name: Loki
type: loki
access: proxy
orgId: 1
url: http://loki:3100
basicAuth: false
isDefault: false
version: 1
editable: false
EOF
/run.sh
ports:
- "3000:3000"
networks:
- grafana
alloy:
container_name: alloy
image: docker.io/grafana/alloy:v1.8.2
environment:
- HOSTNAME
command: run --server.http.listen-addr=0.0.0.0:12345 --storage.path=/var/lib/alloy/data --disable-reporting --stability.level=generally-available /etc/alloy/config.alloy
volumes:
- ./config.alloy:/etc/alloy/config.alloy
ports:
- "12345:12345"
- "3101:3100"
networks:
- grafana
logging {
level = "debug"
format = "logfmt"
}
livedebugging {
enabled = true
}
loki.source.api "nginxagents" {
http {
listen_port = 3100
}
graceful_shutdown_timeout = "0s"
forward_to = [otelcol.receiver.loki.loki2otlp.receiver]
labels = {}
relabel_rules = null
use_incoming_timestamp = true
}
otelcol.receiver.loki "loki2otlp" {
output {
//logs = [otelcol.exporter.loki.otlp2loki.input]
//logs = [otelcol.processor.filter.otlp_filter.input]
logs = [otelcol.processor.transform.otlp_transformer.input]
}
}
otelcol.processor.filter "otlp_filter" {
error_mode = "ignore"
logs {
log_record = [
`UnixSeconds(Now()) - UnixSeconds(log.observed_time) > 5`,
]
}
output {
logs = [otelcol.exporter.loki.otlp2loki.input]
}
}
otelcol.processor.transform "otlp_transformer" {
error_mode = "ignore"
log_statements {
context = "log"
//statements = [
// `set(attributes["is_stale"], "true") where (UnixSeconds(Now()) - UnixSeconds(log.observed_time) > 5)`,
//]
//statements = [
// `set(attributes["is_stale"], "true") where (UnixSeconds(Now()) - UnixSeconds(observed_timestamp) > 5)`,
// ]
statements = [
`set(attributes["obs_ts"], UnixSeconds(log.observed_time))`,
]
}
output {
logs = [otelcol.exporter.loki.otlp2loki.input]
}
}
otelcol.exporter.loki "otlp2loki" {
forward_to = [loki.write.loki.receiver]
}
loki.write "loki" {
endpoint {
url = "http://loki:3100/loki/api/v1/push"
}
}
auth_enabled: false
server:
http_listen_port: 3100
common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
#ruler:
# alertmanager_url: http://localhost:9093
analytics:
reporting_enabled: false
usage_stats_url: ""
#!/bin/bash -x
LOKI_PUSH_URL="http://127.0.0.1:3101/loki/api/v1/push"
LOKI_MSG_TEMPLATE="{\"streams\": [{\"stream\": {\"job\": \"populate_loki\", \"service_name\": \"test\", \"host\": \"${HOSTNAME}\"}, \"values\": [[\"TIMESTAMP\", \"MESSAGE\"]]}]}"
_curl_cmd() {
curl -fsS \
-H "Content-Type: application/json" \
-H "Connection: close" \
"$@"
}
# alter timestamp after every 3 messages
skew_after=3
# timestamp delta in seconds
skew_delta=10
count=0
while true; do
count=$(( count + 1 ))
msg=$(openssl rand -base64 32)
ts=$(date +%s)
if (( count > skew_after )); then
ts=$(( ts - skew_delta ))
count=0
fi
ts_ns=$(( ts * 10**9 ))
post_body="${LOKI_MSG_TEMPLATE}"
post_body="${post_body/TIMESTAMP/$ts_ns}"
post_body="${post_body/MESSAGE/$msg $ts}"
if ! _curl_cmd -d "${post_body}" "${LOKI_PUSH_URL}"; then
echo "POST FAILED: '${post_body}'" >&2
exit 1
fi
sleep 1
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment