MINOR: otel: test: added full-event test config

Added the 'full' test configuration that exercises all 29 supported OTel
filter events with all three signal types (traces, metrics, logs).  Every
instrument definition has a corresponding update.
This commit is contained in:
Miroslav Zagorac 2026-03-13 22:12:49 +01:00 committed by William Lallemand
parent 6f177cd01e
commit 579d1247f2
4 changed files with 570 additions and 0 deletions

View File

@ -0,0 +1,28 @@
global
stats socket /tmp/haproxy.sock mode 666 level admin
listen stats
mode http
bind *:8001
stats uri /
stats admin if TRUE
stats refresh 10s
frontend otel-test-full-frontend
bind *:10080
default_backend servers-backend
# ACL used to distinguish successful from error responses
acl acl-http-status-ok status 100:399
# OTel filter
filter opentelemetry id otel-test-full config full/otel.cfg
# run response scopes for successful responses
http-response otel-group otel-test-full http_response_group if acl-http-status-ok
# run after-response scopes for error responses
http-after-response otel-group otel-test-full http_after_response_group if !acl-http-status-ok
backend servers-backend
server server-1 127.0.0.1:8000

View File

@ -0,0 +1,280 @@
[otel-test-full]
otel-instrumentation otel-test-instrumentation
debug-level 0x77f
log localhost:514 local7 debug
config full/otel.yml
option dontlog-normal
option hard-errors
no option disabled
rate-limit 100.0
groups http_response_group
groups http_after_response_group
scopes on_stream_start
scopes on_stream_stop
scopes on_idle_timeout
scopes on_backend_set
scopes client_session_start
scopes frontend_tcp_request
scopes http_wait_request
scopes http_body_request
scopes frontend_http_request
scopes switching_rules_request
scopes backend_tcp_request
scopes backend_http_request
scopes process_server_rules_request
scopes http_process_request
scopes tcp_rdp_cookie_request
scopes process_sticking_rules_request
scopes http_headers_request
scopes http_end_request
scopes client_session_end
scopes server_unavailable
scopes server_session_start
scopes tcp_response
scopes http_wait_response
scopes process_store_rules_response
scopes http_response http_response-error
scopes http_headers_response
scopes http_end_response
scopes http_reply
scopes server_session_end
otel-group http_response_group
scopes http_response_1
scopes http_response_2
otel-scope http_response_1
span "HTTP response"
event "event_content" "hdr.content" res.hdr("content-type") str("; length: ") res.hdr("content-length") str(" bytes")
otel-scope http_response_2
span "HTTP response"
event "event_date" "hdr.date" res.hdr("date") str(" / ") res.hdr("last-modified")
otel-group http_after_response_group
scopes http_after_response
otel-scope http_after_response
span "HAProxy response" parent "HAProxy session"
status "error" str("http.status_code: ") status
otel-scope on_stream_start
instrument udcnt_int "haproxy.sessions.active" desc "Active sessions" value int(1) unit "{session}"
instrument gauge_int "haproxy.fe.connections" desc "Frontend connections" value fe_conn unit "{connection}"
span "HAProxy session" root
baggage "haproxy_id" var(sess.otel.uuid)
event "event_ip" "src" src str(":") src_port
event "event_be" "be" be_id str(" ") be_name
event "event_ip" "dst" dst str(":") dst_port
event "event_fe" "fe" fe_id str(" ") fe_name
log-record trace id 1000 event "session-start" span "HAProxy session" attr "attr_1_key" "attr_1_value" attr "attr_2_key" "attr_2_value" src str(":") src_port
acl acl-test-src-ip src 127.0.0.1
otel-event on-stream-start if acl-test-src-ip
otel-scope on_stream_stop
finish *
log-record info event "session-stop" str("stream stopped")
otel-event on-stream-stop
otel-scope on_idle_timeout
idle-timeout 1s
span "heartbeat" parent "HAProxy session"
attribute "idle.elapsed" str("idle-check")
instrument cnt_int "idle.count" value int(1)
instrument update "idle.count"
log-record info str("heartbeat")
otel-event on-idle-timeout
otel-scope on_backend_set
span "Backend set" parent "HAProxy session"
attribute "backend.name" be_name
attribute "backend.id" be_id
instrument cnt_int "haproxy.backend.set" desc "Backend assignments" value int(1) unit "{assignment}"
instrument update "haproxy.backend.set"
log-record info id 1010 event "backend-set" span "Backend set" be_name
otel-event on-backend-set
otel-scope client_session_start
span "Client session" parent "HAProxy session"
instrument cnt_int "haproxy.client.session.start" desc "Client session starts" value int(1) unit "{session}"
log-record info id 1001 event "client-session-start" span "Client session" src str(":") src_port
otel-event on-client-session-start
otel-scope frontend_tcp_request
span "Frontend TCP request" parent "Client session"
instrument cnt_int "haproxy.tcp.request.fe" desc "Frontend TCP requests" value int(1) unit "{request}"
log-record info event "frontend-tcp-request" span "Frontend TCP request" src str(":") src_port
otel-event on-frontend-tcp-request
otel-scope http_wait_request
span "HTTP wait request" parent "Frontend TCP request"
finish "Frontend TCP request"
log-record info event "http-wait-request" span "HTTP wait request" str("waiting")
otel-event on-http-wait-request
otel-scope http_body_request
span "HTTP body request" parent "HTTP wait request"
finish "HTTP wait request"
log-record info event "http-body-request" span "HTTP body request" str("body")
otel-event on-http-body-request
otel-scope frontend_http_request
instrument cnt_int "haproxy.http.requests" desc "HTTP request count" value int(1) unit "{request}"
instrument hist_int "haproxy.http.latency" desc "HTTP request latency" value lat_ns_tot unit "ns" aggr "histogram" bounds "1000 1000000 1000000000"
instrument update "haproxy.http.latency" attr "phase" "request"
instrument update "haproxy.tcp.request.fe"
span "Frontend HTTP request" parent "HTTP body request" link "HAProxy session"
attribute "http.method" method
attribute "http.url" url
attribute "http.version" str("HTTP/") req.ver
finish "HTTP body request"
log-record info id 1002 event "http-request" span "Frontend HTTP request" attr "http.method" "GET" method url
otel-event on-frontend-http-request
otel-scope switching_rules_request
span "Switching rules request" parent "Frontend HTTP request"
finish "Frontend HTTP request"
log-record info event "switching-rules" span "Switching rules request" be_name
otel-event on-switching-rules-request
otel-scope backend_tcp_request
span "Backend TCP request" parent "Switching rules request"
finish "Switching rules request"
instrument cnt_int "haproxy.tcp.request.be" desc "Backend TCP requests" value int(1) unit "{request}"
log-record info event "backend-tcp-request" span "Backend TCP request" be_name
otel-event on-backend-tcp-request
otel-scope backend_http_request
instrument update "haproxy.tcp.request.be"
span "Backend HTTP request" parent "Backend TCP request"
finish "Backend TCP request"
log-record info event "backend-http-request" span "Backend HTTP request" be_name
otel-event on-backend-http-request
otel-scope process_server_rules_request
span "Process server rules request" parent "Backend HTTP request"
finish "Backend HTTP request"
log-record info event "server-rules" span "Process server rules request" str("processing")
otel-event on-process-server-rules-request
otel-scope http_process_request
span "HTTP process request" parent "Process server rules request"
finish "Process server rules request"
log-record info event "http-process" span "HTTP process request" str("processing")
otel-event on-http-process-request
otel-scope tcp_rdp_cookie_request
span "TCP RDP cookie request" parent "HTTP process request"
finish "HTTP process request"
log-record info event "tcp-rdp-cookie" span "TCP RDP cookie request" str("cookie")
otel-event on-tcp-rdp-cookie-request
otel-scope process_sticking_rules_request
span "Process sticking rules request" parent "TCP RDP cookie request"
finish "TCP RDP cookie request"
log-record info event "sticking-rules" span "Process sticking rules request" str("sticking")
otel-event on-process-sticking-rules-request
otel-scope http_headers_request
span "HTTP headers request" parent "Process sticking rules request"
finish "Process sticking rules request"
instrument cnt_int "haproxy.http.headers.request" desc "Request headers processed" value int(1) unit "{header}"
log-record info event "http-headers-request" span "HTTP headers request" method url
otel-event on-http-headers-request
otel-scope http_end_request
span "HTTP end request" parent "HTTP headers request"
finish "HTTP headers request"
instrument cnt_int "haproxy.http.end.request" desc "Request end events" value int(1) unit "{request}"
instrument update "haproxy.http.headers.request"
log-record info event "http-end-request" span "HTTP end request" str("end")
otel-event on-http-end-request
otel-scope client_session_end
instrument update "haproxy.sessions.active"
instrument update "haproxy.client.session.start"
instrument update "haproxy.http.end.request"
finish "*req*"
log-record info event "client-session-end" str("session ended")
otel-event on-client-session-end
otel-scope server_unavailable
finish "*req*" "*res*"
log-record warn event "server-unavailable" str("503 Service Unavailable")
otel-event on-server-unavailable
otel-scope server_session_start
span "Server session" parent "HAProxy session"
link "HAProxy session" "Client session"
finish "HTTP end request"
instrument cnt_int "haproxy.server.session.start" desc "Server session starts" value int(1) unit "{session}"
log-record info event "server-session-start" span "Server session" str("server session")
otel-event on-server-session-start
otel-scope tcp_response
span "TCP response" parent "Server session"
instrument cnt_int "haproxy.tcp.response" desc "TCP responses" value int(1) unit "{response}"
log-record info event "tcp-response" span "TCP response" str("tcp response")
otel-event on-tcp-response
otel-scope http_wait_response
instrument update "haproxy.tcp.response"
span "HTTP wait response" parent "TCP response"
finish "TCP response"
log-record info event "http-wait-response" span "HTTP wait response" str("waiting")
otel-event on-http-wait-response
otel-scope process_store_rules_response
span "Process store rules response" parent "HTTP wait response"
finish "HTTP wait response"
log-record info event "store-rules" span "Process store rules response" str("store rules")
otel-event on-process-store-rules-response
otel-scope http_response
instrument update "haproxy.http.requests" attr "phase" "response"
instrument update "haproxy.http.latency" attr "phase" "response"
instrument update "haproxy.fe.connections"
span "HTTP response" parent "Process store rules response"
attribute "http.status_code" status
finish "Process store rules response"
log-record info id 1003 event "http-response" span "HTTP response" status
otel-event on-http-response
otel-scope http_response-error
span "HTTP response"
status "error" str("http.status_code: ") status
otel-event on-http-response if !acl-http-status-ok
otel-scope http_headers_response
span "HTTP headers response" parent "HTTP response"
finish "HTTP response"
instrument cnt_int "haproxy.http.headers.response" desc "Response headers processed" value int(1) unit "{header}"
log-record info event "http-headers-response" span "HTTP headers response" status
otel-event on-http-headers-response
otel-scope http_end_response
span "HTTP end response" parent "HTTP headers response"
finish "HTTP headers response"
instrument cnt_int "haproxy.http.end.response" desc "Response end events" value int(1) unit "{response}"
instrument update "haproxy.http.headers.response"
log-record info event "http-end-response" span "HTTP end response" str("end")
otel-event on-http-end-response
otel-scope http_reply
span "HTTP reply" parent "HTTP end response"
finish "HTTP end response"
instrument cnt_int "haproxy.http.reply" desc "HTTP replies" value int(1) unit "{reply}"
instrument update "haproxy.http.end.response"
log-record info event "http-reply" span "HTTP reply" status
otel-event on-http-reply
otel-scope server_session_end
instrument update "haproxy.server.session.start"
instrument update "haproxy.http.reply"
finish "*res*"
log-record info event "server-session-end" str("server session ended")
otel-event on-server-session-end

View File

@ -0,0 +1,246 @@
exporters:
exporter_traces_otlp_file:
type: otlp_file
thread_name: "OTLP/file trace"
file_pattern: "__full_traces_log-%F-%N"
alias_pattern: "__traces_log-latest"
flush_interval: 30000000
flush_count: 256
file_size: 134217728
rotate_size: 5
exporter_traces_otlp_grpc:
type: otlp_grpc
thread_name: "OTLP/gRPC trace"
endpoint: "http://localhost:4317/v1/traces"
use_ssl_credentials: false
# ssl_credentials_cacert_path: ""
# ssl_credentials_cacert_as_string: ""
# ssl_client_key_path: ""
# ssl_client_key_string: ""
# ssl_client_cert_path: ""
# ssl_client_cert_string: ""
# timeout: 10
# user_agent: ""
# max_threads: 0
# compression: ""
# max_concurrent_requests: 0
exporter_traces_otlp_http:
type: otlp_http
thread_name: "OTLP/HTTP trace"
endpoint: "http://localhost:4318/v1/traces"
content_type: json
json_bytes_mapping: hexid
debug: false
timeout: 10
http_headers:
- X-OTel-Header-1: "OTLP HTTP traces test header #1"
- X-OTel-Header-2: "OTLP HTTP traces test header #2"
max_concurrent_requests: 64
max_requests_per_connection: 8
ssl_insecure_skip_verify: true
# ssl_ca_cert_path: ""
# ssl_ca_cert_string: ""
# ssl_client_key_path: ""
# ssl_client_key_string: ""
# ssl_client_cert_path: ""
# ssl_client_cert_string: ""
# ssl_min_tls: ""
# ssl_max_tls: ""
# ssl_cipher: ""
# ssl_cipher_suite: ""
# compression: ""
exporter_traces_dev_null:
type: ostream
filename: /dev/null
exporter_traces_ostream:
type: ostream
filename: __full_traces
exporter_traces_memory:
type: memory
buffer_size: 256
exporter_traces_zipkin:
type: zipkin
endpoint: "http://localhost:9411/api/v2/spans"
format: json
service_name: "zipkin-service"
# ipv4: ""
# ipv6: ""
exporter_metrics_otlp_file:
type: otlp_file
thread_name: "OTLP/file metr"
file_pattern: "__full_metrics_log-%F-%N"
alias_pattern: "__metrics_log-latest"
flush_interval: 30000000
flush_count: 256
file_size: 134217728
rotate_size: 5
exporter_metrics_otlp_grpc:
type: otlp_grpc
thread_name: "OTLP/gRPC metr"
endpoint: "http://localhost:4317/v1/metrics"
use_ssl_credentials: false
exporter_metrics_otlp_http:
type: otlp_http
thread_name: "OTLP/HTTP metr"
endpoint: "http://localhost:4318/v1/metrics"
content_type: json
debug: false
timeout: 10
http_headers:
- X-OTel-Header-1: "OTLP HTTP metrics test header #1"
- X-OTel-Header-2: "OTLP HTTP metrics test header #2"
max_concurrent_requests: 64
max_requests_per_connection: 8
ssl_insecure_skip_verify: true
exporter_metrics_dev_null:
type: ostream
filename: /dev/null
exporter_metrics_ostream:
type: ostream
filename: __full_metrics
exporter_metrics_memory:
type: memory
buffer_size: 256
exporter_logs_otlp_file:
type: otlp_file
thread_name: "OTLP/file logs"
file_pattern: "__full_logs_log-%F-%N"
alias_pattern: "__logs_log-latest"
flush_interval: 30000000
flush_count: 256
file_size: 134217728
rotate_size: 5
exporter_logs_otlp_grpc:
type: otlp_grpc
thread_name: "OTLP/gRPC logs"
endpoint: "http://localhost:4317/v1/logs"
use_ssl_credentials: false
exporter_logs_otlp_http:
type: otlp_http
thread_name: "OTLP/HTTP logs"
endpoint: "http://localhost:4318/v1/logs"
content_type: json
debug: false
timeout: 10
http_headers:
- X-OTel-Header-1: "OTLP HTTP logs test header #1"
- X-OTel-Header-2: "OTLP HTTP logs test header #2"
max_concurrent_requests: 64
max_requests_per_connection: 8
ssl_insecure_skip_verify: true
exporter_logs_dev_null:
type: ostream
filename: /dev/null
exporter_logs_ostream:
type: ostream
filename: __full_logs
exporter_logs_elasticsearch:
type: elasticsearch
host: localhost
port: 9200
index: logs
response_timeout: 30
debug: false
http_headers:
- X-OTel-Header-1: "Elasticsearch logs test header #1"
- X-OTel-Header-2: "Elasticsearch logs test header #2"
readers:
reader_metrics:
thread_name: "reader metr"
export_interval: 10000
export_timeout: 5000
samplers:
sampler_traces:
# type: always_on
# type: always_off
# type: trace_id_ratio_based
# ratio: 1.0
type: parent_based
delegate: always_on
processors:
processor_traces_batch:
type: batch
thread_name: "proc/batch trac"
# Note: when the queue is half full, a preemptive notification is sent
# to start the export call.
max_queue_size: 2048
# Time interval (in ms) between two consecutive exports
schedule_delay: 5000
# Export 'max_export_batch_size' after every `schedule_delay' milliseconds.
max_export_batch_size: 512
processor_traces_single:
type: single
processor_logs_batch:
type: batch
thread_name: "proc/batch logs"
max_queue_size: 2048
schedule_delay: 5000
max_export_batch_size: 512
processor_logs_single:
type: single
providers:
provider_traces:
resources:
- service.version: "1.0.0"
- service.instance.id: "id-full"
- service.name: "full"
- service.namespace: "HAProxy traces test"
provider_metrics:
resources:
- service.version: "1.0.0"
- service.instance.id: "id-full"
- service.name: "full"
- service.namespace: "HAProxy metrics test"
provider_logs:
resources:
- service.version: "1.0.0"
- service.instance.id: "id-full"
- service.name: "full"
- service.namespace: "HAProxy logs test"
signals:
traces:
scope_name: "HAProxy OTEL - traces"
exporters: exporter_traces_otlp_http
samplers: sampler_traces
processors: processor_traces_batch
providers: provider_traces
metrics:
scope_name: "HAProxy OTEL - metrics"
exporters: exporter_metrics_otlp_http
readers: reader_metrics
providers: provider_metrics
logs:
scope_name: "HAProxy OTEL - logs"
exporters: exporter_logs_otlp_http
processors: processor_logs_batch
providers: provider_logs

16
addons/otel/test/run-full.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh -u
#
# Copyright 2026 HAProxy Technologies, Miroslav Zagorac <mzagorac@haproxy.com>
#
SH_ARG_HAPROXY="${1:-$(realpath -L ${PWD}/../../../haproxy)}"
SH_ARG_PIDFILE="${2:-haproxy.pid}"
SH_ARGS="-f haproxy-common.cfg -f full/haproxy.cfg -p "${SH_ARG_PIDFILE}""
SH_LOG_DIR="_logs"
SH_LOG="${SH_LOG_DIR}/_log-$(basename "${0}" .sh)-$(date +%s)"
test -x "${SH_ARG_HAPROXY}" || exit 1
mkdir -p "${SH_LOG_DIR}" || exit 2
echo "executing: ${SH_ARG_HAPROXY} ${SH_ARGS}" >${SH_LOG}
"${SH_ARG_HAPROXY}" ${SH_ARGS} >>"${SH_LOG}" 2>&1