mirror of
https://github.com/haproxy/haproxy.git
synced 2026-06-26 17:59:31 -04:00
Compare commits
No commits in common. "master" and "v3.4-dev13" have entirely different histories.
master
...
v3.4-dev13
252 changed files with 15731 additions and 5503 deletions
18
.cirrus.yml
Normal file
18
.cirrus.yml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
FreeBSD_task:
|
||||||
|
freebsd_instance:
|
||||||
|
matrix:
|
||||||
|
image_family: freebsd-14-3
|
||||||
|
only_if: $CIRRUS_BRANCH =~ 'master|next'
|
||||||
|
install_script:
|
||||||
|
- pkg update -f && pkg upgrade -y && pkg install -y openssl git gmake lua54 socat pcre2
|
||||||
|
script:
|
||||||
|
- sudo sysctl kern.corefile=/tmp/%N.%P.core
|
||||||
|
- sudo sysctl kern.sugid_coredump=1
|
||||||
|
- scripts/build-vtest.sh
|
||||||
|
- gmake CC=clang V=1 ERR=1 TARGET=freebsd USE_ZLIB=1 USE_PCRE2=1 USE_PCRE2_JIT=1 USE_OPENSSL=1 USE_LUA=1 LUA_INC=/usr/local/include/lua54 LUA_LIB=/usr/local/lib LUA_LIB_NAME=lua-5.4
|
||||||
|
- ./haproxy -vv
|
||||||
|
- ldd haproxy
|
||||||
|
test_script:
|
||||||
|
- env VTEST_PROGRAM=../vtest/vtest gmake reg-tests REGTESTS_TYPES=default,bug,devel
|
||||||
|
on_failure:
|
||||||
|
debug_script: (for folder in /tmp/*regtest*/vtc.*; do cat $folder/INFO $folder/LOG; done && ls /tmp/haproxy.*.core && gdb -ex 'thread apply all bt full' ./haproxy /tmp/haproxy.*.core)
|
||||||
2
.github/matrix.py
vendored
2
.github/matrix.py
vendored
|
|
@ -172,6 +172,7 @@ def main(ref_name):
|
||||||
"FLAGS": [
|
"FLAGS": [
|
||||||
'DEBUG="-DDEBUG_LIST"',
|
'DEBUG="-DDEBUG_LIST"',
|
||||||
"USE_ZLIB=1",
|
"USE_ZLIB=1",
|
||||||
|
"USE_OT=1",
|
||||||
"OT_INC=${HOME}/opt-ot/include",
|
"OT_INC=${HOME}/opt-ot/include",
|
||||||
"OT_LIB=${HOME}/opt-ot/lib",
|
"OT_LIB=${HOME}/opt-ot/lib",
|
||||||
"OT_RUNPATH=1",
|
"OT_RUNPATH=1",
|
||||||
|
|
@ -205,6 +206,7 @@ def main(ref_name):
|
||||||
'ARCH_FLAGS="-g -fsanitize=address"',
|
'ARCH_FLAGS="-g -fsanitize=address"',
|
||||||
'OPT_CFLAGS="-O1"',
|
'OPT_CFLAGS="-O1"',
|
||||||
"USE_ZLIB=1",
|
"USE_ZLIB=1",
|
||||||
|
"USE_OT=1",
|
||||||
"DEBUG=-DDEBUG_STRICT=2",
|
"DEBUG=-DDEBUG_STRICT=2",
|
||||||
"OT_INC=${HOME}/opt-ot/include",
|
"OT_INC=${HOME}/opt-ot/include",
|
||||||
"OT_LIB=${HOME}/opt-ot/lib",
|
"OT_LIB=${HOME}/opt-ot/lib",
|
||||||
|
|
|
||||||
38
.github/workflows/freebsd.yml
vendored
38
.github/workflows/freebsd.yml
vendored
|
|
@ -1,38 +0,0 @@
|
||||||
name: FreeBSD
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- next
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
clang:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
|
||||||
steps:
|
|
||||||
- name: "Checkout repository"
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: "Build and test on FreeBSD"
|
|
||||||
uses: vmactions/freebsd-vm@v1
|
|
||||||
with:
|
|
||||||
release: "14.3"
|
|
||||||
prepare: |
|
|
||||||
pkg update -f && pkg upgrade -y && pkg install -y openssl git gmake lua54 socat pcre2 python3
|
|
||||||
run: |
|
|
||||||
sysctl kern.corefile=/tmp/%N.%P.core
|
|
||||||
sysctl kern.sugid_coredump=1
|
|
||||||
scripts/build-vtest.sh
|
|
||||||
gmake CC=clang V=1 ERR=1 TARGET=freebsd USE_ZLIB=1 USE_PCRE2=1 USE_PCRE2_JIT=1 USE_OPENSSL=1 USE_LUA=1 LUA_INC=/usr/local/include/lua54 LUA_LIB=/usr/local/lib LUA_LIB_NAME=lua-5.4
|
|
||||||
./haproxy -vv
|
|
||||||
ldd haproxy
|
|
||||||
if ! env VTEST_PROGRAM=../vtest/vtest gmake reg-tests REGTESTS_TYPES=default,bug,devel; then
|
|
||||||
for folder in /tmp/*regtest*/vtc.*; do cat $folder/INFO $folder/LOG; done
|
|
||||||
ls /tmp/haproxy.*.core 2>/dev/null && gdb -ex 'thread apply all bt full' ./haproxy /tmp/haproxy.*.core
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
2
.github/workflows/illumos.yml
vendored
2
.github/workflows/illumos.yml
vendored
|
|
@ -2,7 +2,7 @@ name: Illumos
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 3 * * 1"
|
- cron: "0 0 25 * *"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
|
|
||||||
11
.github/workflows/vtest.yml
vendored
11
.github/workflows/vtest.yml
vendored
|
|
@ -65,6 +65,13 @@ jobs:
|
||||||
path: '~/opt/'
|
path: '~/opt/'
|
||||||
key: ssl-${{ steps.generate-cache-key.outputs.key }}
|
key: ssl-${{ steps.generate-cache-key.outputs.key }}
|
||||||
|
|
||||||
|
- name: Cache OpenTracing
|
||||||
|
if: ${{ contains(matrix.FLAGS, 'USE_OT=1') }}
|
||||||
|
id: cache_ot
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: '~/opt-ot/'
|
||||||
|
key: ${{ matrix.os }}-ot-${{ matrix.CC }}-${{ env.OT_CPP_VERSION }}-${{ contains(matrix.name, 'ASAN') }}
|
||||||
- name: Add i386 architecture
|
- name: Add i386 architecture
|
||||||
if: ${{ matrix.CC == 'i686-linux-gnu-gcc' }}
|
if: ${{ matrix.CC == 'i686-linux-gnu-gcc' }}
|
||||||
run: sudo dpkg --add-architecture i386
|
run: sudo dpkg --add-architecture i386
|
||||||
|
|
@ -92,6 +99,10 @@ jobs:
|
||||||
- name: Install SSL ${{ matrix.ssl }}
|
- name: Install SSL ${{ matrix.ssl }}
|
||||||
if: ${{ matrix.ssl && matrix.ssl != 'stock' && steps.cache_ssl.outputs.cache-hit != 'true' }}
|
if: ${{ matrix.ssl && matrix.ssl != 'stock' && steps.cache_ssl.outputs.cache-hit != 'true' }}
|
||||||
run: env ${{ matrix.ssl }} scripts/build-ssl.sh
|
run: env ${{ matrix.ssl }} scripts/build-ssl.sh
|
||||||
|
- name: Install OpenTracing libs
|
||||||
|
if: ${{ contains(matrix.FLAGS, 'USE_OT=1') && steps.cache_ot.outputs.cache-hit != 'true' }}
|
||||||
|
run: |
|
||||||
|
OT_PREFIX=${HOME}/opt-ot scripts/build-ot.sh
|
||||||
- name: Build WURFL
|
- name: Build WURFL
|
||||||
if: ${{ contains(matrix.FLAGS, 'USE_WURFL=1') }}
|
if: ${{ contains(matrix.FLAGS, 'USE_WURFL=1') }}
|
||||||
run: make -C addons/wurfl/dummy
|
run: make -C addons/wurfl/dummy
|
||||||
|
|
|
||||||
278
CHANGELOG
278
CHANGELOG
|
|
@ -1,284 +1,6 @@
|
||||||
ChangeLog :
|
ChangeLog :
|
||||||
===========
|
===========
|
||||||
|
|
||||||
2026/06/25 : 3.5-dev1
|
|
||||||
- BUG/MEDIUM: check: Skip tcpcheck post-config for external checks
|
|
||||||
- BUG/MEDIUM: check: Ignore small-buffer option when starting an external check
|
|
||||||
- MINOR: check: Don't dump buffers state in check traces for external checks
|
|
||||||
- BUG/MEDIUM: server/checks: Support healtcheck keyword on default-server lines
|
|
||||||
- BUG/MEDIUM: mux_quic: prevent risk of infinite loop on recv
|
|
||||||
- OPTIM: mux_quic: remove QCS from recv_list on reset
|
|
||||||
- BUG/MINOR: mux_quic: do not interrupt recv on error/incomplete data
|
|
||||||
- BUG/MINOR: tcpcheck: Override external check if healthcheck section is set
|
|
||||||
- REGTESTS: checks: Add script for external healthchecks
|
|
||||||
- BUG/MEDIUM: regex: initialize the match array earlier during boot
|
|
||||||
- BUG/MEDIUM: threads: Fiw build when using no thread
|
|
||||||
- BUG/MEDIUM: xprt_qmux: implement ->get_ssl_sock_ctx() to get the SSL laye
|
|
||||||
- CLEANUP: sessions: simplify the sess_priv_conns pool name
|
|
||||||
- MINOR: pools: reject creation of pools containing invalid chars in their name
|
|
||||||
- BUG/MINOR: acl: report "ACL" not "map" in ACL ID lookup failures
|
|
||||||
- MINOR: memprof: make in_memprof a bitfield instead of a counter
|
|
||||||
- MINOR: memprof: be careful to account allocations only once
|
|
||||||
- BUG/MEDIUM: checks: Dequeue checks on purge
|
|
||||||
- MINOR: servers: Add a back-pointer to the server in srv_per_thread
|
|
||||||
- MEDIUM: servers: Move to a per-thread idle connection cleanup task
|
|
||||||
- REGTESTS: Fix log matching in healthcheck-section.vtc
|
|
||||||
- BUG/MINOR: quic: fix Initial length value in sent packets
|
|
||||||
- BUILD: servers: Fix build with -std=gnu89
|
|
||||||
- BUG/MEDIUM: acme: stuck ACME task when authz is already "valid"
|
|
||||||
- MINOR: acme: introduce acme_challenge_ready() for reuse outside the CLI
|
|
||||||
- MINOR: h3: extend trace verbosity
|
|
||||||
- MINOR: h3: trace HTTP headers on FE side
|
|
||||||
- MINOR: h3: trace HTTP headers on BE side
|
|
||||||
- BUILD: h3: fix compilation with USE_TRACE=0
|
|
||||||
- MINOR: lua: add REGISTER_HLUA_STATE_INIT() to register state init callbacks
|
|
||||||
- MEDIUM: lua: move longjmp annotation macros to hlua.h
|
|
||||||
- MINOR: acme/lua: implement ACME.challenge_ready() Lua function
|
|
||||||
- BUG/MEDIUM: ktls: defer enabling TLS ULP on a socket until connected
|
|
||||||
- MINOR: errors: add ha_diag_notice() to report diag-level notifications
|
|
||||||
- BUG/MINOR: cpu-topo: use ha_diag_notice() to report thread creations
|
|
||||||
- MINOR: acme: publish ACME_NEWCERT event via event_hdl
|
|
||||||
- MINOR: acme: publish ACME_DEPLOY event via event_hdl
|
|
||||||
- EXAMPLES: lua/acme: add a dns-01 handler for Gandi LiveDNS API
|
|
||||||
- DOC: acme: add mentions of lua features
|
|
||||||
- MINOR: tasks: Introduce __task_set_state_and_tid
|
|
||||||
- MINOR: tasks: Add __task_get_new_tid_field()
|
|
||||||
- MINOR: tasks: Introduce __task_get_current_owner
|
|
||||||
- MINOR: tasks: Use __task_get_current_owner() in task_kill.
|
|
||||||
- MINOR: tasks: Start using __task_set_state_and_tid()
|
|
||||||
- MEDIUM: tasks: Remove the per-thread group wait queue
|
|
||||||
- MINOR: tasks: Use __task_set_state_and_tid() in task_instant_wakeup()
|
|
||||||
- MINOR: tasks: Remove wq_lock and the per-thread group wait queues
|
|
||||||
- MEDIUM: tasks: Redispatch shared tasks when the thread is loaded
|
|
||||||
- BUG/MEDIUM: h3: Properly handle PUSH_PROMISE on backend connections
|
|
||||||
- BUG/MINOR: server: fix add server with consistent hash balancing
|
|
||||||
- MINOR: lua: export hlua_pusherror() and check_args()
|
|
||||||
- REORG: httpclient/lua: move the lua httpclient code to http_client.c
|
|
||||||
- MEDIUM: httpclient/lua: allow multiple requests from a single core.httpclient() instance
|
|
||||||
- MEDIUM: httpclient: set res.status to 0 upon SF_ERR_MASK
|
|
||||||
- DOC: httpclient: document status 0 on internal error
|
|
||||||
- DEBUG: stconn: Add a BUG_ON on shut flags when the endpoint is shut
|
|
||||||
- BUG/MINOR: http-ana: Remove a debugging memset on redirect
|
|
||||||
- BUG/MEDIUM: http-ana: Don't ignore L7 retry errors
|
|
||||||
- BUG/MINOR: mux-h1: Properly resolve file path for 'h1-case-adjust-file'
|
|
||||||
- BUG/MINOR: quic: fix rxbuf settings on backend side
|
|
||||||
- EXAMPLES: lua/acme: fix acme-gandi-livedns.lua configuration example
|
|
||||||
- BUG/MEDIUM: ssl: Don't free the early data buffer too early
|
|
||||||
- BUG/MINOR: hpack-tbl: add missing NULL check after hpack_dht_defrag()
|
|
||||||
- BUG/MEDIUM: mux_quic: fix freeze transfer after QCS rxbuf realign
|
|
||||||
- BUG/MEDIUM: http-act: Make a copy of the sample expr in (set/add)-headers-bin
|
|
||||||
- BUG/MEDIUM: mux-fcgi: fix uint16_t overflow in drl += drp
|
|
||||||
- OPTIM: mux-fcgi: Reorganise fcgi_conn structure to fill some holes
|
|
||||||
- BUG/MINOR: hq-interop: reject too big content
|
|
||||||
- MINOR: hq_interop: do not rely on stream layer for HTX stline encoding
|
|
||||||
- BUG/MINOR: hq-interop: prevent reset if missing content-length
|
|
||||||
- BUG/MEDIUM: hlua: Properly report EOS when http applet exits
|
|
||||||
- BUG/MINOR: hq-interop: support full demux buf on large response
|
|
||||||
- BUG/MINOR: hq-interop: support response buffer wrapping
|
|
||||||
- DOC: sched: Document the wait queue modifications
|
|
||||||
- DOC: lua: remove incorrect init tags
|
|
||||||
- BUG/MEDIUM: h3: increment unknown request payload length
|
|
||||||
- REGTESTS: quic: test H3 request without content-length
|
|
||||||
- DEBUG: cli: relax tid check in "debug dev task" for recent sched changes
|
|
||||||
- MINOR: debug: add "print" to "debug dev sched"
|
|
||||||
- BUG/MINOR: poller: fix wait time calculation that is always 1 extra ms
|
|
||||||
- BUILD: quic_pacing: add missing includes for api and activity in the file
|
|
||||||
- MINOR: task: move the profiling checks to the called functions not callers
|
|
||||||
- MINOR: task: add a new explicitly local tasklet wakeup function
|
|
||||||
- MINOR: task: make tasklet_wakeup() explicitly call _tasklet_wakeup_here()
|
|
||||||
- MINOR: task: make task_instant_wakeup() explicitly call _tasklet_wakeup_here()
|
|
||||||
- MEDIUM: task: make __tasklet_wakeup_on() only accept non-local threads
|
|
||||||
- MEDIUM: task: add a new flag TASK_RT to permit a task to skip the priority queue
|
|
||||||
- MINOR: debug: add "rt=1" to "debug dev task" to tune the RT flag
|
|
||||||
- BUG/MEDIUM: mux-fcgi: Truly drain outgoing HTX data when the stream is closed
|
|
||||||
- BUG/MEDIUM: mux-h2: Truly drain outgoing HTX data when the stream is closed
|
|
||||||
- BUG/MEDIUM: mux-spop: Truly drain outgoing data when the stream is closed
|
|
||||||
- BUG/MEDIUM: mux-quic: Drain the given amount of data in qcs_http_reset_buf()
|
|
||||||
- CLEANUP: task: remove duplicated code in __tasklet_wakeup_after()
|
|
||||||
- BUILD: task: silence a build warning with threads disabled
|
|
||||||
- MINOR: task: do not try to redistribute the WQ when single-threaded
|
|
||||||
- MEDIUM: task: add a new tasklet class for real-time: TL_RT
|
|
||||||
|
|
||||||
2026/06/03 : 3.5-dev0
|
|
||||||
- MINOR: version: mention that it's development again
|
|
||||||
|
|
||||||
2026/06/03 : 3.4.0
|
|
||||||
- BUG/MINOR: tcpcheck: Check LDAP response to not read more data than available
|
|
||||||
- BUG/MINOR: ssl-gencert: validate SNI characters to prevent SAN certificate injection
|
|
||||||
- BUG/MINOR: mux-h1: H2 preface rejection doesn't update stick-table glitches
|
|
||||||
- BUG/MEDIUM: cpu-topo: Enforce thread-hard-limit on policy
|
|
||||||
- BUG/MEDIUM: qmux: do not crash on too large record
|
|
||||||
- BUG/MEDIUM: qmux: do not crash on receiving an invalid first frame
|
|
||||||
- BUG/MINOR: qmux: reject too large initial record
|
|
||||||
- Revert "BUG/MEDIUM: dns: fix long loops in additional records parse on name failure"
|
|
||||||
- BUG/MINOR: qpack: Fix index calculation in debug functions
|
|
||||||
- BUG/MINOR: qpack: fix potential null-pointer dereference in qpack_dht_insert()
|
|
||||||
- CLEANUP: qpack: fix copy-paste typo in value Huffman debug string
|
|
||||||
- BUG/MINOR: qpack: fix sign bit mask in qpack_decode_fs_pfx()
|
|
||||||
- CLEANUP: qpack: fix copy-paste typo in value Huffman debug string for WLN
|
|
||||||
- BUG/MINOR: qpack: fix huff_dec() error handling in qpack_decode_fs()
|
|
||||||
- CLEANUP: qpack: move encoded macros to qpack-t.h to avoid duplication
|
|
||||||
- BUG/MEDIUM: quic: handle ECONNREFUSED on RX side
|
|
||||||
- BUG/MINOR: quic: Fix memory leak in quic_deallocate_dghdlrs()
|
|
||||||
- BUG/MEDIUM: lua: defer Lua VM initialisation to the first Lua config keyword
|
|
||||||
- REGTESTS: lua: fix tune.lua.openlibs in Lua reg-tests
|
|
||||||
- BUG/MINOR: mux-h2: Count padding for connection flow control on error path
|
|
||||||
- BUILD: addons: convert 51d addon to EXTRA_MAKE
|
|
||||||
- BUILD: addons: convert deviceatlas addon to EXTRA_MAKE
|
|
||||||
- BUILD: addons: convert WURFL addon to EXTRA_MAKE
|
|
||||||
- MINOR: mux_quic/flags: add missing flags
|
|
||||||
- BUG/MINOR: mux_quic: open an idle QCS on reset on BE side
|
|
||||||
- BUG/MINOR: mux_quic: fix BE conn removal on app shutdown
|
|
||||||
- BUG/MINOR: mux_quic: prevent BE reuse with an errored conn
|
|
||||||
- BUG/MINOR: quic: fix ack range node pool_free call passing wrong pointer type
|
|
||||||
- MEDIUM: quic: optimize HKDF operations by reusing per-thread contexts
|
|
||||||
- BUG/MEDIUM: quic: reset cwnd in slow_start on persistent congestion (cubic)
|
|
||||||
- BUG/MEDIUM: quic: reset consecutive_losses on exit from recovery period (cubic)
|
|
||||||
- BUG/MINOR: quic: update drs->lost before calling on_ack_recv
|
|
||||||
- Revert "MEDIUM: quic: optimize HKDF operations by reusing per-thread contexts"
|
|
||||||
- BUG/MEDIUM: lua: register hlua_init() as a pre-check to fix crash without Lua config
|
|
||||||
- REGTESTS: quic: disable quic/ocsp_auto_update for now
|
|
||||||
- BUG/MINOR: threads: set at least grp_max when mtpg is too small
|
|
||||||
- BUG/MEDIUM: threads: ignore max-threads-per-group when thread-groups is set
|
|
||||||
- CLEANUP: thread: indicate when max-threads-per-group is ignored
|
|
||||||
- MINOR: cpu-topo: notify when cpu-policy is ignored due to other settings
|
|
||||||
- MINOR: thread: report when thread-groups or nbthread results in less threads
|
|
||||||
- BUILD: makefile: include EXTRA_MAKE in the .build_opts construction
|
|
||||||
- BUG/MINOR: quic: Fix another buffer overflow with sockaddr_in46
|
|
||||||
- MINOR: quic: Copy sin6_flowinfo and sin6_scope_id too
|
|
||||||
- BUILD: Makefile: put EXTRA_MAKE help at the right place
|
|
||||||
- BUG/MINOR: cache: fix cache tree iteration
|
|
||||||
- BUG/MEDIUM: resolvers: Wait a bit before calling the xprt prepare_srv
|
|
||||||
- CLEANUP: addons/51degrees: initialize variables
|
|
||||||
- MINOR: addons/51degrees: handle memory allocation failures
|
|
||||||
- CLEANUP: ncbmbuf: improve handling of memory allocation errors in unit tests
|
|
||||||
- CLEANUP: admin/halog: improve handling of memory allocation errors
|
|
||||||
- DOC: internals: clarify ambiguous wording in core-principles
|
|
||||||
- DOC: internals: add a threat model definition
|
|
||||||
- DOC: add security.txt describing how to report security issues
|
|
||||||
- DOC: security: also add a note to exclude dev/ and admin/
|
|
||||||
- BUG/MEDIUM: qmux: Close connection on invalid frame
|
|
||||||
- CLEANUP: fix comment typo
|
|
||||||
- BUG/MEDIUM: h3: fix MAX_PUSH_ID handling
|
|
||||||
- BUG/MINOR: cache: Fix copy of value when parsing maxage
|
|
||||||
- BUG/MEDIUM: mux-h1: Dup connection/upgrade value to parse it when making headers
|
|
||||||
- BUG/MEDIUM: htx: Fix headers rollback on partial copy in htx_xfer()
|
|
||||||
- MINOR: deinit: release the in-memory copy of shared libs
|
|
||||||
- MINOR: debug: add -dA to dump an archive of all dependencies
|
|
||||||
- BUG/MEDIUM: ssl: Make sure the alpn length is small enough
|
|
||||||
- BUG/MINOR: applet: Commit changes into input buffer after sending HTX data
|
|
||||||
- BUG/MINOR: mux-spop: Fix possible off-by-one OOB read in spop_get_varint()
|
|
||||||
- BUG/MEDIUM: leastconn: Unlock the write lock on allocation failure
|
|
||||||
- BUG/MINOR: tasks: Increase the right niced_task counter
|
|
||||||
- BUILD: makefile: search for Lua 5.5 as well
|
|
||||||
- DEV: dev/gdb: improve ebtree pointer handling
|
|
||||||
- DEV: dev/gdb: add simple task dump
|
|
||||||
- DEV: dev/gdb: add simple thread dump
|
|
||||||
- DEV: dev/gdb: add fdtab dump
|
|
||||||
- DOC: config: add a few more explanation in http-reusee regarding sni-auto
|
|
||||||
- REGTESTS: add basic QMux tests
|
|
||||||
- BUG/MINOR: http-act: Properly handle final evaluation in pause action
|
|
||||||
- BUILD: makefile/lua: use the system's default library before all other variants
|
|
||||||
- BUG/MINOR: startup: unbreak chroot with CAP_SYS_CHROOT
|
|
||||||
- BUG/MINOR: haterm: do not try to bind QUIC when not supported
|
|
||||||
- BUG/MINOR: haterm: also apply the tcp-bind-opts to clear TCP "bind" lines
|
|
||||||
- CLEANUP: haterm: do not try to bind to SSL when not built in
|
|
||||||
- MINOR: haterm: enable ktls on the SSL bind line when supported
|
|
||||||
- CI: github: replace cirrus by a vmactions/freebsd-vm job
|
|
||||||
- BUILD: makefile: fix build error with GNU make 4.2.1 and /bin/dash
|
|
||||||
- BUG/MEDIUM: channel: Fix condition to know if a channel may send
|
|
||||||
- BUG/MEDIUM: vars: Properly eval set-var-fmt action for emtpy log-format string
|
|
||||||
- CI: github: run illumos job weekly on Mondays at 03:00 instead of monthly
|
|
||||||
- BUG/MEDIUM: stream: Don't use small buffer on queuing with a request data filter
|
|
||||||
- BUG/MINOR: jwe: don't write randoms past MAX_DECRYPTED_CEK_LEN in RSA_PKCS1_PADDING
|
|
||||||
- BUG/MEDIUM: chunk: do not rely on small trash by default for expressions
|
|
||||||
- CLEANUP: map: always test pat->ref in sample_conv_map_key()
|
|
||||||
- DEV: patchbot: prepare for new version 3.5-dev
|
|
||||||
- MINOR: version: mention that it's 3.4 LTS now.
|
|
||||||
|
|
||||||
2026/05/26 : 3.4-dev14
|
|
||||||
- MINOR: config: shm-stats-file is no longer experimental
|
|
||||||
- BUILD: proxy: unstatify the proxies_del_lock to avoid a warning without threads
|
|
||||||
- BUG/MEDIUM: net_helper: fix a remaining possibly infinite loop in converters
|
|
||||||
- MINOR: ssl_sock: remove unneeded check on QMux flags
|
|
||||||
- MINOR: connection: define xprt_add_l6hs()
|
|
||||||
- MINOR: xprt_qmux: define default value for get_alpn
|
|
||||||
- MINOR: connection: define mask CO_FL_WAIT_XPRT_L6
|
|
||||||
- MINOR: session: support QMux in clear on FE side
|
|
||||||
- MINOR: backend: support QMux in clear for BE side
|
|
||||||
- BUG/MINOR: ocsp: Manage date too far away in the future
|
|
||||||
- MINOR: mux_quic: handle STOP_SENDING in QMux
|
|
||||||
- MINOR: mux_quic: handle MAX_STREAMS for uni stream in QMux
|
|
||||||
- MINOR: mux_quic: do not crash on unhandled QMux frame reception
|
|
||||||
- BUG/MEDIUM: applet: Properly handle receives of size 0
|
|
||||||
- BUG/MEDIUM: resolvers: Fix test on dn label size in resolv_dn_label_to_str()
|
|
||||||
- BUG/MEDIUM: ssl-gencert: Unlock LRU cache if failing to generate certificate
|
|
||||||
- BUG/MINOR: quic: fix ODCID lookup from derived value
|
|
||||||
- BUG/MEDIUM: dict: hold lock while decrementing refcount in dict_entry_unref
|
|
||||||
- BUG/MINOR: tcpchecks: Limit parsing of agent-check reply to the buffer
|
|
||||||
- BUG/MEDIUM: hlua: Fix integer underflow when receiving line from lua cosocket
|
|
||||||
- BUG/MEDIUM: cli: Fix parsing of pattern finishing a command payload
|
|
||||||
- BUG/MEDIUM: acme: NUL terminate response buffer before PEM parsing
|
|
||||||
- BUILD: intops: mask the fail value in array_size_or_fail()
|
|
||||||
- BUG/MEDIUM: log-forward: make sure the month is unsigned
|
|
||||||
- BUG/MEDIUM: regex: allocate a large enough pcre2 match for all matches
|
|
||||||
- BUG/MEDIUM: tcpcheck/spoe: bound the SPOP error code to valid values
|
|
||||||
- BUG/MEDIUM: cache: fix a refcount leak for missed secondary entries
|
|
||||||
- BUG/MINOR: log: free logformat expr on compile failure in cfg_parse_log_profile
|
|
||||||
- BUG/MINOR: resolvers: fix room for trailing zero in resolv_dn_label_to_str()
|
|
||||||
- BUG/MINOR: resolvers: fix risk of appending garbage past the domain name
|
|
||||||
- BUG/MINOR: mux-h2: validate HEADERS frame length before reading stream dep
|
|
||||||
- BUG/MINOR: log: look for the end of priority before the end of the buffer
|
|
||||||
- BUG/MINOR: dict: fix refcount race on insert collision
|
|
||||||
- BUG/MINOR: init: use more than ha_random64() for the cluster secret
|
|
||||||
- BUG/MINOR: sample: limit the be2hex converter's chunk size
|
|
||||||
- CLEANUP: resolvers: use read_n32() instead of open-coded big-endian read
|
|
||||||
- CLEANUP: resolvers: remove pool_free(NULL) in SRV additional record matching
|
|
||||||
- CLEANUP: resolvers: fix comment typos and wrong filenames in file headers
|
|
||||||
- BUG/MINOR: haterm: fix the random suffix multiplication
|
|
||||||
- MINOR: haterm: enable h3 for TCP bindings
|
|
||||||
- MINOR: haterm: do not emit a warning when not using SSL
|
|
||||||
- BUG/MEDIUM: h1: drop headers whose names contain invalid chars
|
|
||||||
- BUG/MEDIUM: h1: limit status codes to 3 digits by default
|
|
||||||
- BUG/MEDIUM: cache: always verify the primary hash in get_secondary_entry()
|
|
||||||
- BUG/MINOR: cache: also recognize directives in the form "token="
|
|
||||||
- BUG/MINOR: resolvers: relax size checks in authority record parsing
|
|
||||||
- BUG/MINOR: sample: request an extra output byte for the url_dec converter
|
|
||||||
- BUG/MINOR: http-fetch: check against the whole token in get_http_auth()
|
|
||||||
- BUG/MEDIUM: acme: protect against risk of null-deref on connection failure
|
|
||||||
- BUG/MINOR: http-ext: always check remaining data when reading rfc7239 nodeport
|
|
||||||
- BUG/MINOR: base64: return empty string for empty input in base64dec()
|
|
||||||
- BUG/MINOR: payload: fix the handshake length bounds check smp_client_hello_parse()
|
|
||||||
- BUG/MINOR: ssl-hello: make use of the null-terminated servername
|
|
||||||
- BUG/MINOR: resolvers: switch to a better PRNG for query IDs
|
|
||||||
- BUG/MINOR: addons/51d: NUL-terminate headers before passing them to Trie API
|
|
||||||
- BUG/MEDIUM: tools: insert an XXH64 layer on the PRNG output
|
|
||||||
- MINOR: tools: provide a function to generate a hashed random pair
|
|
||||||
- MEDIUM: init: fall back to ha_random64_pair_hashed() for the cluster secret
|
|
||||||
- MEDIUM: tools: use the hashed random pair for UUID generation
|
|
||||||
- MEDIUM: h1: use ha_random64_pair_hashed() for the WebSocket key
|
|
||||||
- MEDIUM: quic: use ha_random64_pair_hashed() to generate the QUIC retry tokens
|
|
||||||
- MEDIUM: tools: switch the main PRNG to a thread-local xoshiro256**
|
|
||||||
- BUG/MEDIUM: h3: reject client push stream
|
|
||||||
- BUG/MINOR: h3: reject server push stream
|
|
||||||
- BUG/MINOR: h3: reject client CANCEL_PUSH frame
|
|
||||||
- BUG/MINOR: h3: adjust error on PUSH_PROMISE frame reception
|
|
||||||
- BUG/MINOR: h3: reject server MAX_PUSH_ID frame
|
|
||||||
- BUG/MEDIUM: auth: fix unconfigured password NULL deref
|
|
||||||
- BUG/MINOR: h3: add missing break on rcv_buf()
|
|
||||||
- BUG/MINOR: hlua: prevent Lua from passing CR/LF/NUL in HTTP headers
|
|
||||||
- BUG/MINOR: qmux: do not crash on frame parsing issue
|
|
||||||
- BUG/MINOR: quic: reject packet too short for HP decryption
|
|
||||||
- BUG/MINOR: jwe: enforce GCM tag length to 128 bits
|
|
||||||
- BUG/MEDIUM: jwe: substitute random CEK on RSA1_5 decryption failure per RFC 7516 #11.5
|
|
||||||
- BUG/MEDIUM: mux-fcgi: reject stream ID 0 for application records
|
|
||||||
- MINOR: http: Add function to remove all occurrences of a value in a header
|
|
||||||
- MINOR: h1: Add a H1M flag to specify a non-empty 'Upgrade:' header was parsed
|
|
||||||
- BUG/MEDIUM: h1-htx: Sanitize parsing to properly handle upgrade requests
|
|
||||||
- BUG/MINOR: mux-fcgi: Use relative offset to compute contig data in demux buf
|
|
||||||
- BUG/MINOR: mux-spop: Use relative offset to compute contig data in demux buf
|
|
||||||
- CLEANUP: mux-fcgi/mux-spop: Remove copy/pasted comment about slow realign
|
|
||||||
|
|
||||||
2026/05/20 : 3.4-dev13
|
2026/05/20 : 3.4-dev13
|
||||||
- BUG/MINOR: backend: correct parameter value validation in get_server_ph_post()
|
- BUG/MINOR: backend: correct parameter value validation in get_server_ph_post()
|
||||||
- BUG/MINOR: config/dns: properly fail on duplicate nameserver name detection
|
- BUG/MINOR: config/dns: properly fail on duplicate nameserver name detection
|
||||||
|
|
|
||||||
8
INSTALL
8
INSTALL
|
|
@ -11,7 +11,7 @@ this task seriously and are doing a good job at backporting important fixes.
|
||||||
|
|
||||||
If for any reason you would prefer a different version than the one packaged
|
If for any reason you would prefer a different version than the one packaged
|
||||||
for your system, you want to be certain to have all the fixes or to get some
|
for your system, you want to be certain to have all the fixes or to get some
|
||||||
commercial support, other choices are available at https://www.haproxy.com/.
|
commercial support, other choices are available at http://www.haproxy.com/.
|
||||||
|
|
||||||
|
|
||||||
Areas covered in this document
|
Areas covered in this document
|
||||||
|
|
@ -426,9 +426,9 @@ Lua is an embedded programming language supported by HAProxy to provide more
|
||||||
advanced scripting capabilities. Only versions 5.3 and above are supported.
|
advanced scripting capabilities. Only versions 5.3 and above are supported.
|
||||||
In order to enable Lua support, please specify "USE_LUA=1" on the command line.
|
In order to enable Lua support, please specify "USE_LUA=1" on the command line.
|
||||||
Some systems provide this library under various names to avoid conflicts with
|
Some systems provide this library under various names to avoid conflicts with
|
||||||
previous versions. By default, HAProxy looks for "lua5.5", "lua55", "lua5.4",
|
previous versions. By default, HAProxy looks for "lua5.4", "lua54", "lua5.3",
|
||||||
"lua54", "lua5.3", "lua53", "lua". If your system uses a different naming, you
|
"lua53", "lua". If your system uses a different naming, you may need to set the
|
||||||
may need to set the library name in the "LUA_LIB_NAME" variable.
|
library name in the "LUA_LIB_NAME" variable.
|
||||||
|
|
||||||
If Lua is not provided on your system, it can be very simply built locally. It
|
If Lua is not provided on your system, it can be very simply built locally. It
|
||||||
can be downloaded from https://www.lua.org/, extracted and built, for example :
|
can be downloaded from https://www.lua.org/, extracted and built, for example :
|
||||||
|
|
|
||||||
88
Makefile
88
Makefile
|
|
@ -60,6 +60,8 @@
|
||||||
# USE_WURFL : enable WURFL detection library from Scientiamobile
|
# USE_WURFL : enable WURFL detection library from Scientiamobile
|
||||||
# USE_OBSOLETE_LINKER : use when the linker fails to emit __start_init/__stop_init
|
# USE_OBSOLETE_LINKER : use when the linker fails to emit __start_init/__stop_init
|
||||||
# USE_THREAD_DUMP : use the more advanced thread state dump system. Automatic.
|
# USE_THREAD_DUMP : use the more advanced thread state dump system. Automatic.
|
||||||
|
# USE_OT : enable the OpenTracing filter
|
||||||
|
# EXTRA_MAKE : space-separated list of external addons using a Makefile.inc
|
||||||
# USE_MEMORY_PROFILING : enable the memory profiler. Linux-glibc only.
|
# USE_MEMORY_PROFILING : enable the memory profiler. Linux-glibc only.
|
||||||
# USE_LIBATOMIC : force to link with/without libatomic. Automatic.
|
# USE_LIBATOMIC : force to link with/without libatomic. Automatic.
|
||||||
# USE_PTHREAD_EMULATION : replace pthread's rwlocks with ours
|
# USE_PTHREAD_EMULATION : replace pthread's rwlocks with ours
|
||||||
|
|
@ -93,7 +95,6 @@
|
||||||
# SILENT_DEFINE may be used to specify other defines which will not be
|
# SILENT_DEFINE may be used to specify other defines which will not be
|
||||||
# reported by "haproxy -vv".
|
# reported by "haproxy -vv".
|
||||||
# EXTRA is used to force building or not building some extra tools.
|
# EXTRA is used to force building or not building some extra tools.
|
||||||
# EXTRA_MAKE space-separated list of external addons using a Makefile.inc
|
|
||||||
# DESTDIR is not set by default and is used for installation only.
|
# DESTDIR is not set by default and is used for installation only.
|
||||||
# It might be useful to set DESTDIR if you want to install haproxy
|
# It might be useful to set DESTDIR if you want to install haproxy
|
||||||
# in a sandbox.
|
# in a sandbox.
|
||||||
|
|
@ -123,7 +124,12 @@
|
||||||
# LUA_LIB : force the lib path to lua
|
# LUA_LIB : force the lib path to lua
|
||||||
# LUA_INC : force the include path to lua
|
# LUA_INC : force the include path to lua
|
||||||
# LUA_LIB_NAME : force the lib name (or automatically evaluated, by order of
|
# LUA_LIB_NAME : force the lib name (or automatically evaluated, by order of
|
||||||
# priority: lua5.5, lua55, lua5.4, lua54, lua5.3, lua53, lua).
|
# priority : lua5.4, lua54, lua5.3, lua53, lua).
|
||||||
|
# OT_DEBUG : compile the OpenTracing filter in debug mode
|
||||||
|
# OT_INC : force the include path to libopentracing-c-wrapper
|
||||||
|
# OT_LIB : force the lib path to libopentracing-c-wrapper
|
||||||
|
# OT_RUNPATH : add RUNPATH for libopentracing-c-wrapper to haproxy executable
|
||||||
|
# OT_USE_VARS : allows the use of variables for the OpenTracing context
|
||||||
# IGNOREGIT : ignore GIT commit versions if set.
|
# IGNOREGIT : ignore GIT commit versions if set.
|
||||||
# VERSION : force haproxy version reporting.
|
# VERSION : force haproxy version reporting.
|
||||||
# SUBVERS : add a sub-version (eg: platform, model, ...).
|
# SUBVERS : add a sub-version (eg: platform, model, ...).
|
||||||
|
|
@ -343,7 +349,7 @@ use_opts = USE_EPOLL USE_KQUEUE USE_NETFILTER USE_POLL \
|
||||||
USE_CPU_AFFINITY USE_TFO USE_NS USE_DL USE_RT USE_LIBATOMIC \
|
USE_CPU_AFFINITY USE_TFO USE_NS USE_DL USE_RT USE_LIBATOMIC \
|
||||||
USE_MATH USE_DEVICEATLAS USE_51DEGREES \
|
USE_MATH USE_DEVICEATLAS USE_51DEGREES \
|
||||||
USE_WURFL USE_OBSOLETE_LINKER USE_PRCTL USE_PROCCTL \
|
USE_WURFL USE_OBSOLETE_LINKER USE_PRCTL USE_PROCCTL \
|
||||||
USE_THREAD_DUMP USE_EVPORTS USE_QUIC USE_PROMEX \
|
USE_THREAD_DUMP USE_EVPORTS USE_OT USE_QUIC USE_PROMEX \
|
||||||
USE_MEMORY_PROFILING USE_SHM_OPEN \
|
USE_MEMORY_PROFILING USE_SHM_OPEN \
|
||||||
USE_STATIC_PCRE USE_STATIC_PCRE2 \
|
USE_STATIC_PCRE USE_STATIC_PCRE2 \
|
||||||
USE_PCRE USE_PCRE_JIT USE_PCRE2 USE_PCRE2_JIT \
|
USE_PCRE USE_PCRE_JIT USE_PCRE2 USE_PCRE2_JIT \
|
||||||
|
|
@ -678,15 +684,15 @@ OPTIONS_OBJS += src/quic_openssl_compat.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(USE_LUA:0=),)
|
ifneq ($(USE_LUA:0=),)
|
||||||
check_lua_inc = $(shell if [ ! -e /usr/include/lua.h -a -e $(2)$(1)/lua.h ]; then echo $(2)$(1); fi;)
|
check_lua_inc = $(shell if [ -d $(2)$(1) ]; then echo $(2)$(1); fi;)
|
||||||
LUA_INC := $(firstword $(foreach lib,lua5.5 lua55 lua5.4 lua54 lua5.3 lua53 lua,$(call check_lua_inc,$(lib),"/usr/include/")))
|
LUA_INC := $(firstword $(foreach lib,lua5.4 lua54 lua5.3 lua53 lua,$(call check_lua_inc,$(lib),"/usr/include/")))
|
||||||
|
|
||||||
check_lua_lib = $(shell echo "int main(){}" | $(CC) $(if $(LUA_INC),-I$(LUA_INC)) -o /dev/null -x c - $(2) -l$(1) 2>/dev/null && echo $(1))
|
check_lua_lib = $(shell echo "int main(){}" | $(CC) -o /dev/null -x c - $(2) -l$(1) 2>/dev/null && echo $(1))
|
||||||
LUA_LD_FLAGS := -Wl,$(if $(EXPORT_SYMBOL),$(EXPORT_SYMBOL),--export-dynamic) $(if $(LUA_LIB),-L$(LUA_LIB))
|
LUA_LD_FLAGS := -Wl,$(if $(EXPORT_SYMBOL),$(EXPORT_SYMBOL),--export-dynamic) $(if $(LUA_LIB),-L$(LUA_LIB))
|
||||||
|
|
||||||
# Try to automatically detect the Lua library if not set
|
# Try to automatically detect the Lua library if not set
|
||||||
ifeq ($(LUA_LIB_NAME),)
|
ifeq ($(LUA_LIB_NAME),)
|
||||||
LUA_LIB_NAME := $(firstword $(foreach lib,lua lua5.5 lua55 lua5.4 lua54 lua5.3 lua53,$(call check_lua_lib,$(lib),$(LUA_LD_FLAGS))))
|
LUA_LIB_NAME := $(firstword $(foreach lib,lua5.4 lua54 lua5.3 lua53 lua,$(call check_lua_lib,$(lib),$(LUA_LD_FLAGS))))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Lua lib name must be set now (forced/detected above)
|
# Lua lib name must be set now (forced/detected above)
|
||||||
|
|
@ -716,15 +722,70 @@ ifneq ($(USE_PROMEX:0=),)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(USE_DEVICEATLAS:0=),)
|
ifneq ($(USE_DEVICEATLAS:0=),)
|
||||||
EXTRA_MAKE += addons/deviceatlas
|
# Use DEVICEATLAS_SRC and possibly DEVICEATLAS_INC and DEVICEATLAS_LIB to force path
|
||||||
|
# to DeviceAtlas headers and libraries if needed. In this context, DEVICEATLAS_NOCACHE
|
||||||
|
# can be used to disable the cache support if needed (this also removes the necessity of having
|
||||||
|
# a C++ toolchain installed).
|
||||||
|
DEVICEATLAS_INC = $(DEVICEATLAS_SRC)
|
||||||
|
DEVICEATLAS_LIB = $(DEVICEATLAS_SRC)
|
||||||
|
include addons/deviceatlas/Makefile.inc
|
||||||
|
OPTIONS_OBJS += addons/deviceatlas/da.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Use 51DEGREES_SRC and possibly 51DEGREES_INC and 51DEGREES_LIB to force path
|
||||||
|
# to 51degrees v3/v4 headers and libraries if needed. Note that the SRC/INC/
|
||||||
|
# LIB/CFLAGS/LDFLAGS variables names all use 51DEGREES as the prefix,
|
||||||
|
# regardless of the version since they are mutually exclusive. The version
|
||||||
|
# (51DEGREES_VER) must be either 3 or 4, and defaults to 3 if not set.
|
||||||
|
51DEGREES_INC = $(51DEGREES_SRC)
|
||||||
|
51DEGREES_LIB = $(51DEGREES_SRC)
|
||||||
|
51DEGREES_VER = 3
|
||||||
|
|
||||||
ifneq ($(USE_51DEGREES:0=),)
|
ifneq ($(USE_51DEGREES:0=),)
|
||||||
EXTRA_MAKE += addons/51degrees
|
ifeq ($(51DEGREES_VER),4) # v4 here
|
||||||
|
_51DEGREES_SRC = $(shell find $(51DEGREES_LIB) -maxdepth 2 -name '*.c')
|
||||||
|
OPTIONS_OBJS += $(_51DEGREES_SRC:%.c=%.o)
|
||||||
|
51DEGREES_CFLAGS += -DUSE_51DEGREES_V4
|
||||||
|
ifeq ($(USE_THREAD:0=),)
|
||||||
|
51DEGREES_CFLAGS += -DFIFTYONEDEGREES_NO_THREADING -DFIFTYONE_DEGREES_NO_THREADING
|
||||||
|
endif
|
||||||
|
USE_LIBATOMIC = implicit
|
||||||
|
endif # 51DEGREES_VER==4
|
||||||
|
|
||||||
|
ifeq ($(51DEGREES_VER),3) # v3 here
|
||||||
|
OPTIONS_OBJS += $(51DEGREES_LIB)/../cityhash/city.o
|
||||||
|
OPTIONS_OBJS += $(51DEGREES_LIB)/51Degrees.o
|
||||||
|
ifeq ($(USE_THREAD:0=),)
|
||||||
|
51DEGREES_CFLAGS += -DFIFTYONEDEGREES_NO_THREADING
|
||||||
|
else
|
||||||
|
OPTIONS_OBJS += $(51DEGREES_LIB)/../threading.o
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
ifneq ($(51DEGREES_VER),4)
|
||||||
|
$(error 51Degrees version (51DEGREES_VER) must be either 3 or 4)
|
||||||
|
endif
|
||||||
|
endif # 51DEGREES_VER==3
|
||||||
|
|
||||||
|
OPTIONS_OBJS += addons/51degrees/51d.o
|
||||||
|
51DEGREES_CFLAGS += $(if $(51DEGREES_INC),-I$(51DEGREES_INC))
|
||||||
|
51DEGREES_LDFLAGS += $(if $(51DEGREES_LIB),-L$(51DEGREES_LIB))
|
||||||
|
USE_MATH = implicit
|
||||||
endif # USE_51DEGREES
|
endif # USE_51DEGREES
|
||||||
|
|
||||||
ifneq ($(USE_WURFL:0=),)
|
ifneq ($(USE_WURFL:0=),)
|
||||||
EXTRA_MAKE += addons/wurfl
|
# Use WURFL_SRC and possibly WURFL_INC and WURFL_LIB to force path
|
||||||
|
# to WURFL headers and libraries if needed.
|
||||||
|
WURFL_INC = $(WURFL_SRC)
|
||||||
|
WURFL_LIB = $(WURFL_SRC)
|
||||||
|
OPTIONS_OBJS += addons/wurfl/wurfl.o
|
||||||
|
WURFL_CFLAGS = $(if $(WURFL_INC),-I$(WURFL_INC))
|
||||||
|
ifneq ($(WURFL_DEBUG),)
|
||||||
|
WURFL_CFLAGS += -DWURFL_DEBUG
|
||||||
|
endif
|
||||||
|
ifneq ($(WURFL_HEADER_WITH_DETAILS),)
|
||||||
|
WURFL_CFLAGS += -DWURFL_HEADER_WITH_DETAILS
|
||||||
|
endif
|
||||||
|
WURFL_LDFLAGS = $(if $(WURFL_LIB),-L$(WURFL_LIB)) -lwurfl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(USE_PCRE:0=)$(USE_STATIC_PCRE:0=)$(USE_PCRE_JIT:0=),)
|
ifneq ($(USE_PCRE:0=)$(USE_STATIC_PCRE:0=)$(USE_PCRE_JIT:0=),)
|
||||||
|
|
@ -803,6 +864,11 @@ ifneq ($(USE_LINUX_CAP:0=),)
|
||||||
OPTIONS_OBJS += src/linuxcap.o
|
OPTIONS_OBJS += src/linuxcap.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(USE_OT:0=),)
|
||||||
|
$(call warning, The opentracing filter was deprecated in haproxy 3.3 and will be removed in 3.5.)
|
||||||
|
include addons/ot/Makefile
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(EXTRA_MAKE),)
|
ifneq ($(EXTRA_MAKE),)
|
||||||
include $(addsuffix /Makefile.mk,$(EXTRA_MAKE))
|
include $(addsuffix /Makefile.mk,$(EXTRA_MAKE))
|
||||||
endif
|
endif
|
||||||
|
|
@ -992,7 +1058,7 @@ IGNORE_OPTS=help install install-man install-doc install-bin \
|
||||||
|
|
||||||
ifneq ($(TARGET),)
|
ifneq ($(TARGET),)
|
||||||
ifeq ($(filter $(firstword $(MAKECMDGOALS)),$(IGNORE_OPTS)),)
|
ifeq ($(filter $(firstword $(MAKECMDGOALS)),$(IGNORE_OPTS)),)
|
||||||
build_opts = $(shell rm -f .build_opts.new; echo \'$(TARGET) $(BUILD_OPTIONS) $(EXTRA_MAKE) $(VERBOSE_CFLAGS) $(WARN_CFLAGS) $(NOWARN_CFLAGS) $(DEBUG)\' > .build_opts.new; if cmp -s .build_opts .build_opts.new; then rm -f .build_opts.new; else mv -f .build_opts.new .build_opts; fi)
|
build_opts = $(shell rm -f .build_opts.new; echo \'$(TARGET) $(BUILD_OPTIONS) $(VERBOSE_CFLAGS) $(WARN_CFLAGS) $(NOWARN_CFLAGS) $(DEBUG)\' > .build_opts.new; if cmp -s .build_opts .build_opts.new; then rm -f .build_opts.new; else mv -f .build_opts.new .build_opts; fi)
|
||||||
.build_opts: $(build_opts)
|
.build_opts: $(build_opts)
|
||||||
else
|
else
|
||||||
.build_opts:
|
.build_opts:
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/illumos.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/illumos.yml)
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/netbsd.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/netbsd.yml)
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/cross-zoo.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/cross-zoo.yml)
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/freebsd.yml)
|
[](https://cirrus-ci.com/github/haproxy/haproxy/)
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/vtest.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/vtest.yml)
|
||||||
|
|
||||||

|

|
||||||
|
|
|
||||||
2
VERDATE
2
VERDATE
|
|
@ -1,2 +1,2 @@
|
||||||
$Format:%ci$
|
$Format:%ci$
|
||||||
2026/06/25
|
2026/05/20
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
3.5-dev1
|
3.4-dev13
|
||||||
|
|
|
||||||
|
|
@ -127,16 +127,7 @@ static int _51d_property_name_list(char **args, int section_type, struct proxy *
|
||||||
|
|
||||||
while (*(args[cur_arg])) {
|
while (*(args[cur_arg])) {
|
||||||
name = calloc(1, sizeof(*name));
|
name = calloc(1, sizeof(*name));
|
||||||
if (!name) {
|
|
||||||
memprintf(err, "'%s' failed to allocate memory.", args[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
name->name = strdup(args[cur_arg]);
|
name->name = strdup(args[cur_arg]);
|
||||||
if (!name->name) {
|
|
||||||
free(name);
|
|
||||||
memprintf(err, "'%s' failed to allocate memory.", args[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
LIST_APPEND(&global_51degrees.property_names, &name->list);
|
LIST_APPEND(&global_51degrees.property_names, &name->list);
|
||||||
++cur_arg;
|
++cur_arg;
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +303,6 @@ static void _51d_init_device_offsets(fiftyoneDegreesDeviceOffsets *offsets) {
|
||||||
|
|
||||||
static void _51d_set_device_offsets(struct sample *smp, fiftyoneDegreesDeviceOffsets *offsets)
|
static void _51d_set_device_offsets(struct sample *smp, fiftyoneDegreesDeviceOffsets *offsets)
|
||||||
{
|
{
|
||||||
struct buffer *temp = get_trash_chunk();
|
|
||||||
struct channel *chn;
|
struct channel *chn;
|
||||||
struct htx *htx;
|
struct htx *htx;
|
||||||
struct http_hdr_ctx ctx;
|
struct http_hdr_ctx ctx;
|
||||||
|
|
@ -334,15 +324,7 @@ static void _51d_set_device_offsets(struct sample *smp, fiftyoneDegreesDeviceOff
|
||||||
|
|
||||||
if (http_find_header(htx, name, &ctx, 1)) {
|
if (http_find_header(htx, name, &ctx, 1)) {
|
||||||
(offsets->firstOffset + offsets->size)->httpHeaderOffset = *(global_51degrees.header_offsets + i);
|
(offsets->firstOffset + offsets->size)->httpHeaderOffset = *(global_51degrees.header_offsets + i);
|
||||||
/* Copy value into trash and NUL-terminate before passing to the
|
(offsets->firstOffset + offsets->size)->deviceOffset = fiftyoneDegreesGetDeviceOffset(&global_51degrees.data_set, ctx.value.ptr);
|
||||||
* 51Degrees Trie API, which expects a C string.
|
|
||||||
*/
|
|
||||||
if (ctx.value.len >= temp->size)
|
|
||||||
continue;
|
|
||||||
memcpy(temp->area, ctx.value.ptr, ctx.value.len);
|
|
||||||
temp->area[ctx.value.len] = '\0';
|
|
||||||
temp->data = ctx.value.len + 1;
|
|
||||||
(offsets->firstOffset + offsets->size)->deviceOffset = fiftyoneDegreesGetDeviceOffset(&global_51degrees.data_set, temp->area);
|
|
||||||
offsets->size++;
|
offsets->size++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -937,10 +919,6 @@ static int init_51degrees(void)
|
||||||
list_for_each_entry(name, &global_51degrees.property_names, list)
|
list_for_each_entry(name, &global_51degrees.property_names, list)
|
||||||
++i;
|
++i;
|
||||||
_51d_property_list = calloc(i, sizeof(*_51d_property_list));
|
_51d_property_list = calloc(i, sizeof(*_51d_property_list));
|
||||||
if (!_51d_property_list) {
|
|
||||||
ha_alert("51Degrees: Failed to allocate property list.\n");
|
|
||||||
return (ERR_FATAL | ERR_ALERT);
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
list_for_each_entry(name, &global_51degrees.property_names, list)
|
list_for_each_entry(name, &global_51degrees.property_names, list)
|
||||||
|
|
@ -1075,7 +1053,7 @@ static int init_51degrees(void)
|
||||||
|
|
||||||
static void deinit_51degrees(void)
|
static void deinit_51degrees(void)
|
||||||
{
|
{
|
||||||
struct _51d_property_names *_51d_prop_name = NULL, *_51d_prop_nameb = NULL;
|
struct _51d_property_names *_51d_prop_name, *_51d_prop_nameb;
|
||||||
|
|
||||||
#if defined(FIFTYONEDEGREES_H_PATTERN_INCLUDED) || defined(FIFTYONEDEGREES_H_TRIE_INCLUDED)
|
#if defined(FIFTYONEDEGREES_H_PATTERN_INCLUDED) || defined(FIFTYONEDEGREES_H_TRIE_INCLUDED)
|
||||||
free(global_51degrees.header_names);
|
free(global_51degrees.header_names);
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
# Use 51DEGREES_SRC and possibly 51DEGREES_INC and 51DEGREES_LIB to force path
|
|
||||||
# to 51degrees v3/v4 headers and libraries if needed. Note that the SRC/INC/
|
|
||||||
# LIB/CFLAGS/LDFLAGS variables names all use 51DEGREES as the prefix,
|
|
||||||
# regardless of the version since they are mutually exclusive. The version
|
|
||||||
# (51DEGREES_VER) must be either 3 or 4, and defaults to 3 if not set.
|
|
||||||
51DEGREES_INC = $(51DEGREES_SRC)
|
|
||||||
51DEGREES_LIB = $(51DEGREES_SRC)
|
|
||||||
51DEGREES_VER = 3
|
|
||||||
|
|
||||||
ifeq ($(51DEGREES_VER),4) # v4 here
|
|
||||||
_51DEGREES_SRC = $(shell find $(51DEGREES_LIB) -maxdepth 2 -name '*.c')
|
|
||||||
OPTIONS_OBJS += $(_51DEGREES_SRC:%.c=%.o)
|
|
||||||
51DEGREES_CFLAGS += -DUSE_51DEGREES_V4
|
|
||||||
ifeq ($(USE_THREAD:0=),)
|
|
||||||
51DEGREES_CFLAGS += -DFIFTYONEDEGREES_NO_THREADING -DFIFTYONE_DEGREES_NO_THREADING
|
|
||||||
endif
|
|
||||||
USE_LIBATOMIC = implicit
|
|
||||||
endif # 51DEGREES_VER==4
|
|
||||||
|
|
||||||
ifeq ($(51DEGREES_VER),3) # v3 here
|
|
||||||
OPTIONS_OBJS += $(51DEGREES_LIB)/../cityhash/city.o
|
|
||||||
OPTIONS_OBJS += $(51DEGREES_LIB)/51Degrees.o
|
|
||||||
ifeq ($(USE_THREAD:0=),)
|
|
||||||
51DEGREES_CFLAGS += -DFIFTYONEDEGREES_NO_THREADING
|
|
||||||
else
|
|
||||||
OPTIONS_OBJS += $(51DEGREES_LIB)/../threading.o
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
ifneq ($(51DEGREES_VER),4)
|
|
||||||
$(error 51Degrees version (51DEGREES_VER) must be either 3 or 4)
|
|
||||||
endif
|
|
||||||
endif # 51DEGREES_VER==3
|
|
||||||
|
|
||||||
OPTIONS_OBJS += addons/51degrees/51d.o
|
|
||||||
51DEGREES_CFLAGS += $(if $(51DEGREES_INC),-I$(51DEGREES_INC))
|
|
||||||
51DEGREES_LDFLAGS += $(if $(51DEGREES_LIB),-L$(51DEGREES_LIB))
|
|
||||||
USE_MATH = implicit
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
# DEVICEATLAS_SRC : DeviceAtlas API source root path
|
# DEVICEATLAS_SRC : DeviceAtlas API source root path
|
||||||
|
|
||||||
|
|
||||||
# Use DEVICEATLAS_SRC and possibly DEVICEATLAS_INC and DEVICEATLAS_LIB to force path
|
|
||||||
# to DeviceAtlas headers and libraries if needed. In this context, DEVICEATLAS_NOCACHE
|
|
||||||
# can be used to disable the cache support if needed (this also removes the necessity of having
|
|
||||||
# a C++ toolchain installed).
|
|
||||||
DEVICEATLAS_INC = $(DEVICEATLAS_SRC)
|
|
||||||
DEVICEATLAS_LIB = $(DEVICEATLAS_SRC)
|
|
||||||
|
|
||||||
CXX := c++
|
CXX := c++
|
||||||
CXXLIB := -lstdc++
|
CXXLIB := -lstdc++
|
||||||
|
|
||||||
|
|
@ -35,7 +28,5 @@ OPTIONS_OBJS += $(DEVICEATLAS_SRC)/dadwcurl.o
|
||||||
OPTIONS_OBJS += $(DEVICEATLAS_SRC)/Os/daunix.o
|
OPTIONS_OBJS += $(DEVICEATLAS_SRC)/Os/daunix.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OPTIONS_OBJS += addons/deviceatlas/da.o
|
|
||||||
|
|
||||||
addons/deviceatlas/dummy/%.o: addons/deviceatlas/dummy/%.cpp
|
addons/deviceatlas/dummy/%.o: addons/deviceatlas/dummy/%.cpp
|
||||||
$(cmd_CXX) $(CXXFLAGS) -c -o $@ $<
|
$(cmd_CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
1
addons/ot/AUTHORS
Normal file
1
addons/ot/AUTHORS
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Miroslav Zagorac <mzagorac@haproxy.com>
|
||||||
1
addons/ot/MAINTAINERS
Normal file
1
addons/ot/MAINTAINERS
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Miroslav Zagorac <mzagorac@haproxy.com>
|
||||||
73
addons/ot/Makefile
Normal file
73
addons/ot/Makefile
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
# USE_OT : enable the OpenTracing filter
|
||||||
|
# OT_DEBUG : compile the OpenTracing filter in debug mode
|
||||||
|
# OT_INC : force the include path to libopentracing-c-wrapper
|
||||||
|
# OT_LIB : force the lib path to libopentracing-c-wrapper
|
||||||
|
# OT_RUNPATH : add libopentracing-c-wrapper RUNPATH to haproxy executable
|
||||||
|
# OT_USE_VARS : allows the use of variables for the OpenTracing context
|
||||||
|
|
||||||
|
OT_DEFINE =
|
||||||
|
OT_CFLAGS =
|
||||||
|
OT_LDFLAGS =
|
||||||
|
OT_DEBUG_EXT =
|
||||||
|
OT_PKGSTAT =
|
||||||
|
OTC_WRAPPER = opentracing-c-wrapper
|
||||||
|
|
||||||
|
ifneq ($(OT_DEBUG),)
|
||||||
|
OT_DEBUG_EXT = _dbg
|
||||||
|
OT_DEFINE = -DDEBUG_OT
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OT_INC),)
|
||||||
|
OT_PKGSTAT = $(shell pkg-config --exists $(OTC_WRAPPER)$(OT_DEBUG_EXT); echo $$?)
|
||||||
|
OT_CFLAGS = $(shell pkg-config --silence-errors --cflags $(OTC_WRAPPER)$(OT_DEBUG_EXT))
|
||||||
|
else
|
||||||
|
ifneq ($(wildcard $(OT_INC)/$(OTC_WRAPPER)/.*),)
|
||||||
|
OT_CFLAGS = -I$(OT_INC) $(if $(OT_DEBUG),-DOTC_DBG_MEM)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OT_PKGSTAT),)
|
||||||
|
ifeq ($(OT_CFLAGS),)
|
||||||
|
$(error OpenTracing C wrapper : can't find headers)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
ifneq ($(OT_PKGSTAT),0)
|
||||||
|
$(error OpenTracing C wrapper : can't find package)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OT_LIB),)
|
||||||
|
OT_LDFLAGS = $(shell pkg-config --silence-errors --libs $(OTC_WRAPPER)$(OT_DEBUG_EXT))
|
||||||
|
else
|
||||||
|
ifneq ($(wildcard $(OT_LIB)/lib$(OTC_WRAPPER).*),)
|
||||||
|
OT_LDFLAGS = -L$(OT_LIB) -l$(OTC_WRAPPER)$(OT_DEBUG_EXT)
|
||||||
|
ifneq ($(OT_RUNPATH),)
|
||||||
|
OT_LDFLAGS += -Wl,--rpath,$(OT_LIB)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OT_LDFLAGS),)
|
||||||
|
$(error OpenTracing C wrapper : can't find library)
|
||||||
|
endif
|
||||||
|
|
||||||
|
OPTIONS_OBJS += \
|
||||||
|
addons/ot/src/cli.o \
|
||||||
|
addons/ot/src/conf.o \
|
||||||
|
addons/ot/src/event.o \
|
||||||
|
addons/ot/src/filter.o \
|
||||||
|
addons/ot/src/group.o \
|
||||||
|
addons/ot/src/http.o \
|
||||||
|
addons/ot/src/opentracing.o \
|
||||||
|
addons/ot/src/parser.o \
|
||||||
|
addons/ot/src/pool.o \
|
||||||
|
addons/ot/src/scope.o \
|
||||||
|
addons/ot/src/util.o
|
||||||
|
|
||||||
|
ifneq ($(OT_USE_VARS),)
|
||||||
|
OT_DEFINE += -DUSE_OT_VARS
|
||||||
|
OPTIONS_OBJS += \
|
||||||
|
addons/ot/src/vars.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
OT_CFLAGS := $(OT_CFLAGS) $(OT_DEFINE)
|
||||||
799
addons/ot/README
Normal file
799
addons/ot/README
Normal file
|
|
@ -0,0 +1,799 @@
|
||||||
|
-----------------------------------------
|
||||||
|
The HAProxy OpenTracing filter (OT)
|
||||||
|
Version 1.0
|
||||||
|
( Last update: 2020-12-10 )
|
||||||
|
-----------------------------------------
|
||||||
|
Author : Miroslav Zagorac
|
||||||
|
Contact : mzagorac at haproxy dot com
|
||||||
|
|
||||||
|
|
||||||
|
SUMMARY
|
||||||
|
--------
|
||||||
|
|
||||||
|
0. Terms
|
||||||
|
1. Introduction
|
||||||
|
2. Build instructions
|
||||||
|
3. Basic concepts in OpenTracing
|
||||||
|
4. OT configuration
|
||||||
|
4.1. OT scope
|
||||||
|
4.2. "ot-tracer" section
|
||||||
|
4.3. "ot-scope" section
|
||||||
|
4.4. "ot-group" section
|
||||||
|
5. Examples
|
||||||
|
5.1 Benchmarking results
|
||||||
|
6. OT CLI
|
||||||
|
7. Known bugs and limitations
|
||||||
|
|
||||||
|
|
||||||
|
0. Terms
|
||||||
|
---------
|
||||||
|
|
||||||
|
* OT: The HAProxy OpenTracing filter
|
||||||
|
|
||||||
|
OT is the HAProxy filter that allows you to send data to distributed
|
||||||
|
tracing systems via the OpenTracing API.
|
||||||
|
|
||||||
|
|
||||||
|
1. Introduction
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Nowadays there is a growing need to divide a process into microservices and
|
||||||
|
there is a problem of monitoring the work of the same process. One way to
|
||||||
|
solve this problem is to use distributed tracing service in a central location,
|
||||||
|
the so-called tracer.
|
||||||
|
|
||||||
|
OT is a feature introduced in HAProxy 2.4. This filter enables communication
|
||||||
|
via the OpenTracing API with OpenTracing compatible servers (tracers).
|
||||||
|
Currently, tracers that support this API include Datadog, Jaeger, LightStep
|
||||||
|
and Zipkin.
|
||||||
|
|
||||||
|
Note: The OpenTracing filter shouldn't be used for new designs as OpenTracing
|
||||||
|
itself is no longer maintained nor supported by its authors. As such
|
||||||
|
OpenTracing will be deprecated in 3.3 and removed in 3.5. A replacement
|
||||||
|
filter based on OpenTelemetry is available since 3.4 with complete build
|
||||||
|
instructions currently at:
|
||||||
|
|
||||||
|
https://github.com/haproxytech/haproxy-opentelemetry/
|
||||||
|
|
||||||
|
The OT filter is a standard HAProxy filter, so what applies to others also
|
||||||
|
applies to this one (of course, by that I mean what is described in the
|
||||||
|
documentation, more precisely in the doc/internals/filters.txt file).
|
||||||
|
|
||||||
|
The OT filter activation is done explicitly by specifying it in the HAProxy
|
||||||
|
configuration. If this is not done, the OT filter in no way participates
|
||||||
|
in the work of HAProxy.
|
||||||
|
|
||||||
|
As for the impact on HAProxy speed, this is documented with several tests
|
||||||
|
located in the test directory, and the result is found in the README-speed-*
|
||||||
|
files. In short, the speed of operation depends on the way it is used and
|
||||||
|
the complexity of the configuration, from an almost immeasurable impact to
|
||||||
|
a significant deceleration (5x and more). I think that in some normal use
|
||||||
|
the speed of HAProxy with the filter on will be quite satisfactory with a
|
||||||
|
slowdown of less than 4% (provided that no more than 10% of requests are
|
||||||
|
sent to the tracer, which is determined by the keyword 'rate-limit').
|
||||||
|
|
||||||
|
The OT filter allows intensive use of ACLs, which can be defined anywhere in
|
||||||
|
the configuration. Thus, it is possible to use the filter only for those
|
||||||
|
connections that are of interest to us.
|
||||||
|
|
||||||
|
|
||||||
|
2. Build instructions
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
OT is the HAProxy filter and as such is compiled together with HAProxy.
|
||||||
|
|
||||||
|
To communicate with some OpenTracing compatible tracer, the OT filter uses the
|
||||||
|
OpenTracing C Wrapper library (which again uses the OpenTracing CPP library).
|
||||||
|
This means that we must have both libraries installed on the system on which
|
||||||
|
we want to compile or use HAProxy.
|
||||||
|
|
||||||
|
Instructions for compiling and installing both required libraries can be
|
||||||
|
found at https://github.com/haproxytech/opentracing-c-wrapper .
|
||||||
|
|
||||||
|
Also, to use the OT filter when running HAProxy we need to have an OpenTracing
|
||||||
|
plugin for the tracer we want to use. We will return to this later, in
|
||||||
|
section 5.
|
||||||
|
|
||||||
|
The OT filter can be more easily compiled using the pkg-config tool, if we
|
||||||
|
have the OpenTracing C Wrapper library installed so that it contains pkg-config
|
||||||
|
files (which have the .pc extension). If the pkg-config tool cannot be used,
|
||||||
|
then the path to the directory where the include files and libraries are
|
||||||
|
located can be explicitly specified.
|
||||||
|
|
||||||
|
Below are examples of the two ways to compile HAProxy with the OT filter, the
|
||||||
|
first using the pkg-congfig tool and the second explicitly specifying the path
|
||||||
|
to the OpenTracing C Wrapper include and library.
|
||||||
|
|
||||||
|
Note: prompt '%' indicates that the command is executed under a unprivileged
|
||||||
|
user, while prompt '#' indicates that the command is executed under the
|
||||||
|
root user.
|
||||||
|
|
||||||
|
Example of compiling HAProxy using the pkg-congfig tool (assuming the
|
||||||
|
OpenTracing C Wrapper library is installed in the /opt directory):
|
||||||
|
|
||||||
|
% PKG_CONFIG_PATH=/opt/lib/pkgconfig make USE_OT=1 TARGET=linux-glibc
|
||||||
|
|
||||||
|
The OT filter can also be compiled in debug mode as follows:
|
||||||
|
|
||||||
|
% PKG_CONFIG_PATH=/opt/lib/pkgconfig make USE_OT=1 OT_DEBUG=1 TARGET=linux-glibc
|
||||||
|
|
||||||
|
HAProxy compilation example explicitly specifying path to the OpenTracing C
|
||||||
|
Wrapper include and library:
|
||||||
|
|
||||||
|
% make USE_OT=1 OT_INC=/opt/include OT_LIB=/opt/lib TARGET=linux-glibc
|
||||||
|
|
||||||
|
In case we want to use debug mode, then it looks like this:
|
||||||
|
|
||||||
|
% make USE_OT=1 OT_DEBUG=1 OT_INC=/opt/include OT_LIB=/opt/lib TARGET=linux-glibc
|
||||||
|
|
||||||
|
If the library we want to use is not installed on a unix system, then a locally
|
||||||
|
installed library can be used (say, which is compiled and installed in the user
|
||||||
|
home directory). In this case instead of /opt/include and /opt/lib the
|
||||||
|
equivalent paths to the local installation should be specified. Of course,
|
||||||
|
in that case the pkg-config tool can also be used if we have a complete
|
||||||
|
installation (with .pc files).
|
||||||
|
|
||||||
|
last but not least, if the pkg-config tool is not used when compiling, then
|
||||||
|
HAProxy executable may not be able to find the OpenTracing C Wrapper library
|
||||||
|
at startup. This can be solved in several ways, for example using the
|
||||||
|
LD_LIBRARY_PATH environment variable which should be set to the path where the
|
||||||
|
library is located before starting the HAProxy.
|
||||||
|
|
||||||
|
% LD_LIBRARY_PATH=/opt/lib /path-to/haproxy ...
|
||||||
|
|
||||||
|
Another way is to add RUNPATH to HAProxy executable that contains the path to
|
||||||
|
the library in question.
|
||||||
|
|
||||||
|
% make USE_OT=1 OT_RUNPATH=1 OT_INC=/opt/include OT_LIB=/opt/lib TARGET=linux-glibc
|
||||||
|
|
||||||
|
After HAProxy is compiled, we can check if the OT filter is enabled:
|
||||||
|
|
||||||
|
% ./haproxy -vv | grep opentracing
|
||||||
|
--- command output ----------
|
||||||
|
[ OT] opentracing
|
||||||
|
--- command output ----------
|
||||||
|
|
||||||
|
|
||||||
|
3. Basic concepts in OpenTracing
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Basic concepts of OpenTracing can be read on the OpenTracing documentation
|
||||||
|
website https://opentracing.io/docs/overview/.
|
||||||
|
|
||||||
|
Here we will list only the most important elements of distributed tracing and
|
||||||
|
these are 'trace', 'span' and 'span context'. Trace is a description of the
|
||||||
|
complete transaction we want to record in the tracing system. A span is an
|
||||||
|
operation that represents a unit of work that is recorded in a tracing system.
|
||||||
|
Span context is a group of information related to a particular span that is
|
||||||
|
passed on to the system (from service to service). Using this context, we can
|
||||||
|
add new spans to already open trace (or supplement data in already open spans).
|
||||||
|
|
||||||
|
An individual span may contain one or more tags, logs and baggage items.
|
||||||
|
The tag is a key-value element that is valid for the entire span. Log is a
|
||||||
|
key-value element that allows you to write some data at a certain time, it
|
||||||
|
can be used for debugging. A baggage item is a key-value data pair that can
|
||||||
|
be used for the duration of an entire trace, from the moment it is added to
|
||||||
|
the span.
|
||||||
|
|
||||||
|
|
||||||
|
4. OT configuration
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
In order for the OT filter to be used, it must be included in the HAProxy
|
||||||
|
configuration, in the proxy section (frontend / listen / backend):
|
||||||
|
|
||||||
|
frontend ot-test
|
||||||
|
...
|
||||||
|
filter opentracing [id <id>] config <file>
|
||||||
|
...
|
||||||
|
|
||||||
|
If no filter id is specified, 'ot-filter' is used as default. The 'config'
|
||||||
|
parameter must be specified and it contains the path of the file used to
|
||||||
|
configure the OT filter.
|
||||||
|
|
||||||
|
|
||||||
|
4.1 OT scope
|
||||||
|
-------------
|
||||||
|
|
||||||
|
If the filter id is defined for the OT filter, then the OT scope with
|
||||||
|
the same name should be defined in the configuration file. In the same
|
||||||
|
configuration file we can have several defined OT scopes.
|
||||||
|
|
||||||
|
Each OT scope must have a defined (only one) "ot-tracer" section that is
|
||||||
|
used to configure the operation of the OT filter and define the used groups
|
||||||
|
and scopes.
|
||||||
|
|
||||||
|
OT scope starts with the id of the filter specified in square brackets and
|
||||||
|
ends with the end of the file or when a new OT scope is defined.
|
||||||
|
|
||||||
|
For example, this defines two OT scopes in the same configuration file:
|
||||||
|
[my-first-ot-filter]
|
||||||
|
ot-tracer tracer1
|
||||||
|
...
|
||||||
|
ot-group group1
|
||||||
|
...
|
||||||
|
ot-scope scope1
|
||||||
|
...
|
||||||
|
|
||||||
|
[my-second-ot-filter]
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
4.2. "ot-tracer" section
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Only one "ot-tracer" section must be defined for each OT scope.
|
||||||
|
|
||||||
|
There are several keywords that must be defined for the OT filter to work.
|
||||||
|
These are 'config' which defines the configuration file for the OpenTracing
|
||||||
|
API, and 'plugin' which defines the OpenTracing plugin used.
|
||||||
|
|
||||||
|
Through optional keywords can be defined ACLs, logging, rate limit, and groups
|
||||||
|
and scopes that define the tracing model.
|
||||||
|
|
||||||
|
|
||||||
|
ot-tracer <name>
|
||||||
|
A new OT with the name <name> is created.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the tracer section
|
||||||
|
|
||||||
|
|
||||||
|
The following keywords are supported in this section:
|
||||||
|
- mandatory keywords:
|
||||||
|
- config
|
||||||
|
- plugin
|
||||||
|
|
||||||
|
- optional keywords:
|
||||||
|
- acl
|
||||||
|
- debug-level
|
||||||
|
- groups
|
||||||
|
- [no] log
|
||||||
|
- [no] option disabled
|
||||||
|
- [no] option dontlog-normal
|
||||||
|
- [no] option hard-errors
|
||||||
|
- rate-limit
|
||||||
|
- scopes
|
||||||
|
|
||||||
|
|
||||||
|
acl <aclname> <criterion> [flags] [operator] <value> ...
|
||||||
|
Declare or complete an access list.
|
||||||
|
|
||||||
|
To configure and use the ACL, see section 7 of the HAProxy Configuration
|
||||||
|
Manual.
|
||||||
|
|
||||||
|
|
||||||
|
config <file>
|
||||||
|
'config' is one of the two mandatory keywords associated with the OT tracer
|
||||||
|
configuration. This keyword sets the path of the configuration file for the
|
||||||
|
OpenTracing tracer plugin. To set the contents of this configuration file,
|
||||||
|
it is best to look at the documentation related to the OpenTracing tracer we
|
||||||
|
want to use.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
file - the path of the configuration file
|
||||||
|
|
||||||
|
|
||||||
|
debug-level <value>
|
||||||
|
This keyword sets the value of the debug level related to the display of
|
||||||
|
debug messages in the OT filter. The 'debug-level' value is binary, ie
|
||||||
|
a single value bit enables or disables the display of the corresponding
|
||||||
|
debug message that uses that bit. The default value is set via the
|
||||||
|
FLT_OT_DEBUG_LEVEL macro in the include/config.h file. Debug level value
|
||||||
|
is used only if the OT filter is compiled with the debug mode enabled,
|
||||||
|
otherwise it is ignored.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
value - binary value ranging from 0 to 255 (8 bits)
|
||||||
|
|
||||||
|
|
||||||
|
groups <name> ...
|
||||||
|
A list of "ot-group" groups used for the currently defined tracer is declared.
|
||||||
|
Several groups can be specified in one line.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the OT group
|
||||||
|
|
||||||
|
|
||||||
|
log global
|
||||||
|
log <addr> [len <len>] [format <fmt>] <facility> [<level> [<minlevel>]]
|
||||||
|
no log
|
||||||
|
Enable per-instance logging of events and traffic.
|
||||||
|
|
||||||
|
To configure and use the logging system, see section 4.2 of the HAProxy
|
||||||
|
Configuration Manual.
|
||||||
|
|
||||||
|
|
||||||
|
option disabled
|
||||||
|
no option disabled
|
||||||
|
Keyword which turns the operation of the OT filter on or off. By default
|
||||||
|
the filter is on.
|
||||||
|
|
||||||
|
|
||||||
|
option dontlog-normal
|
||||||
|
no option dontlog-normal
|
||||||
|
Enable or disable logging of normal, successful processing. By default,
|
||||||
|
this option is disabled. For this option to be considered, logging must
|
||||||
|
be turned on.
|
||||||
|
|
||||||
|
See also: 'log' keyword description.
|
||||||
|
|
||||||
|
|
||||||
|
option hard-errors
|
||||||
|
no option hard-errors
|
||||||
|
During the operation of the filter, some errors may occur, caused by
|
||||||
|
incorrect configuration of the tracer or some error related to the operation
|
||||||
|
of HAProxy. By default, such an error will not interrupt the filter
|
||||||
|
operation for the stream in which the error occurred. If the 'hard-error'
|
||||||
|
option is enabled, the operation error prohibits all further processing of
|
||||||
|
events and groups in the stream in which the error occurred.
|
||||||
|
|
||||||
|
|
||||||
|
plugin <file>
|
||||||
|
'plugin' is one of the two mandatory keywords associated with the OT tracer
|
||||||
|
configuration. This keyword sets the path of the OpenTracing tracer plugin.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
file - the name of the plugin used
|
||||||
|
|
||||||
|
|
||||||
|
rate-limit <value>
|
||||||
|
This option allows limiting the use of the OT filter, ie it can be influenced
|
||||||
|
whether the OT filter is activated for a stream or not. Determining whether
|
||||||
|
or not a filter is activated depends on the value of this option that is
|
||||||
|
compared to a randomly selected value when attaching the filter to the stream.
|
||||||
|
By default, the value of this option is set to 100.0, ie the OT filter is
|
||||||
|
activated for each stream.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
value - floating point value ranging from 0.0 to 100.0
|
||||||
|
|
||||||
|
|
||||||
|
scopes <name> ...
|
||||||
|
This keyword declares a list of "ot-scope" definitions used for the currently
|
||||||
|
defined tracer. Multiple scopes can be specified in the same line.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the OT scope
|
||||||
|
|
||||||
|
|
||||||
|
4.3. "ot-scope" section
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Stream processing begins with filter attachment, then continues with the
|
||||||
|
processing of a number of defined events and groups, and ends with filter
|
||||||
|
detachment. The "ot-scope" section is used to define actions related to
|
||||||
|
individual events. However, this section may be part of a group, so the
|
||||||
|
event does not have to be part of the definition.
|
||||||
|
|
||||||
|
|
||||||
|
ot-scope <name>
|
||||||
|
Creates a new OT scope definition named <name>.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the OT scope
|
||||||
|
|
||||||
|
|
||||||
|
The following keywords are supported in this section:
|
||||||
|
- acl
|
||||||
|
- baggage
|
||||||
|
- event
|
||||||
|
- extract
|
||||||
|
- finish
|
||||||
|
- inject
|
||||||
|
- log
|
||||||
|
- span
|
||||||
|
- tag
|
||||||
|
|
||||||
|
|
||||||
|
acl <aclname> <criterion> [flags] [operator] <value> ...
|
||||||
|
Declare or complete an access list.
|
||||||
|
|
||||||
|
To configure and use the ACL, see section 7 of the HAProxy Configuration
|
||||||
|
Manual.
|
||||||
|
|
||||||
|
|
||||||
|
baggage <name> <sample> ...
|
||||||
|
Baggage items allow the propagation of data between spans, ie allow the
|
||||||
|
assignment of metadata that is propagated to future children spans.
|
||||||
|
This data is formatted in the style of key-value pairs and is part of
|
||||||
|
the context that can be transferred between processes that are part of
|
||||||
|
a server architecture.
|
||||||
|
|
||||||
|
This kewyord allows setting the baggage for the currently active span. The
|
||||||
|
data type is always a string, ie any sample type is converted to a string.
|
||||||
|
The exception is a binary value that is not supported by the OT filter.
|
||||||
|
|
||||||
|
See the 'tag' keyword description for the data type conversion table.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - key part of a data pair
|
||||||
|
sample - sample expression (value part of a data pair), at least one
|
||||||
|
sample must be present
|
||||||
|
|
||||||
|
|
||||||
|
event <name> [{ if | unless } <condition>]
|
||||||
|
Set the event that triggers the 'ot-scope' to which it is assigned.
|
||||||
|
Optionally, it can be followed by an ACL-based condition, in which case it
|
||||||
|
will only be evaluated if the condition is true.
|
||||||
|
|
||||||
|
ACL-based conditions are executed in the context of a stream that processes
|
||||||
|
the client and server connections. To configure and use the ACL, see
|
||||||
|
section 7 of the HAProxy Configuration Manual.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the event name
|
||||||
|
condition - a standard ACL-based condition
|
||||||
|
|
||||||
|
Supported events are (the table gives the names of the events in the OT
|
||||||
|
filter and the corresponding equivalent in the SPOE filter):
|
||||||
|
|
||||||
|
-------------------------------------|------------------------------
|
||||||
|
the OT filter | the SPOE filter
|
||||||
|
-------------------------------------|------------------------------
|
||||||
|
on-client-session-start | on-client-session
|
||||||
|
on-frontend-tcp-request | on-frontend-tcp-request
|
||||||
|
on-http-wait-request | -
|
||||||
|
on-http-body-request | -
|
||||||
|
on-frontend-http-request | on-frontend-http-request
|
||||||
|
on-switching-rules-request | -
|
||||||
|
on-backend-tcp-request | on-backend-tcp-request
|
||||||
|
on-backend-http-request | on-backend-http-request
|
||||||
|
on-process-server-rules-request | -
|
||||||
|
on-http-process-request | -
|
||||||
|
on-tcp-rdp-cookie-request | -
|
||||||
|
on-process-sticking-rules-request | -
|
||||||
|
on-client-session-end | -
|
||||||
|
on-server-unavailable | -
|
||||||
|
-------------------------------------|------------------------------
|
||||||
|
on-server-session-start | on-server-session
|
||||||
|
on-tcp-response | on-tcp-response
|
||||||
|
on-http-wait-response | -
|
||||||
|
on-process-store-rules-response | -
|
||||||
|
on-http-response | on-http-response
|
||||||
|
on-server-session-end | -
|
||||||
|
-------------------------------------|------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
extract <name-prefix> [use-vars | use-headers]
|
||||||
|
For a more detailed description of the propagation process of the span
|
||||||
|
context, see the description of the keyword 'inject'. Only the process
|
||||||
|
of extracting data from the carrier is described here.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name-prefix - data name prefix (ie key element prefix)
|
||||||
|
use-vars - data is extracted from HAProxy variables
|
||||||
|
use-headers - data is extracted from the HTTP header
|
||||||
|
|
||||||
|
|
||||||
|
Below is an example of using HAProxy variables to transfer span context data:
|
||||||
|
|
||||||
|
--- test/ctx/ot.cfg --------------------------------------------------------
|
||||||
|
...
|
||||||
|
ot-scope client_session_start_2
|
||||||
|
extract "ot_ctx_1" use-vars
|
||||||
|
span "Client session" child-of "ot_ctx_1"
|
||||||
|
...
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
finish <name> ...
|
||||||
|
Closing a particular span or span context. Instead of the name of the span,
|
||||||
|
there are several specially predefined names with which we can finish certain
|
||||||
|
groups of spans. So it can be used as the name '*req*' for all open spans
|
||||||
|
related to the request channel, '*res*' for all open spans related to the
|
||||||
|
response channel and '*' for all open spans regardless of which channel they
|
||||||
|
are related to. Several spans and/or span contexts can be specified in one
|
||||||
|
line.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the span or context context
|
||||||
|
|
||||||
|
|
||||||
|
inject <name-prefix> [use-vars] [use-headers]
|
||||||
|
In OpenTracing, the transfer of data related to the tracing process between
|
||||||
|
microservices that are part of a larger service is done through the
|
||||||
|
propagation of the span context. The basic operations that allow us to
|
||||||
|
access and transfer this data are 'inject' and 'extract'.
|
||||||
|
|
||||||
|
'inject' allows us to extract span context so that the obtained data can
|
||||||
|
be forwarded to another process (microservice) via the selected carrier.
|
||||||
|
'inject' in the name actually means inject data into carrier. Carrier is
|
||||||
|
an interface here (ie a data structure) that allows us to transfer tracing
|
||||||
|
state from one process to another.
|
||||||
|
|
||||||
|
Data transfer can take place via one of two selected storage methods, the
|
||||||
|
first is by adding data to the HTTP header and the second is by using HAProxy
|
||||||
|
variables. Only data transfer via HTTP header can be used to transfer data
|
||||||
|
to another process (ie microservice). All data is organized in the form of
|
||||||
|
key-value data pairs.
|
||||||
|
|
||||||
|
No matter which data transfer method you use, we need to specify a prefix
|
||||||
|
for the key element. All alphanumerics (lowercase only) and underline
|
||||||
|
character can be used to construct the data name prefix. Uppercase letters
|
||||||
|
can actually be used, but they will be converted to lowercase when creating
|
||||||
|
the prefix.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name-prefix - data name prefix (ie key element prefix)
|
||||||
|
use-vars - HAProxy variables are used to store and transfer data
|
||||||
|
use-headers - HTTP headers are used to store and transfer data
|
||||||
|
|
||||||
|
|
||||||
|
Below is an example of using HTTP headers and variables, and how this is
|
||||||
|
reflected in the internal data of the HAProxy process.
|
||||||
|
|
||||||
|
--- test/ctx/ot.cfg --------------------------------------------------------
|
||||||
|
...
|
||||||
|
ot-scope client_session_start_1
|
||||||
|
span "HAProxy session" root
|
||||||
|
inject "ot_ctx_1" use-headers use-vars
|
||||||
|
...
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
- generated HAProxy variable (key -> value):
|
||||||
|
txn.ot_ctx_1.uberDtraceDid -> 8f1a05a3518d2283:8f1a05a3518d2283:0:1
|
||||||
|
|
||||||
|
- generated HTTP header (key: value):
|
||||||
|
ot_ctx_1-uber-trace-id: 8f1a05a3518d2283:8f1a05a3518d2283:0:1
|
||||||
|
|
||||||
|
Because HAProxy does not allow the '-' character in the variable name (which
|
||||||
|
is automatically generated by the OpenTracing API and on which we have no
|
||||||
|
influence), it is converted to the letter 'D'. We can see that there is no
|
||||||
|
such conversion in the name of the HTTP header because the '-' sign is allowed
|
||||||
|
there. Due to this conversion, initially all uppercase letters are converted
|
||||||
|
to lowercase because otherwise we would not be able to distinguish whether
|
||||||
|
the disputed sign '-' is used or not.
|
||||||
|
|
||||||
|
Thus created HTTP headers and variables are deleted when executing the
|
||||||
|
'finish' keyword or when detaching the stream from the filter.
|
||||||
|
|
||||||
|
|
||||||
|
log <name> <sample> ...
|
||||||
|
This kewyord allows setting the log for the currently active span. The
|
||||||
|
data type is always a string, ie any sample type is converted to a string.
|
||||||
|
The exception is a binary value that is not supported by the OT filter.
|
||||||
|
|
||||||
|
See the 'tag' keyword description for the data type conversion table.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - key part of a data pair
|
||||||
|
sample - sample expression (value part of a data pair), at least one
|
||||||
|
sample must be present
|
||||||
|
|
||||||
|
|
||||||
|
span <name> [<reference>]
|
||||||
|
Creating a new span (or referencing an already opened one). If a new span
|
||||||
|
is created, it can be a child of the referenced span, follow from the
|
||||||
|
referenced span, or be root 'span'. In case we did not specify a reference
|
||||||
|
to the previously created span, the new span will become the root span.
|
||||||
|
We need to pay attention to the fact that in one trace there can be only
|
||||||
|
one root span. In case we have specified a non-existent span as a reference,
|
||||||
|
a new span will not be created.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the span being created or referenced (operation
|
||||||
|
name)
|
||||||
|
reference - span or span context to which the created span is referenced
|
||||||
|
|
||||||
|
|
||||||
|
tag <name> <sample> ...
|
||||||
|
This kewyord allows setting a tag for the currently active span. The first
|
||||||
|
argument is the name of the tag (tag ID) and the second its value. A value
|
||||||
|
can consist of one or more data. If the value is only one data, then the
|
||||||
|
type of that data depends on the type of the HAProxy sample. If the value
|
||||||
|
contains more data, then the data type is string. The data conversion table
|
||||||
|
is below:
|
||||||
|
|
||||||
|
HAProxy sample data type | the OpenTracing data type
|
||||||
|
--------------------------+---------------------------
|
||||||
|
NULL | NULL
|
||||||
|
BOOL | BOOL
|
||||||
|
INT32 | INT64
|
||||||
|
UINT32 | UINT64
|
||||||
|
INT64 | INT64
|
||||||
|
UINT64 | UINT64
|
||||||
|
IPV4 | STRING
|
||||||
|
IPV6 | STRING
|
||||||
|
STRING | STRING
|
||||||
|
BINARY | UNSUPPORTED
|
||||||
|
--------------------------+---------------------------
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - key part of a data pair
|
||||||
|
sample - sample expression (value part of a data pair), at least one
|
||||||
|
sample must be present
|
||||||
|
|
||||||
|
|
||||||
|
4.4. "ot-group" section
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This section allows us to define a group of OT scopes, that is not activated
|
||||||
|
via an event but is triggered from TCP or HTTP rules. More precisely, these
|
||||||
|
are the following rules: 'tcp-request', 'tcp-response', 'http-request',
|
||||||
|
'http-response' and 'http-after-response'. These rules can be defined in the
|
||||||
|
HAProxy configuration file.
|
||||||
|
|
||||||
|
|
||||||
|
ot-group <name>
|
||||||
|
Creates a new OT group definition named <name>.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the OT group
|
||||||
|
|
||||||
|
|
||||||
|
The following keywords are supported in this section:
|
||||||
|
- scopes
|
||||||
|
|
||||||
|
|
||||||
|
scopes <name> ...
|
||||||
|
'ot-scope' sections that are part of the specified group are defined. If
|
||||||
|
the mentioned 'ot-scope' sections are used only in some OT group, they do
|
||||||
|
not have to have defined events. Several 'ot-scope' sections can be
|
||||||
|
specified in one line.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
name - the name of the 'ot-scope' section
|
||||||
|
|
||||||
|
|
||||||
|
5. Examples
|
||||||
|
------------
|
||||||
|
|
||||||
|
Several examples of the OT filter configuration can be found in the test
|
||||||
|
directory. A brief description of the prepared configurations follows:
|
||||||
|
|
||||||
|
cmp - the configuration very similar to that of the spoa-opentracing project.
|
||||||
|
It was made to compare the speed of the OT filter with the
|
||||||
|
implementation of distributed tracing via spoa-opentracing application.
|
||||||
|
|
||||||
|
sa - the configuration in which all possible events are used.
|
||||||
|
|
||||||
|
ctx - the configuration is very similar to the previous one, with the only
|
||||||
|
difference that the spans are opened using the span context as a span
|
||||||
|
reference.
|
||||||
|
|
||||||
|
fe be - a slightly more complicated example of the OT filter configuration
|
||||||
|
that uses two cascaded HAProxy services. The span context between
|
||||||
|
HAProxy processes is transmitted via the HTTP header.
|
||||||
|
|
||||||
|
empty - the empty configuration in which the OT filter is initialized but
|
||||||
|
no event is triggered. It is not very usable, except to check the
|
||||||
|
behavior of the OT filter in the case of a similar configuration.
|
||||||
|
|
||||||
|
|
||||||
|
In order to be able to collect data (and view results via the web interface)
|
||||||
|
we need to install some of the supported tracers. We will use the Jaeger
|
||||||
|
tracer as an example. Installation instructions can be found on the website
|
||||||
|
https://www.jaegertracing.io/download/. For the impatient, here we will list
|
||||||
|
how the image to test the operation of the tracer system can be installed
|
||||||
|
without much reading of the documentation.
|
||||||
|
|
||||||
|
# docker pull jaegertracing/all-in-one:latest
|
||||||
|
# docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
|
||||||
|
-p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 \
|
||||||
|
-p 16686:16686 -p 14268:14268 -p 9411:9411 jaegertracing/all-in-one:latest
|
||||||
|
|
||||||
|
The last command will also initialize and run the Jaeger container. If we
|
||||||
|
want to use that container later, it can be started and stopped in the classic
|
||||||
|
way, using the 'docker container start/stop' commands.
|
||||||
|
|
||||||
|
|
||||||
|
In order to be able to use any of the configurations from the test directory,
|
||||||
|
we must also have a tracer plugin in that directory (all examples use the
|
||||||
|
Jaeger tracer plugin). The simplest way is to download the tracer plugin
|
||||||
|
using the already prepared shell script get-opentracing-plugins.sh.
|
||||||
|
The script accepts one argument, the directory in which the download is made.
|
||||||
|
If run without an argument, the script downloads all plugins to the current
|
||||||
|
directory.
|
||||||
|
|
||||||
|
% ./get-opentracing-plugins.sh
|
||||||
|
|
||||||
|
After that, we can run one of the pre-configured configurations using the
|
||||||
|
provided script run-xxx.sh (where xxx is the name of the configuration being
|
||||||
|
tested). For example:
|
||||||
|
|
||||||
|
% ./run-sa.sh
|
||||||
|
|
||||||
|
The script will create a new log file each time it is run (because part of the
|
||||||
|
log file name is the start time of the script).
|
||||||
|
|
||||||
|
Eh, someone will surely notice that all test configurations use the Jaeger
|
||||||
|
tracing plugin that cannot be downloaded using the get-opentracing-plugins.sh
|
||||||
|
script. Unfortunately, the latest precompiled version that can be downloaded
|
||||||
|
is 0.4.2, for newer ones only the source code can be found. Version 0.4.2 has
|
||||||
|
a bug that can cause the operation of the OT filter to get stuck, so it is
|
||||||
|
better not to use this version. Here is the procedure by which we can compile
|
||||||
|
a newer version of the plugin (in our example it is 0.5.0).
|
||||||
|
|
||||||
|
Important note: the GCC version must be at least 4.9 or later.
|
||||||
|
|
||||||
|
% wget https://github.com/jaegertracing/jaeger-client-cpp/archive/v0.5.0.tar.gz
|
||||||
|
% tar xf v0.5.0.tar.gz
|
||||||
|
% cd jaeger-client-cpp-0.5.0
|
||||||
|
% mkdir build
|
||||||
|
% cd build
|
||||||
|
% cmake -DCMAKE_INSTALL_PREFIX=/opt -DJAEGERTRACING_PLUGIN=ON -DHUNTER_CONFIGURATION_TYPES=Release -DHUNTER_BUILD_SHARED_LIBS=OFF ..
|
||||||
|
% make
|
||||||
|
|
||||||
|
After the plugin is compiled, it will be in the current directory. The name
|
||||||
|
of the plugin is libjaegertracing_plugin.so.
|
||||||
|
|
||||||
|
|
||||||
|
5.1. Benchmarking results
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
To check the operation of the OT filter, several different test configurations
|
||||||
|
have been made which are located in the test directory. The test results of
|
||||||
|
the same configurations (with the names README-speed-xxx, where xxx is the name
|
||||||
|
of the configuration being tested) are also in the directory of the same name.
|
||||||
|
|
||||||
|
All tests were performed on the same debian 9.13 system, CPU i7-4770, 32 GB RAM.
|
||||||
|
For the purpose of testing, the thttpd web server on port 8000 was used.
|
||||||
|
Testing was done with the wrk utility running via run-xxx.sh scripts; that is,
|
||||||
|
via the test-speed.sh script that is run as follows:
|
||||||
|
|
||||||
|
% ./test-speed.sh all
|
||||||
|
|
||||||
|
The above mentioned thttpd web server is run from that script and it should be
|
||||||
|
noted that we need to have the same installed on the system (or change the path
|
||||||
|
to the thttpd server in that script if it is installed elsewhere).
|
||||||
|
|
||||||
|
Each test is performed several times over a period of 5 minutes per individual
|
||||||
|
test. The only difference when running the tests for the same configuration
|
||||||
|
was in changing the 'rate-limit' parameter (and the 'option disabled' option),
|
||||||
|
which is set to the following values: 100.0, 50.0, 10.0, 2.5 and 0.0 percent.
|
||||||
|
Then a test is performed with the OT filter active but disabled for request
|
||||||
|
processing ('option disabled' is included in the ot.cfg configuration). In
|
||||||
|
the last test, the OT filter is not used at all, ie it is not active and does
|
||||||
|
not affect the operation of HAProxy in any way.
|
||||||
|
|
||||||
|
|
||||||
|
6. OT CLI
|
||||||
|
----------
|
||||||
|
|
||||||
|
Via the HAProxy CLI interface we can find out the current status of the OT
|
||||||
|
filter and change several of its settings.
|
||||||
|
|
||||||
|
All supported CLI commands can be found in the following way, using the
|
||||||
|
socat utility with the assumption that the HAProxy CLI socket path is set
|
||||||
|
to /tmp/haproxy.sock (of course, instead of socat, nc or other utility can
|
||||||
|
be used with a change in arguments when running the same):
|
||||||
|
|
||||||
|
% echo "help" | socat - UNIX-CONNECT:/tmp/haproxy.sock | grep flt-ot
|
||||||
|
--- command output ----------
|
||||||
|
flt-ot debug [level] : set the OT filter debug level (default: get current debug level)
|
||||||
|
flt-ot disable : disable the OT filter
|
||||||
|
flt-ot enable : enable the OT filter
|
||||||
|
flt-ot soft-errors : turning off hard-errors mode
|
||||||
|
flt-ot hard-errors : enabling hard-errors mode
|
||||||
|
flt-ot logging [state] : set logging state (default: get current logging state)
|
||||||
|
flt-ot rate [value] : set the rate limit (default: get current rate value)
|
||||||
|
flt-ot status : show the OT filter status
|
||||||
|
--- command output ----------
|
||||||
|
|
||||||
|
'flt-ot debug' can only be used in case the OT filter is compiled with the
|
||||||
|
debug mode enabled.
|
||||||
|
|
||||||
|
|
||||||
|
7. Known bugs and limitations
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
The name of the span context definition can contain only letters, numbers and
|
||||||
|
characters '_' and '-'. Also, all uppercase letters in the name are converted
|
||||||
|
to lowercase. The character '-' is converted internally to the 'D' character,
|
||||||
|
and since a HAProxy variable is generated from that name, this should be taken
|
||||||
|
into account if we want to use it somewhere in the HAProxy configuration.
|
||||||
|
The above mentioned span context is used in the 'inject' and 'extract' keywords.
|
||||||
|
|
||||||
|
Let's look a little at the example test/fe-be (configurations are in the
|
||||||
|
test/fe and test/be directories, 'fe' is here the abbreviation for frontend
|
||||||
|
and 'be' for backend). In case we have the 'rate-limit' set to a value less
|
||||||
|
than 100.0, then distributed tracing will not be started with each new HTTP
|
||||||
|
request. It also means that the span context will not be delivered (via the
|
||||||
|
HTTP header) to the backend HAProxy process. The 'rate-limit' on the backend
|
||||||
|
HAProxy must be set to 100.0, but because the frontend HAProxy does not send
|
||||||
|
a span context every time, all such cases will cause an error to be reported
|
||||||
|
on the backend server. Therefore, the 'hard-errors' option must be set on the
|
||||||
|
backend server, so that processing on that stream is stopped as soon as the
|
||||||
|
first error occurs. Such cases will slow down the backend server's response
|
||||||
|
a bit (in the example in question it is about 3%).
|
||||||
298
addons/ot/README-func
Normal file
298
addons/ot/README-func
Normal file
|
|
@ -0,0 +1,298 @@
|
||||||
|
Here I will write down some specifics of certain parts of the source, these are
|
||||||
|
just some of my thoughts and clues and they are probably not too important for
|
||||||
|
a wider audience.
|
||||||
|
|
||||||
|
src/parser.c
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
The first thing to run when starting the HAProxy is the flt_ot_parse() function
|
||||||
|
which actually parses the filter configuration.
|
||||||
|
|
||||||
|
In case of correct configuration, the function returns ERR_NONE (or 0), while
|
||||||
|
in case of incorrect configuration it returns the combination of ERR_* flags
|
||||||
|
(ERR_NONE here does not belong to that bit combination because its value is 0).
|
||||||
|
|
||||||
|
One of the parameters of the function is <char **err> in which an error message
|
||||||
|
can be returned, if it exists. In that case the return value of the function
|
||||||
|
should have some of the ERR_* flags set.
|
||||||
|
|
||||||
|
Let's look at an example of the following filter configuration what the function
|
||||||
|
call sequence looks like.
|
||||||
|
|
||||||
|
Filter configuration line:
|
||||||
|
filter opentracing [id <id>] config <file>
|
||||||
|
|
||||||
|
Function call sequence:
|
||||||
|
flt_ot_parse(<err>) {
|
||||||
|
/* Initialization of the filter configuration data. */
|
||||||
|
flt_ot_conf_init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setting the filter name. */
|
||||||
|
flt_ot_parse_keyword(<err>) {
|
||||||
|
flt_ot_parse_strdup(<err>) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setting the filter configuration file name. */
|
||||||
|
flt_ot_parse_keyword(<err>) {
|
||||||
|
flt_ot_parse_strdup(<err>) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checking the configuration of the filter. */
|
||||||
|
flt_ot_parse_cfg(<err>) {
|
||||||
|
flt_ot_parse_cfg_tracer() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
flt_ot_post_parse_cfg_tracer() {
|
||||||
|
}
|
||||||
|
flt_ot_parse_cfg_group() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
flt_ot_post_parse_cfg_group() {
|
||||||
|
}
|
||||||
|
flt_ot_parse_cfg_scope() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
flt_ot_post_parse_cfg_scope() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Checking the filter configuration is actually much more complicated, only the
|
||||||
|
name of the main function flt_ot_parse_cfg() that does it is listed here.
|
||||||
|
|
||||||
|
All functions that use the <err> parameter should set the error status using
|
||||||
|
that pointer. All other functions (actually these are all functions called
|
||||||
|
by the flt_ot_parse_cfg() function) should set the error message using the
|
||||||
|
ha_warning()/ha_alert() HAProxy functions. Of course, the return value (the
|
||||||
|
mentioned combination of ERR_* bits) is set in all these functions and it
|
||||||
|
indicates whether the filter configuration is correct or not.
|
||||||
|
|
||||||
|
|
||||||
|
src/group.c
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
The OT filter allows the use of groups within which one or more 'ot-scope'
|
||||||
|
declarations can be found. These groups can be used using several HAProxy
|
||||||
|
rules, more precisely 'http-request', 'http-response', 'tcp-request',
|
||||||
|
'tcp-response' and 'http-after-response' rules.
|
||||||
|
|
||||||
|
Configuration example for the specified rules:
|
||||||
|
<rule> ot-group <filter-id> <group-name> [ { if | unless } <condition> ]
|
||||||
|
|
||||||
|
Parsing each of these rules is performed by the flt_ot_group_parse() function.
|
||||||
|
After parsing the configuration, its verification is performed via the
|
||||||
|
flt_ot_group_check() function. One parsing function and one configuration
|
||||||
|
check function are called for each defined rule.
|
||||||
|
|
||||||
|
flt_ot_group_parse(<err>) {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
flt_ot_group_check() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
When deinitializing the module, the function flt_ot_group_release() is called
|
||||||
|
(which is actually an release_ptr callback function from one of the above
|
||||||
|
rules). One callback function is called for each defined rule.
|
||||||
|
|
||||||
|
flt_ot_group_release() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
src/filter.c
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
After parsing and checking the configuration, the flt_ot_check() function is
|
||||||
|
called which associates the 'ot-group' and 'ot-scope' definitions with their
|
||||||
|
declarations. This procedure concludes the configuration of the OT filter and
|
||||||
|
after that its initialization is possible.
|
||||||
|
|
||||||
|
flt_ops.check = flt_ot_check;
|
||||||
|
flt_ot_check() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
The initialization of the OT filter is done via the flt_ot_init() callback
|
||||||
|
function. In this function the OpenTracing API library is also initialized.
|
||||||
|
It is also possible to initialize for each thread individually, but nothing
|
||||||
|
is being done here for now.
|
||||||
|
|
||||||
|
flt_ops.init = flt_ot_init;
|
||||||
|
flt_ot_init() {
|
||||||
|
flt_ot_cli_init() {
|
||||||
|
}
|
||||||
|
/* Initialization of the OpenTracing API. */
|
||||||
|
ot_init(<err>) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flt_ops.init_per_thread = flt_ot_init_per_thread;
|
||||||
|
flt_ot_init_per_thread() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
After the filter instance is created and attached to the stream, the
|
||||||
|
flt_ot_attach() function is called. In this function a new OT runtime
|
||||||
|
context is created, and flags are set that define which analyzers are used.
|
||||||
|
|
||||||
|
flt_ops.attach = flt_ot_attach;
|
||||||
|
flt_ot_attach() {
|
||||||
|
/* In case OT is disabled, nothing is done on this stream further. */
|
||||||
|
flt_ot_runtime_context_init(<err>) {
|
||||||
|
flt_ot_pool_alloc() {
|
||||||
|
}
|
||||||
|
/* Initializing and setting the variable 'sess.ot.uuid'. */
|
||||||
|
if (flt_ot_var_register(<err>) != -1) {
|
||||||
|
flt_ot_var_set(<err>) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
When a stream is started, this function is called. At the moment, nothing
|
||||||
|
is being done in it.
|
||||||
|
|
||||||
|
flt_ops.stream_start = flt_ot_stream_start;
|
||||||
|
flt_ot_stream_start() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Channel analyzers are called when executing individual filter events.
|
||||||
|
For each of the four analyzer functions, the events associated with them
|
||||||
|
are listed.
|
||||||
|
|
||||||
|
Events:
|
||||||
|
- 1 'on-client-session-start'
|
||||||
|
- 15 'on-server-session-start'
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
flt_ops.channel_start_analyze = flt_ot_channel_start_analyze;
|
||||||
|
flt_ot_channel_start_analyze() {
|
||||||
|
flt_ot_event_run() {
|
||||||
|
/* Run event. */
|
||||||
|
flt_ot_scope_run() {
|
||||||
|
/* Processing of all ot-scopes defined for the current event. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Events:
|
||||||
|
- 2 'on-frontend-tcp-request'
|
||||||
|
- 4 'on-http-body-request'
|
||||||
|
- 5 'on-frontend-http-request'
|
||||||
|
- 6 'on-switching-rules-request'
|
||||||
|
- 7 'on-backend-tcp-request'
|
||||||
|
- 8 'on-backend-http-request'
|
||||||
|
- 9 'on-process-server-rules-request'
|
||||||
|
- 10 'on-http-process-request'
|
||||||
|
- 11 'on-tcp-rdp-cookie-request'
|
||||||
|
- 12 'on-process-sticking-rules-request
|
||||||
|
- 16 'on-tcp-response'
|
||||||
|
- 18 'on-process-store-rules-response'
|
||||||
|
- 19 'on-http-response'
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
flt_ops.channel_pre_analyze = flt_ot_channel_pre_analyze;
|
||||||
|
flt_ot_channel_pre_analyze() {
|
||||||
|
flt_ot_event_run() {
|
||||||
|
/* Run event. */
|
||||||
|
flt_ot_scope_run() {
|
||||||
|
/* Processing of all ot-scopes defined for the current event. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Events:
|
||||||
|
- 3 'on-http-wait-request'
|
||||||
|
- 17 'on-http-wait-response'
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
flt_ops.channel_post_analyze = flt_ot_channel_post_analyze;
|
||||||
|
flt_ot_channel_post_analyze() {
|
||||||
|
flt_ot_event_run() {
|
||||||
|
/* Run event. */
|
||||||
|
flt_ot_scope_run() {
|
||||||
|
/* Processing of all ot-scopes defined for the current event. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Events:
|
||||||
|
- 13 'on-client-session-end'
|
||||||
|
- 14 'on-server-unavailable'
|
||||||
|
- 20 'on-server-session-end'
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
flt_ops.channel_end_analyze = flt_ot_channel_end_analyze;
|
||||||
|
flt_ot_channel_end_analyze() {
|
||||||
|
flt_ot_event_run() {
|
||||||
|
/* Run event. */
|
||||||
|
flt_ot_scope_run() {
|
||||||
|
/* Processing of all ot-scopes defined for the current event. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In case the backend server does not work, event 'on-server-unavailable'
|
||||||
|
is called here before event 'on-client-session-end'. */
|
||||||
|
if ('on-server-unavailable') {
|
||||||
|
flt_ot_event_run() {
|
||||||
|
/* Run event. */
|
||||||
|
flt_ot_scope_run() {
|
||||||
|
/* Processing of all ot-scopes defined for the current event. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
After the stream has stopped, this function is called. At the moment, nothing
|
||||||
|
is being done in it.
|
||||||
|
|
||||||
|
flt_ops.stream_stop = flt_ot_stream_stop;
|
||||||
|
flt_ot_stream_stop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Then, before the instance filter is detached from the stream, the following
|
||||||
|
function is called. It deallocates the runtime context of the OT filter.
|
||||||
|
|
||||||
|
flt_ops.detach = flt_ot_detach;
|
||||||
|
flt_ot_detach() {
|
||||||
|
flt_ot_runtime_context_free() {
|
||||||
|
flt_ot_pool_free() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Module deinitialization begins with deinitialization of individual threads
|
||||||
|
(as many threads as configured for the HAProxy process). Because nothing
|
||||||
|
special is connected to the process threads, nothing is done in this function.
|
||||||
|
|
||||||
|
flt_ops.deinit_per_thread = flt_ot_deinit_per_thread;
|
||||||
|
flt_ot_deinit_per_thread() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
For this function see the above description related to the src/group.c file.
|
||||||
|
|
||||||
|
flt_ot_group_release() {
|
||||||
|
}
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Module deinitialization ends with the flt_ot_deinit() function, in which all
|
||||||
|
memory occupied by module operation (and OpenTracing API operation, of course)
|
||||||
|
is freed.
|
||||||
|
|
||||||
|
flt_ops.deinit = flt_ot_deinit;
|
||||||
|
flt_ot_deinit() {
|
||||||
|
ot_close() {
|
||||||
|
}
|
||||||
|
flt_ot_conf_free() {
|
||||||
|
}
|
||||||
|
}
|
||||||
25
addons/ot/README-pool
Normal file
25
addons/ot/README-pool
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
Used pools:
|
||||||
|
|
||||||
|
-------------------------------+-----------------------------+-----------------------------
|
||||||
|
head / name | size | define
|
||||||
|
-------------------------------+-----------------------------+-----------------------------
|
||||||
|
pool_head_ buffer | global.tune.bufsize = 16384 | USE_POOL_BUFFER
|
||||||
|
pool_head_ trash | 32 + 16384 | USE_TRASH_CHUNK
|
||||||
|
-------------------------------+-----------------------------+-----------------------------
|
||||||
|
pool_head_ ot_scope_span | 96 | USE_POOL_OT_SCOPE_SPAN
|
||||||
|
pool_head_ ot_scope_context | 64 | USE_POOL_OT_SCOPE_CONTEXT
|
||||||
|
pool_head_ ot_runtime_context | 128 | USE_POOL_OT_RUNTIME_CONTEXT
|
||||||
|
pool_head_ ot_span_context | 96 | USE_POOL_OT_SPAN_CONTEXT
|
||||||
|
-------------------------------+-----------------------------+-----------------------------
|
||||||
|
|
||||||
|
By defining individual definitions in file include/config.h, it is possible to
|
||||||
|
switch individual pools on / off. If a particular pool is not used, memory is
|
||||||
|
used in a 'normal' way instead, using malloc()/free() functions.
|
||||||
|
|
||||||
|
This is made only from the aspect of debugging the program, i.e. comparing the
|
||||||
|
speed of operation using different methods of working with memory.
|
||||||
|
|
||||||
|
In general, it would be better to use memory pools, due to less fragmentation
|
||||||
|
of memory space after long operation of the program. The speed of operation
|
||||||
|
is similar to when using standard allocation functions (when testing it was
|
||||||
|
shown that pool use was fast by about 1%).
|
||||||
50
addons/ot/include/cli.h
Normal file
50
addons/ot/include/cli.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_CLI_H_
|
||||||
|
#define _OPENTRACING_CLI_H_
|
||||||
|
|
||||||
|
#define FLT_OT_CLI_CMD "flt-ot"
|
||||||
|
|
||||||
|
#define FLT_OT_CLI_LOGGING_OFF "off"
|
||||||
|
#define FLT_OT_CLI_LOGGING_ON "on"
|
||||||
|
#define FLT_OT_CLI_LOGGING_NOLOGNORM "dontlog-normal"
|
||||||
|
#define FLT_OT_CLI_LOGGING_STATE(a) ((a) & FLT_OT_LOGGING_ON) ? (((a) & FLT_OT_LOGGING_NOLOGNORM) ? "enabled, " FLT_OT_CLI_LOGGING_NOLOGNORM : "enabled") : "disabled"
|
||||||
|
|
||||||
|
#define FLT_OT_CLI_MSG_CAT(a) ((a) == NULL) ? "" : (a), ((a) == NULL) ? "" : "\n"
|
||||||
|
|
||||||
|
enum FLT_OT_LOGGING_enum {
|
||||||
|
FLT_OT_LOGGING_OFF = 0,
|
||||||
|
FLT_OT_LOGGING_ON = 1 << 0,
|
||||||
|
FLT_OT_LOGGING_NOLOGNORM = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void flt_ot_cli_init(void);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_CLI_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
228
addons/ot/include/conf.h
Normal file
228
addons/ot/include/conf.h
Normal file
|
|
@ -0,0 +1,228 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_CONF_H_
|
||||||
|
#define _OPENTRACING_CONF_H_
|
||||||
|
|
||||||
|
#define FLT_OT_CONF(f) ((struct flt_ot_conf *)FLT_CONF(f))
|
||||||
|
#define FLT_OT_CONF_HDR_FMT "%p:{ { '%.*s' %zu %d } "
|
||||||
|
#define FLT_OT_CONF_HDR_ARGS(a,b) (a), (int)(a)->b##_len, (a)->b, (a)->b##_len, (a)->cfg_line
|
||||||
|
#define FLT_OT_STR_HDR_ARGS(a,b) (a)->b, (a)->b##_len
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_SAMPLE_EXPR(f,a) \
|
||||||
|
FLT_OT_DBG(3, "%s%p:{ '%s' %p }", (f), (a), (a)->value, (a)->expr)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_SAMPLE(f,a) \
|
||||||
|
FLT_OT_DBG(3, "%s%p:{ '%s' '%s' %s %d }", \
|
||||||
|
(f), (a), (a)->key, (a)->value, flt_ot_list_debug(&((a)->exprs)), (a)->num_exprs)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_STR(f,a) \
|
||||||
|
FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "}", FLT_OT_CONF_HDR_ARGS(a, str))
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_CONTEXT(f,a) \
|
||||||
|
FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "0x%02hhx }", FLT_OT_CONF_HDR_ARGS(a, id), (a)->flags)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_SPAN(f,a) \
|
||||||
|
FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "'%s' %zu %d '%s' %zu %hhu 0x%02hhx %s %s %s }", \
|
||||||
|
FLT_OT_CONF_HDR_ARGS(a, id), FLT_OT_STR_HDR_ARGS(a, ref_id), (a)->ref_type, \
|
||||||
|
FLT_OT_STR_HDR_ARGS(a, ctx_id), (a)->flag_root, (a)->ctx_flags, flt_ot_list_debug(&((a)->tags)), \
|
||||||
|
flt_ot_list_debug(&((a)->logs)), flt_ot_list_debug(&((a)->baggages)))
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_SCOPE(f,a) \
|
||||||
|
FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "%hhu %d %s %p %s %s %s }", \
|
||||||
|
FLT_OT_CONF_HDR_ARGS(a, id), (a)->flag_used, (a)->event, flt_ot_list_debug(&((a)->acls)), \
|
||||||
|
(a)->cond, flt_ot_list_debug(&((a)->contexts)), flt_ot_list_debug(&((a)->spans)), \
|
||||||
|
flt_ot_list_debug(&((a)->finish)))
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_GROUP(f,a) \
|
||||||
|
FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "%hhu %s }", \
|
||||||
|
FLT_OT_CONF_HDR_ARGS(a, id), (a)->flag_used, flt_ot_list_debug(&((a)->ph_scopes)))
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_PH(f,a) \
|
||||||
|
FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "%p }", FLT_OT_CONF_HDR_ARGS(a, id), (a)->ptr)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF_TRACER(f,a) \
|
||||||
|
FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "'%s' %p '%s' %p %u %hhu %hhu 0x%02hhx %p:%s 0x%08x %s %s %s }", \
|
||||||
|
FLT_OT_CONF_HDR_ARGS(a, id), (a)->config, (a)->cfgbuf, (a)->plugin, (a)->tracer, (a)->rate_limit, (a)->flag_harderr, \
|
||||||
|
(a)->flag_disabled, (a)->logging, &((a)->proxy_log), flt_ot_list_debug(&((a)->proxy_log.loggers)), (a)->analyzers, \
|
||||||
|
flt_ot_list_debug(&((a)->acls)), flt_ot_list_debug(&((a)->ph_groups)), flt_ot_list_debug(&((a)->ph_scopes)))
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CONF(f,a) \
|
||||||
|
FLT_OT_DBG(3, "%s%p:{ %p '%s' '%s' %p %s %s }", \
|
||||||
|
(f), (a), (a)->proxy, (a)->id, (a)->cfg_file, (a)->tracer, \
|
||||||
|
flt_ot_list_debug(&((a)->groups)), flt_ot_list_debug(&((a)->scopes)))
|
||||||
|
|
||||||
|
#define FLT_OT_STR_HDR(a) \
|
||||||
|
struct { \
|
||||||
|
char *a; \
|
||||||
|
size_t a##_len; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FLT_OT_CONF_HDR(a) \
|
||||||
|
struct { \
|
||||||
|
FLT_OT_STR_HDR(a); \
|
||||||
|
int cfg_line; \
|
||||||
|
struct list list; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct flt_ot_conf_hdr {
|
||||||
|
FLT_OT_CONF_HDR(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flt_ot_conf_sample->exprs */
|
||||||
|
struct flt_ot_conf_sample_expr {
|
||||||
|
FLT_OT_CONF_HDR(value); /* The sample value. */
|
||||||
|
struct sample_expr *expr; /* The sample expression. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flt_ot_conf_span->tags
|
||||||
|
* flt_ot_conf_span->logs
|
||||||
|
* flt_ot_conf_span->baggages
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_sample {
|
||||||
|
FLT_OT_CONF_HDR(key); /* The sample name. */
|
||||||
|
char *value; /* The sample content. */
|
||||||
|
struct list exprs; /* Used to chain sample expressions. */
|
||||||
|
int num_exprs; /* Number of defined expressions. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flt_ot_conf_scope->finish */
|
||||||
|
struct flt_ot_conf_str {
|
||||||
|
FLT_OT_CONF_HDR(str); /* String content/length. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flt_ot_conf_scope->contexts */
|
||||||
|
struct flt_ot_conf_context {
|
||||||
|
FLT_OT_CONF_HDR(id); /* The name of the context. */
|
||||||
|
uint8_t flags; /* The type of storage from which the span context is extracted. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flt_ot_conf_scope->spans */
|
||||||
|
struct flt_ot_conf_span {
|
||||||
|
FLT_OT_CONF_HDR(id); /* The name of the span. */
|
||||||
|
FLT_OT_STR_HDR(ref_id); /* The reference name, if used. */
|
||||||
|
int ref_type; /* The reference type. */
|
||||||
|
FLT_OT_STR_HDR(ctx_id); /* The span context name, if used. */
|
||||||
|
uint8_t ctx_flags; /* The type of storage used for the span context. */
|
||||||
|
bool flag_root; /* Whether this is a root span. */
|
||||||
|
struct list tags; /* The set of key:value tags. */
|
||||||
|
struct list logs; /* The set of key:value logs. */
|
||||||
|
struct list baggages; /* The set of key:value baggage items. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flt_ot_conf_scope {
|
||||||
|
FLT_OT_CONF_HDR(id); /* The scope name. */
|
||||||
|
bool flag_used; /* The indication that the scope is being used. */
|
||||||
|
int event; /* FLT_OT_EVENT_* */
|
||||||
|
struct list acls; /* ACLs declared on this scope. */
|
||||||
|
struct acl_cond *cond; /* ACL condition to meet. */
|
||||||
|
struct list contexts; /* Declared contexts. */
|
||||||
|
struct list spans; /* Declared spans. */
|
||||||
|
struct list finish; /* The list of spans to be finished. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flt_ot_conf_group {
|
||||||
|
FLT_OT_CONF_HDR(id); /* The group name. */
|
||||||
|
bool flag_used; /* The indication that the group is being used. */
|
||||||
|
struct list ph_scopes; /* List of all used scopes. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flt_ot_conf_ph {
|
||||||
|
FLT_OT_CONF_HDR(id); /* The scope/group name. */
|
||||||
|
void *ptr; /* Pointer to real placeholder structure. */
|
||||||
|
};
|
||||||
|
#define flt_ot_conf_ph_group flt_ot_conf_ph
|
||||||
|
#define flt_ot_conf_ph_scope flt_ot_conf_ph
|
||||||
|
|
||||||
|
struct flt_ot_conf_tracer {
|
||||||
|
FLT_OT_CONF_HDR(id); /* The tracer name. */
|
||||||
|
char *config; /* The OpenTracing configuration file name. */
|
||||||
|
char *cfgbuf; /* The OpenTracing configuration. */
|
||||||
|
char *plugin; /* The OpenTracing plugin library file name. */
|
||||||
|
struct otc_tracer *tracer; /* The OpenTracing tracer handle. */
|
||||||
|
uint32_t rate_limit; /* [0 2^32-1] <-> [0.0 100.0] */
|
||||||
|
bool flag_harderr; /* [0 1] */
|
||||||
|
bool flag_disabled; /* [0 1] */
|
||||||
|
uint8_t logging; /* [0 1 3] */
|
||||||
|
struct proxy proxy_log; /* The log server list. */
|
||||||
|
uint analyzers; /* Defined channel analyzers. */
|
||||||
|
struct list acls; /* ACLs declared on this tracer. */
|
||||||
|
struct list ph_groups; /* List of all used groups. */
|
||||||
|
struct list ph_scopes; /* List of all used scopes. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flt_ot_counters {
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
struct {
|
||||||
|
bool flag_used; /* Whether this event is used. */
|
||||||
|
uint64_t htx[2]; /* htx_is_empty() function result counter. */
|
||||||
|
} event[FLT_OT_EVENT_MAX];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint64_t disabled[2]; /* How many times stream processing is disabled. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The OpenTracing filter configuration. */
|
||||||
|
struct flt_ot_conf {
|
||||||
|
struct proxy *proxy; /* Proxy owning the filter. */
|
||||||
|
char *id; /* The OpenTracing filter id. */
|
||||||
|
char *cfg_file; /* The OpenTracing filter configuration file name. */
|
||||||
|
struct flt_ot_conf_tracer *tracer; /* There can only be one tracer. */
|
||||||
|
struct list groups; /* List of all available groups. */
|
||||||
|
struct list scopes; /* List of all available scopes. */
|
||||||
|
struct flt_ot_counters cnt; /* Various counters related to filter operation. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define flt_ot_conf_ph_group_free flt_ot_conf_ph_free
|
||||||
|
#define flt_ot_conf_ph_scope_free flt_ot_conf_ph_free
|
||||||
|
|
||||||
|
struct flt_ot_conf_ph *flt_ot_conf_ph_init(const char *id, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_ph_free(struct flt_ot_conf_ph **ptr);
|
||||||
|
struct flt_ot_conf_sample_expr *flt_ot_conf_sample_expr_init(const char *id, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_sample_expr_free(struct flt_ot_conf_sample_expr **ptr);
|
||||||
|
struct flt_ot_conf_sample *flt_ot_conf_sample_init(char **args, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_sample_free(struct flt_ot_conf_sample **ptr);
|
||||||
|
struct flt_ot_conf_str *flt_ot_conf_str_init(const char *id, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_str_free(struct flt_ot_conf_str **ptr);
|
||||||
|
struct flt_ot_conf_context *flt_ot_conf_context_init(const char *id, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_context_free(struct flt_ot_conf_context **ptr);
|
||||||
|
struct flt_ot_conf_span *flt_ot_conf_span_init(const char *id, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_span_free(struct flt_ot_conf_span **ptr);
|
||||||
|
struct flt_ot_conf_scope *flt_ot_conf_scope_init(const char *id, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_scope_free(struct flt_ot_conf_scope **ptr);
|
||||||
|
struct flt_ot_conf_group *flt_ot_conf_group_init(const char *id, int linenum, struct list *head, char **err);
|
||||||
|
void flt_ot_conf_group_free(struct flt_ot_conf_group **ptr);
|
||||||
|
struct flt_ot_conf_tracer *flt_ot_conf_tracer_init(const char *id, int linenum, char **err);
|
||||||
|
void flt_ot_conf_tracer_free(struct flt_ot_conf_tracer **ptr);
|
||||||
|
struct flt_ot_conf *flt_ot_conf_init(struct proxy *px);
|
||||||
|
void flt_ot_conf_free(struct flt_ot_conf **ptr);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_CONF_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
46
addons/ot/include/config.h
Normal file
46
addons/ot/include/config.h
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_CONFIG_H_
|
||||||
|
#define _OPENTRACING_CONFIG_H_
|
||||||
|
|
||||||
|
#undef DEBUG_OT_SYSTIME
|
||||||
|
#define USE_POOL_BUFFER
|
||||||
|
#define USE_POOL_OT_SPAN_CONTEXT
|
||||||
|
#define USE_POOL_OT_SCOPE_SPAN
|
||||||
|
#define USE_POOL_OT_SCOPE_CONTEXT
|
||||||
|
#define USE_POOL_OT_RUNTIME_CONTEXT
|
||||||
|
#define USE_TRASH_CHUNK
|
||||||
|
|
||||||
|
#define FLT_OT_ID_MAXLEN 64
|
||||||
|
#define FLT_OT_MAXTAGS 8
|
||||||
|
#define FLT_OT_MAXBAGGAGES 8
|
||||||
|
#define FLT_OT_RATE_LIMIT_MAX 100.0
|
||||||
|
#define FLT_OT_DEBUG_LEVEL 0b00001111
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_CONFIG_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
104
addons/ot/include/debug.h
Normal file
104
addons/ot/include/debug.h
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_DEBUG_H_
|
||||||
|
#define _OPENTRACING_DEBUG_H_
|
||||||
|
|
||||||
|
#ifdef DEBUG_FULL
|
||||||
|
# define DEBUG_OT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
# ifdef DEBUG_OT_SYSTIME
|
||||||
|
# define FLT_OT_DBG_FMT(f) "[% 2d] %ld.%06ld [" FLT_OT_SCOPE "]: " f, tid, date.tv_sec, date.tv_usec
|
||||||
|
# else
|
||||||
|
# define FLT_OT_DBG_FMT(f) "[% 2d] %11.6f [" FLT_OT_SCOPE "]: " f, tid, FLT_OT_TV_UDIFF(&(flt_ot_debug.start), &date) / 1e6
|
||||||
|
# endif
|
||||||
|
# define FLT_OT_DBG_INDENT " "
|
||||||
|
# define FLT_OT_DBG(l,f, ...) \
|
||||||
|
do { \
|
||||||
|
if (!(l) || (flt_ot_debug.level & (1 << (l)))) \
|
||||||
|
(void)fprintf(stderr, FLT_OT_DBG_FMT("%.*s" f "\n"), \
|
||||||
|
flt_ot_dbg_indent_level, FLT_OT_DBG_INDENT, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
# define FLT_OT_FUNC(f, ...) do { FLT_OT_DBG(1, "%s(" f ") {", __func__, ##__VA_ARGS__); flt_ot_dbg_indent_level += 3; } while (0)
|
||||||
|
# define FLT_OT_RETURN(a) do { flt_ot_dbg_indent_level -= 3; FLT_OT_DBG(1, "}"); return a; } while (0)
|
||||||
|
# define FLT_OT_RETURN_EX(a,t,f) do { flt_ot_dbg_indent_level -= 3; { t _r = (a); FLT_OT_DBG(1, "} = " f, _r); return _r; } } while (0)
|
||||||
|
# define FLT_OT_RETURN_INT(a) FLT_OT_RETURN_EX((a), int, "%d")
|
||||||
|
# define FLT_OT_RETURN_PTR(a) FLT_OT_RETURN_EX((a), void *, "%p")
|
||||||
|
# define FLT_OT_DBG_IFDEF(a,b) a
|
||||||
|
# define FLT_OT_DBG_ARGS(a, ...) a, ##__VA_ARGS__
|
||||||
|
# define FLT_OT_DBG_BUF(a,b) do { FLT_OT_DBG((a), "%p:{ %zu %p %zu %zu }", (b), (b)->size, (b)->area, (b)->data, (b)->head); } while (0)
|
||||||
|
|
||||||
|
struct flt_ot_debug {
|
||||||
|
#ifndef DEBUG_OT_SYSTIME
|
||||||
|
struct timeval start;
|
||||||
|
#endif
|
||||||
|
uint8_t level;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern THREAD_LOCAL int flt_ot_dbg_indent_level;
|
||||||
|
extern struct flt_ot_debug flt_ot_debug;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define FLT_OT_DBG(...) while (0)
|
||||||
|
# define FLT_OT_FUNC(...) while (0)
|
||||||
|
# define FLT_OT_RETURN(a) return a
|
||||||
|
# define FLT_OT_RETURN_EX(a,t,f) return a
|
||||||
|
# define FLT_OT_RETURN_INT(a) return a
|
||||||
|
# define FLT_OT_RETURN_PTR(a) return a
|
||||||
|
# define FLT_OT_DBG_IFDEF(a,b) b
|
||||||
|
# define FLT_OT_DBG_ARGS(...)
|
||||||
|
# define FLT_OT_DBG_BUF(a,b) while (0)
|
||||||
|
#endif /* DEBUG_OT */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ON | NOLOGNORM |
|
||||||
|
* -----+-----------+-------------
|
||||||
|
* 0 | 0 | no log
|
||||||
|
* 0 | 1 | no log
|
||||||
|
* 1 | 0 | log all
|
||||||
|
* 1 | 1 | log errors
|
||||||
|
* -----+-----------+-------------
|
||||||
|
*/
|
||||||
|
#define FLT_OT_LOG(l,f, ...) \
|
||||||
|
do { \
|
||||||
|
if (!(conf->tracer->logging & FLT_OT_LOGGING_ON)) \
|
||||||
|
FLT_OT_DBG(3, "NOLOG[%d]: [" FLT_OT_SCOPE "]: [%s] " f, (l), conf->id, ##__VA_ARGS__); \
|
||||||
|
else if ((conf->tracer->logging & FLT_OT_LOGGING_NOLOGNORM) && ((l) > LOG_ERR)) \
|
||||||
|
FLT_OT_DBG(2, "NOLOG[%d]: [" FLT_OT_SCOPE "]: [%s] " f, (l), conf->id, ##__VA_ARGS__); \
|
||||||
|
else { \
|
||||||
|
send_log(&(conf->tracer->proxy_log), (l), "[" FLT_OT_SCOPE "]: [%s] " f "\n", conf->id, ##__VA_ARGS__); \
|
||||||
|
\
|
||||||
|
FLT_OT_DBG(1, "LOG[%d]: %s", (l), logline); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_DEBUG_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
107
addons/ot/include/define.h
Normal file
107
addons/ot/include/define.h
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_DEFINE_H_
|
||||||
|
#define _OPENTRACING_DEFINE_H_
|
||||||
|
|
||||||
|
#define FLT_OT_DEREF(a,m,v) (((a) != NULL) ? (a)->m : (v))
|
||||||
|
#define FLT_OT_DDEREF(a,m,v) ((((a) != NULL) && (*(a) != NULL)) ? (*(a))->m : (v))
|
||||||
|
#define FLT_OT_TABLESIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
#define FLT_OT_IN_RANGE(v,a,b) (((v) >= (a)) && ((v) <= (b)))
|
||||||
|
#define FLT_OT_DPTR_ARGS(a) (a), ((a) == NULL) ? NULL : *(a)
|
||||||
|
#define FLT_OT_ARG_ISVALID(n) ((args[n] != NULL) && *args[n])
|
||||||
|
#define FLT_OT_TV_UDIFF(a,b) (((b)->tv_sec - (a)->tv_sec) * 1000000 + (b)->tv_usec - (a)->tv_usec)
|
||||||
|
#define FLT_OT_U32_FLOAT(a,b) ((a) * (double)(b) / UINT32_MAX)
|
||||||
|
#define FLT_OT_FLOAT_U32(a,b) ((uint32_t)((a) / (double)(b) * UINT32_MAX + 0.5))
|
||||||
|
|
||||||
|
#define FLT_OT_STR_DASH_72 "------------------------------------------------------------------------"
|
||||||
|
#define FLT_OT_STR_DASH_78 FLT_OT_STR_DASH_72 "------"
|
||||||
|
#define FLT_OT_STR_FLAG_YN(a) (a) ? "yes" : "no"
|
||||||
|
|
||||||
|
#define FLT_OT_STR_SIZE(a) (sizeof(a) - 1)
|
||||||
|
#define FLT_OT_STR_ADDRSIZE(a) (a), FLT_OT_STR_SIZE(a)
|
||||||
|
#define FLT_OT_STR_ISVALID(a) (((a) != NULL) && (*(a) != '\0'))
|
||||||
|
#define FLT_OT_STR_CMP(S,s,l) (((l) == FLT_OT_STR_SIZE(S)) && (memcmp((s), FLT_OT_STR_ADDRSIZE(S)) == 0))
|
||||||
|
#define FLT_OT_STR_ELLIPSIS(a,n) do { if ((a) != NULL) { if ((n) > 0) (a)[(n) - 1] = '\0'; if ((n) > 3) (a)[(n) - 2] = (a)[(n) - 3] = (a)[(n) - 4] = '.'; } } while (0)
|
||||||
|
#define FLT_OT_NIBBLE_TO_HEX(a) ((a) + (((a) < 10) ? '0' : ('a' - 10)))
|
||||||
|
|
||||||
|
#define FLT_OT_FREE(a) do { if ((a) != NULL) OTC_DBG_FREE(a); } while (0)
|
||||||
|
#define FLT_OT_FREE_VOID(a) do { if ((a) != NULL) OTC_DBG_FREE((void *)(a)); } while (0)
|
||||||
|
#define FLT_OT_FREE_CLEAR(a) do { if ((a) != NULL) { OTC_DBG_FREE(a); (a) = NULL; } } while (0)
|
||||||
|
#define FLT_OT_STRDUP(s) OTC_DBG_STRDUP(s)
|
||||||
|
#define FLT_OT_STRNDUP(s,n) OTC_DBG_STRNDUP((s), (n))
|
||||||
|
#define FLT_OT_CALLOC(n,e) OTC_DBG_CALLOC((n), (e))
|
||||||
|
#define FLT_OT_MALLOC(s) OTC_DBG_MALLOC((s))
|
||||||
|
#define FLT_OT_MEMINFO() OTC_DBG_MEMINFO()
|
||||||
|
|
||||||
|
#define FLT_OT_RUN_ONCE(f) do { static bool __f = 1; if (__f) { __f = 0; f; } } while (0)
|
||||||
|
|
||||||
|
#define FLT_OT_LIST_ISVALID(a) (((a) != NULL) && ((a)->n != NULL) && ((a)->p != NULL))
|
||||||
|
#define FLT_OT_LIST_DEL(a) do { if (FLT_OT_LIST_ISVALID(a)) LIST_DELETE(a); } while (0)
|
||||||
|
#define FLT_OT_LIST_DESTROY(t,h) \
|
||||||
|
do { \
|
||||||
|
struct flt_ot_conf_##t *_ptr, *_back; \
|
||||||
|
\
|
||||||
|
if (!FLT_OT_LIST_ISVALID(h) || LIST_ISEMPTY(h)) \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
FLT_OT_DBG(2, "- deleting " #t " list %s", flt_ot_list_debug(h)); \
|
||||||
|
\
|
||||||
|
list_for_each_entry_safe(_ptr, _back, (h), list) \
|
||||||
|
flt_ot_conf_##t##_free(&_ptr); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define FLT_OT_BUFFER_THR(b,m,n,p) \
|
||||||
|
static THREAD_LOCAL char b[m][n]; \
|
||||||
|
static THREAD_LOCAL size_t __idx = 0; \
|
||||||
|
char *p = b[__idx]; \
|
||||||
|
__idx = (__idx + 1) % (m)
|
||||||
|
|
||||||
|
#define FLT_OT_ERR(f, ...) \
|
||||||
|
do { \
|
||||||
|
if ((err != NULL) && (*err == NULL)) { \
|
||||||
|
(void)memprintf(err, f, ##__VA_ARGS__); \
|
||||||
|
\
|
||||||
|
FLT_OT_DBG(3, "%d err: '%s'", __LINE__, *err); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define FLT_OT_ERR_APPEND(f, ...) \
|
||||||
|
do { \
|
||||||
|
if (err != NULL) \
|
||||||
|
(void)memprintf(err, f, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
#define FLT_OT_ERR_FREE(p) \
|
||||||
|
do { \
|
||||||
|
if ((p) == NULL) \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
FLT_OT_DBG(0, "%s:%d: ERROR: %s", __func__, __LINE__, (p)); \
|
||||||
|
FLT_OT_FREE_CLEAR(p); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_DEFINE_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
120
addons/ot/include/event.h
Normal file
120
addons/ot/include/event.h
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_EVENT_H_
|
||||||
|
#define _OPENTRACING_EVENT_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This must be defined in order for macro FLT_OT_EVENT_DEFINES
|
||||||
|
* and structure flt_ot_event_data to have the correct contents.
|
||||||
|
*/
|
||||||
|
#define AN_REQ_NONE 0
|
||||||
|
#define AN_REQ_CLIENT_SESS_START 0
|
||||||
|
#define AN_REQ_SERVER_UNAVAILABLE 0
|
||||||
|
#define AN_REQ_CLIENT_SESS_END 0
|
||||||
|
#define AN_RES_SERVER_SESS_START 0
|
||||||
|
#define AN_RES_SERVER_SESS_END 0
|
||||||
|
#define SMP_VAL_FE_ 0
|
||||||
|
#define SMP_VAL_BE_ 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event names are selected to be somewhat compatible with the SPOE filter,
|
||||||
|
* from which the following names are taken:
|
||||||
|
* - on-client-session -> on-client-session-start
|
||||||
|
* - on-frontend-tcp-request
|
||||||
|
* - on-frontend-http-request
|
||||||
|
* - on-backend-tcp-request
|
||||||
|
* - on-backend-http-request
|
||||||
|
* - on-server-session -> on-server-session-start
|
||||||
|
* - on-tcp-response
|
||||||
|
* - on-http-response
|
||||||
|
*
|
||||||
|
* FLT_OT_EVENT_NONE is used as an index for 'ot-scope' sections that do not
|
||||||
|
* have an event defined. The 'ot-scope' sections thus defined can be used
|
||||||
|
* within the 'ot-group' section.
|
||||||
|
*
|
||||||
|
* A description of the macro arguments can be found in the structure
|
||||||
|
* flt_ot_event_data definition
|
||||||
|
*/
|
||||||
|
#define FLT_OT_EVENT_DEFINES \
|
||||||
|
FLT_OT_EVENT_DEF( NONE, REQ, , , 0, "") \
|
||||||
|
FLT_OT_EVENT_DEF( CLIENT_SESS_START, REQ, CON_ACC, , 1, "on-client-session-start") \
|
||||||
|
FLT_OT_EVENT_DEF( INSPECT_FE, REQ, REQ_CNT, , 1, "on-frontend-tcp-request") \
|
||||||
|
FLT_OT_EVENT_DEF( WAIT_HTTP, REQ, , , 1, "on-http-wait-request") \
|
||||||
|
FLT_OT_EVENT_DEF( HTTP_BODY, REQ, , , 1, "on-http-body-request") \
|
||||||
|
FLT_OT_EVENT_DEF( HTTP_PROCESS_FE, REQ, HRQ_HDR, , 1, "on-frontend-http-request") \
|
||||||
|
FLT_OT_EVENT_DEF( SWITCHING_RULES, REQ, , , 1, "on-switching-rules-request") \
|
||||||
|
FLT_OT_EVENT_DEF( INSPECT_BE, REQ, REQ_CNT, REQ_CNT, 1, "on-backend-tcp-request") \
|
||||||
|
FLT_OT_EVENT_DEF( HTTP_PROCESS_BE, REQ, HRQ_HDR, HRQ_HDR, 1, "on-backend-http-request") \
|
||||||
|
/* FLT_OT_EVENT_DEF( HTTP_TARPIT, REQ, , , 1, "on-http-tarpit-request") */ \
|
||||||
|
FLT_OT_EVENT_DEF( SRV_RULES, REQ, , , 1, "on-process-server-rules-request") \
|
||||||
|
FLT_OT_EVENT_DEF( HTTP_INNER, REQ, , , 1, "on-http-process-request") \
|
||||||
|
FLT_OT_EVENT_DEF( PRST_RDP_COOKIE, REQ, , , 1, "on-tcp-rdp-cookie-request") \
|
||||||
|
FLT_OT_EVENT_DEF( STICKING_RULES, REQ, , , 1, "on-process-sticking-rules-request") \
|
||||||
|
FLT_OT_EVENT_DEF( CLIENT_SESS_END, REQ, , , 0, "on-client-session-end") \
|
||||||
|
FLT_OT_EVENT_DEF(SERVER_UNAVAILABLE, REQ, , , 0, "on-server-unavailable") \
|
||||||
|
\
|
||||||
|
FLT_OT_EVENT_DEF( SERVER_SESS_START, RES, , SRV_CON, 0, "on-server-session-start") \
|
||||||
|
FLT_OT_EVENT_DEF( INSPECT, RES, RES_CNT, RES_CNT, 0, "on-tcp-response") \
|
||||||
|
FLT_OT_EVENT_DEF( WAIT_HTTP, RES, , , 1, "on-http-wait-response") \
|
||||||
|
FLT_OT_EVENT_DEF( STORE_RULES, RES, , , 1, "on-process-store-rules-response") \
|
||||||
|
FLT_OT_EVENT_DEF( HTTP_PROCESS_BE, RES, HRS_HDR, HRS_HDR, 1, "on-http-response") \
|
||||||
|
FLT_OT_EVENT_DEF( SERVER_SESS_END, RES, , , 0, "on-server-session-end")
|
||||||
|
|
||||||
|
enum FLT_OT_EVENT_enum {
|
||||||
|
#define FLT_OT_EVENT_DEF(a,b,c,d,e,f) FLT_OT_EVENT_##b##_##a,
|
||||||
|
FLT_OT_EVENT_DEFINES
|
||||||
|
FLT_OT_EVENT_MAX
|
||||||
|
#undef FLT_OT_EVENT_DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FLT_OT_EVENT_SAMPLE_enum {
|
||||||
|
FLT_OT_EVENT_SAMPLE_TAG = 0,
|
||||||
|
FLT_OT_EVENT_SAMPLE_LOG,
|
||||||
|
FLT_OT_EVENT_SAMPLE_BAGGAGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flt_ot_event_data {
|
||||||
|
uint an_bit; /* Used channel analyser. */
|
||||||
|
uint smp_opt_dir; /* Fetch direction (request/response). */
|
||||||
|
uint smp_val_fe; /* Valid FE fetch location. */
|
||||||
|
uint smp_val_be; /* Valid BE fetch location. */
|
||||||
|
bool flag_http_inject; /* Span context injection allowed. */
|
||||||
|
const char *name; /* Filter event name. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flt_ot_conf_scope;
|
||||||
|
|
||||||
|
|
||||||
|
extern const struct flt_ot_event_data flt_ot_event_data[FLT_OT_EVENT_MAX];
|
||||||
|
|
||||||
|
|
||||||
|
int flt_ot_scope_run(struct stream *s, struct filter *f, struct channel *chn, struct flt_ot_conf_scope *conf_scope, const struct timespec *ts, uint dir, char **err);
|
||||||
|
int flt_ot_event_run(struct stream *s, struct filter *f, struct channel *chn, int event, char **err);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_EVENT_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
68
addons/ot/include/filter.h
Normal file
68
addons/ot/include/filter.h
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_FILTER_H_
|
||||||
|
#define _OPENTRACING_FILTER_H_
|
||||||
|
|
||||||
|
#define FLT_OT_FMT_NAME "'" FLT_OT_OPT_NAME "' : "
|
||||||
|
#define FLT_OT_FMT_TYPE "'filter' : "
|
||||||
|
#define FLT_OT_VAR_UUID "sess", "ot", "uuid"
|
||||||
|
#define FLT_OT_ALERT(f, ...) ha_alert(FLT_OT_FMT_TYPE FLT_OT_FMT_NAME f "\n", ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define FLT_OT_CONDITION_IF "if"
|
||||||
|
#define FLT_OT_CONDITION_UNLESS "unless"
|
||||||
|
|
||||||
|
enum FLT_OT_RET_enum {
|
||||||
|
FLT_OT_RET_ERROR = -1,
|
||||||
|
FLT_OT_RET_WAIT = 0,
|
||||||
|
FLT_OT_RET_IGNORE = 0,
|
||||||
|
FLT_OT_RET_OK = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_LIST(d,m,p,t,v,f) \
|
||||||
|
do { \
|
||||||
|
if (LIST_ISEMPTY(&((d)->m##s))) { \
|
||||||
|
FLT_OT_DBG(3, p "- no " #m "s " t); \
|
||||||
|
} else { \
|
||||||
|
const struct flt_ot_conf_##m *v; \
|
||||||
|
\
|
||||||
|
FLT_OT_DBG(3, p "- " t " " #m "s: %s", \
|
||||||
|
flt_ot_list_debug(&((d)->m##s))); \
|
||||||
|
list_for_each_entry(v, &((d)->m##s), list) \
|
||||||
|
do { f; } while (0); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
extern const char *ot_flt_id;
|
||||||
|
extern struct flt_ops flt_ot_ops;
|
||||||
|
|
||||||
|
|
||||||
|
bool flt_ot_is_disabled(const struct filter *f FLT_OT_DBG_ARGS(, int event));
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_FILTER_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
61
addons/ot/include/group.h
Normal file
61
addons/ot/include/group.h
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_GROUP_H_
|
||||||
|
#define _OPENTRACING_GROUP_H_
|
||||||
|
|
||||||
|
#define FLT_OT_ACTION_GROUP "ot-group"
|
||||||
|
|
||||||
|
enum FLT_OT_ARG_enum {
|
||||||
|
FLT_OT_ARG_FILTER_ID = 0,
|
||||||
|
FLT_OT_ARG_GROUP_ID,
|
||||||
|
|
||||||
|
FLT_OT_ARG_FLT_CONF = 0,
|
||||||
|
FLT_OT_ARG_CONF,
|
||||||
|
FLT_OT_ARG_GROUP,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A description of the macro arguments can be found in the structure
|
||||||
|
* flt_ot_group_data definition
|
||||||
|
*/
|
||||||
|
#define FLT_OT_GROUP_DEFINES \
|
||||||
|
FLT_OT_GROUP_DEF(ACT_F_TCP_REQ_CON, SMP_VAL_FE_CON_ACC, SMP_OPT_DIR_REQ) \
|
||||||
|
FLT_OT_GROUP_DEF(ACT_F_TCP_REQ_SES, SMP_VAL_FE_SES_ACC, SMP_OPT_DIR_REQ) \
|
||||||
|
FLT_OT_GROUP_DEF(ACT_F_TCP_REQ_CNT, SMP_VAL_FE_REQ_CNT, SMP_OPT_DIR_REQ) \
|
||||||
|
FLT_OT_GROUP_DEF(ACT_F_TCP_RES_CNT, SMP_VAL_BE_RES_CNT, SMP_OPT_DIR_RES) \
|
||||||
|
FLT_OT_GROUP_DEF(ACT_F_HTTP_REQ, SMP_VAL_FE_HRQ_HDR, SMP_OPT_DIR_REQ) \
|
||||||
|
FLT_OT_GROUP_DEF(ACT_F_HTTP_RES, SMP_VAL_BE_HRS_HDR, SMP_OPT_DIR_RES)
|
||||||
|
|
||||||
|
struct flt_ot_group_data {
|
||||||
|
enum act_from act_from; /* ACT_F_* */
|
||||||
|
uint smp_val; /* Valid FE/BE fetch location. */
|
||||||
|
uint smp_opt_dir; /* Fetch direction (request/response). */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_GROUP_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
41
addons/ot/include/http.h
Normal file
41
addons/ot/include/http.h
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_HTTP_H_
|
||||||
|
#define _OPENTRACING_HTTP_H_
|
||||||
|
|
||||||
|
#ifndef DEBUG_OT
|
||||||
|
# define flt_ot_http_headers_dump(...) while (0)
|
||||||
|
#else
|
||||||
|
void flt_ot_http_headers_dump(const struct channel *chn);
|
||||||
|
#endif
|
||||||
|
struct otc_text_map *flt_ot_http_headers_get(struct channel *chn, const char *prefix, size_t len, char **err);
|
||||||
|
int flt_ot_http_header_set(struct channel *chn, const char *prefix, const char *name, const char *value, char **err);
|
||||||
|
int flt_ot_http_headers_remove(struct channel *chn, const char *prefix, char **err);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_HTTP_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
66
addons/ot/include/include.h
Normal file
66
addons/ot/include/include.h
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_INCLUDE_H_
|
||||||
|
#define _OPENTRACING_INCLUDE_H_
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <haproxy/api.h>
|
||||||
|
#include <haproxy/cfgparse.h>
|
||||||
|
#include <haproxy/acl.h>
|
||||||
|
#include <haproxy/cli.h>
|
||||||
|
#include <haproxy/clock.h>
|
||||||
|
#include <haproxy/filters.h>
|
||||||
|
#include <haproxy/http_htx.h>
|
||||||
|
#include <haproxy/http_rules.h>
|
||||||
|
#include <haproxy/log.h>
|
||||||
|
#include <haproxy/proxy.h>
|
||||||
|
#include <haproxy/sample.h>
|
||||||
|
#include <haproxy/tcp_rules.h>
|
||||||
|
#include <haproxy/tools.h>
|
||||||
|
#include <haproxy/vars.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "define.h"
|
||||||
|
#include "cli.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "group.h"
|
||||||
|
#include "http.h"
|
||||||
|
#include "opentracing.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "pool.h"
|
||||||
|
#include "scope.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "vars.h"
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_INCLUDE_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
86
addons/ot/include/opentracing.h
Normal file
86
addons/ot/include/opentracing.h
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_OT_H_
|
||||||
|
#define _OPENTRACING_OT_H_
|
||||||
|
|
||||||
|
#include <opentracing-c-wrapper/include.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define FLT_OT_VSET(p,t,v) \
|
||||||
|
do { (p)->type = otc_value_##t; (p)->value.t##_value = (v); } while (0)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_TEXT_MAP(a) \
|
||||||
|
FLT_OT_DBG(3, "%p:{ %p %p %zu/%zu %hhu }", \
|
||||||
|
(a), (a)->key, (a)->value, (a)->count, (a)->size, (a)->is_dynamic)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_TEXT_CARRIER(a,f) \
|
||||||
|
FLT_OT_DBG(3, "%p:{ { %p %p %zu/%zu %hhu } %p }", \
|
||||||
|
(a), (a)->text_map.key, (a)->text_map.value, (a)->text_map.count, \
|
||||||
|
(a)->text_map.size, (a)->text_map.is_dynamic, (a)->f)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_CUSTOM_CARRIER(a,f) \
|
||||||
|
FLT_OT_DBG(3, "%p:{ { %p %zu %hhu } %p }", \
|
||||||
|
(a), (a)->binary_data.data, (a)->binary_data.size, \
|
||||||
|
(a)->binary_data.is_dynamic, (a)->f)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_SPAN_CONTEXT(a) \
|
||||||
|
FLT_OT_DBG(3, "%p:{ %" PRId64 " %p %p }", (a), (a)->idx, (a)->span, (a)->destroy)
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DEBUG_OT
|
||||||
|
# define ot_debug() while (0)
|
||||||
|
# define ot_text_map_show(...) while (0)
|
||||||
|
#else
|
||||||
|
void ot_text_map_show(const struct otc_text_map *text_map);
|
||||||
|
void ot_debug(void);
|
||||||
|
#endif
|
||||||
|
int ot_init(struct otc_tracer **tracer, const char *plugin, char **err);
|
||||||
|
int ot_start(struct otc_tracer *tracer, const char *cfgbuf, char **err);
|
||||||
|
struct otc_span *ot_span_init(struct otc_tracer *tracer, const char *operation_name, const struct timespec *ts_steady, const struct timespec *ts_system, int ref_type, int ref_ctx_idx, const struct otc_span *ref_span, const struct otc_tag *tags, int num_tags, char **err);
|
||||||
|
int ot_span_tag(struct otc_span *span, const struct otc_tag *tags, int num_tags);
|
||||||
|
int ot_span_log(struct otc_span *span, const struct otc_log_field *log_fields, int num_fields);
|
||||||
|
int ot_span_set_baggage(struct otc_span *span, const struct otc_text_map *baggage);
|
||||||
|
struct otc_span_context *ot_inject_http_headers(struct otc_tracer *tracer, const struct otc_span *span, struct otc_http_headers_writer *carrier, char **err);
|
||||||
|
struct otc_span_context *ot_extract_http_headers(struct otc_tracer *tracer, struct otc_http_headers_reader *carrier, const struct otc_text_map *text_map, char **err);
|
||||||
|
void ot_span_finish(struct otc_span **span, const struct timespec *ts_finish, const struct timespec *log_ts, const char *log_key, const char *log_value, ...);
|
||||||
|
void ot_close(struct otc_tracer **tracer);
|
||||||
|
|
||||||
|
/* Unused code. */
|
||||||
|
struct otc_span *ot_span_init_va(struct otc_tracer *tracer, const char *operation_name, const struct timespec *ts_steady, const struct timespec *ts_system, int ref_type, int ref_ctx_idx, const struct otc_span *ref_span, char **err, const char *tag_key, const char *tag_value, ...);
|
||||||
|
int ot_span_tag_va(struct otc_span *span, const char *key, int type, ...);
|
||||||
|
int ot_span_log_va(struct otc_span *span, const char *key, const char *value, ...);
|
||||||
|
int ot_span_log_fmt(struct otc_span *span, const char *key, const char *format, ...) __attribute__ ((format(printf, 3, 4)));
|
||||||
|
int ot_span_set_baggage_va(struct otc_span *span, const char *key, const char *value, ...);
|
||||||
|
struct otc_text_map *ot_span_baggage_va(const struct otc_span *span, const char *key, ...);
|
||||||
|
struct otc_span_context *ot_inject_text_map(struct otc_tracer *tracer, const struct otc_span *span, struct otc_text_map_writer *carrier);
|
||||||
|
struct otc_span_context *ot_inject_binary(struct otc_tracer *tracer, const struct otc_span *span, struct otc_custom_carrier_writer *carrier);
|
||||||
|
struct otc_span_context *ot_extract_text_map(struct otc_tracer *tracer, struct otc_text_map_reader *carrier, const struct otc_text_map *text_map);
|
||||||
|
struct otc_span_context *ot_extract_binary(struct otc_tracer *tracer, struct otc_custom_carrier_reader *carrier, const struct otc_binary_data *binary_data);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_OT_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
172
addons/ot/include/parser.h
Normal file
172
addons/ot/include/parser.h
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_PARSER_H_
|
||||||
|
#define _OPENTRACING_PARSER_H_
|
||||||
|
|
||||||
|
#define FLT_OT_SCOPE "OT"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* filter FLT_OT_OPT_NAME FLT_OT_OPT_FILTER_ID <FLT_OT_OPT_FILTER_ID_DEFAULT> FLT_OT_OPT_CONFIG <file>
|
||||||
|
*/
|
||||||
|
#define FLT_OT_OPT_NAME "opentracing"
|
||||||
|
#define FLT_OT_OPT_FILTER_ID "id"
|
||||||
|
#define FLT_OT_OPT_FILTER_ID_DEFAULT "ot-filter"
|
||||||
|
#define FLT_OT_OPT_CONFIG "config"
|
||||||
|
|
||||||
|
#define FLT_OT_PARSE_SECTION_TRACER_ID "ot-tracer"
|
||||||
|
#define FLT_OT_PARSE_SECTION_GROUP_ID "ot-group"
|
||||||
|
#define FLT_OT_PARSE_SECTION_SCOPE_ID "ot-scope"
|
||||||
|
|
||||||
|
#define FLT_OT_PARSE_SPAN_ROOT "root"
|
||||||
|
#define FLT_OT_PARSE_SPAN_REF_CHILD "child-of"
|
||||||
|
#define FLT_OT_PARSE_SPAN_REF_FOLLOWS "follows-from"
|
||||||
|
#define FLT_OT_PARSE_CTX_AUTONAME "-"
|
||||||
|
#define FLT_OT_PARSE_CTX_IGNORE_NAME '-'
|
||||||
|
#define FLT_OT_PARSE_CTX_USE_HEADERS "use-headers"
|
||||||
|
#define FLT_OT_PARSE_CTX_USE_VARS "use-vars"
|
||||||
|
#define FLT_OT_PARSE_OPTION_HARDERR "hard-errors"
|
||||||
|
#define FLT_OT_PARSE_OPTION_DISABLED "disabled"
|
||||||
|
#define FLT_OT_PARSE_OPTION_NOLOGNORM "dontlog-normal"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A description of the macro arguments can be found in the structure
|
||||||
|
* flt_ot_parse_data definition
|
||||||
|
*/
|
||||||
|
#define FLT_OT_PARSE_TRACER_DEFINES \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( ID, 0, CHAR, 2, 2, "ot-tracer", " <name>") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( ACL, 0, CHAR, 3, 0, "acl", " <name> <criterion> [flags] [operator] <value> ...") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( LOG, 0, CHAR, 2, 0, "log", " { global | <addr> [len <len>] [format <fmt>] <facility> [<level> [<minlevel>]] }") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( CONFIG, 0, NONE, 2, 2, "config", " <file>") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( PLUGIN, 0, NONE, 2, 2, "plugin", " <file>") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( GROUPS, 0, NONE, 2, 0, "groups", " <name> ...") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( SCOPES, 0, NONE, 2, 0, "scopes", " <name> ...") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( RATE_LIMIT, 0, NONE, 2, 2, "rate-limit", " <value>") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF( OPTION, 0, NONE, 2, 2, "option", " { disabled | dontlog-normal | hard-errors }") \
|
||||||
|
FLT_OT_PARSE_TRACER_DEF(DEBUG_LEVEL, 0, NONE, 2, 2, "debug-level", " <value>")
|
||||||
|
|
||||||
|
#define FLT_OT_PARSE_GROUP_DEFINES \
|
||||||
|
FLT_OT_PARSE_GROUP_DEF( ID, 0, CHAR, 2, 2, "ot-group", " <name>") \
|
||||||
|
FLT_OT_PARSE_GROUP_DEF(SCOPES, 0, NONE, 2, 0, "scopes", " <name> ...")
|
||||||
|
|
||||||
|
#ifdef USE_OT_VARS
|
||||||
|
# define FLT_OT_PARSE_SCOPE_INJECT_HELP " <name-prefix> [use-vars] [use-headers]"
|
||||||
|
# define FLT_OT_PARSE_SCOPE_EXTRACT_HELP " <name-prefix> [use-vars | use-headers]"
|
||||||
|
#else
|
||||||
|
# define FLT_OT_PARSE_SCOPE_INJECT_HELP " <name-prefix> [use-headers]"
|
||||||
|
# define FLT_OT_PARSE_SCOPE_EXTRACT_HELP " <name-prefix> [use-headers]"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case the possibility of working with OpenTracing context via HAProxyu
|
||||||
|
* variables is not used, args_max member of the structure flt_ot_parse_data
|
||||||
|
* should be reduced for 'inject' keyword. However, this is not critical
|
||||||
|
* because in this case the 'use-vars' argument cannot be entered anyway,
|
||||||
|
* so I will not complicate it here with additional definitions.
|
||||||
|
*/
|
||||||
|
#define FLT_OT_PARSE_SCOPE_DEFINES \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( ID, 0, CHAR, 2, 2, "ot-scope", " <name>") \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( SPAN, 0, NONE, 2, 5, "span", " <name> [<reference>] [root]") \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( TAG, 1, NONE, 3, 0, "tag", " <name> <sample> ...") \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( LOG, 1, NONE, 3, 0, "log", " <name> <sample> ...") \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF(BAGGAGE, 1, VAR, 3, 0, "baggage", " <name> <sample> ...") \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( INJECT, 1, CTX, 2, 4, "inject", FLT_OT_PARSE_SCOPE_INJECT_HELP) \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF(EXTRACT, 0, CTX, 2, 3, "extract", FLT_OT_PARSE_SCOPE_EXTRACT_HELP) \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( FINISH, 0, NONE, 2, 0, "finish", " <name> ...") \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( ACL, 0, CHAR, 3, 0, "acl", " <name> <criterion> [flags] [operator] <value> ...") \
|
||||||
|
FLT_OT_PARSE_SCOPE_DEF( EVENT, 0, NONE, 2, 0, "event", " <name> [{ if | unless } <condition>]")
|
||||||
|
|
||||||
|
enum FLT_OT_PARSE_INVCHAR_enum {
|
||||||
|
FLT_OT_PARSE_INVALID_NONE,
|
||||||
|
FLT_OT_PARSE_INVALID_CHAR,
|
||||||
|
FLT_OT_PARSE_INVALID_DOM,
|
||||||
|
FLT_OT_PARSE_INVALID_CTX,
|
||||||
|
FLT_OT_PARSE_INVALID_VAR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FLT_OT_PARSE_TRACER_enum {
|
||||||
|
#define FLT_OT_PARSE_TRACER_DEF(a,b,c,d,e,f,g) FLT_OT_PARSE_TRACER_##a,
|
||||||
|
FLT_OT_PARSE_TRACER_DEFINES
|
||||||
|
#undef FLT_OT_PARSE_TRACER_DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FLT_OT_PARSE_GROUP_enum {
|
||||||
|
#define FLT_OT_PARSE_GROUP_DEF(a,b,c,d,e,f,g) FLT_OT_PARSE_GROUP_##a,
|
||||||
|
FLT_OT_PARSE_GROUP_DEFINES
|
||||||
|
#undef FLT_OT_PARSE_GROUP_DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FLT_OT_PARSE_SCOPE_enum {
|
||||||
|
#define FLT_OT_PARSE_SCOPE_DEF(a,b,c,d,e,f,g) FLT_OT_PARSE_SCOPE_##a,
|
||||||
|
FLT_OT_PARSE_SCOPE_DEFINES
|
||||||
|
#undef FLT_OT_PARSE_SCOPE_DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FLT_OT_CTX_USE_enum {
|
||||||
|
FLT_OT_CTX_USE_VARS = 1 << 0,
|
||||||
|
FLT_OT_CTX_USE_HEADERS = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct flt_ot_parse_data {
|
||||||
|
int keyword; /* Keyword index. */
|
||||||
|
bool flag_check_id; /* Whether the group ID must be defined for the keyword. */
|
||||||
|
int check_name; /* Checking allowed characters in the name. */
|
||||||
|
int args_min; /* The minimum number of arguments required. */
|
||||||
|
int args_max; /* The maximum number of arguments allowed. */
|
||||||
|
const char *name; /* Keyword name. */
|
||||||
|
const char *usage; /* Usage text to be printed in case of an error. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FLT_OT_PARSE_WARNING(f, ...) \
|
||||||
|
ha_warning("parsing [%s:%d] : " FLT_OT_FMT_TYPE FLT_OT_FMT_NAME "'" f "'\n", ##__VA_ARGS__);
|
||||||
|
#define FLT_OT_PARSE_ALERT(f, ...) \
|
||||||
|
do { \
|
||||||
|
ha_alert("parsing [%s:%d] : " FLT_OT_FMT_TYPE FLT_OT_FMT_NAME "'" f "'\n", ##__VA_ARGS__); \
|
||||||
|
\
|
||||||
|
retval |= ERR_ABORT | ERR_ALERT; \
|
||||||
|
} while (0)
|
||||||
|
#define FLT_OT_POST_PARSE_ALERT(f, ...) \
|
||||||
|
FLT_OT_PARSE_ALERT(f, flt_ot_current_config->cfg_file, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define FLT_OT_PARSE_ERR(e,f, ...) \
|
||||||
|
do { \
|
||||||
|
if (*(e) == NULL) \
|
||||||
|
(void)memprintf((e), f, ##__VA_ARGS__); \
|
||||||
|
\
|
||||||
|
retval |= ERR_ABORT | ERR_ALERT; \
|
||||||
|
} while (0)
|
||||||
|
#define FLT_OT_PARSE_IFERR_ALERT() \
|
||||||
|
do { \
|
||||||
|
if (err == NULL) \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
FLT_OT_PARSE_ALERT("%s", file, linenum, err); \
|
||||||
|
FLT_OT_ERR_FREE(err); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_PARSER_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
39
addons/ot/include/pool.h
Normal file
39
addons/ot/include/pool.h
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_POOL_H_
|
||||||
|
#define _OPENTRACING_POOL_H_
|
||||||
|
|
||||||
|
void *flt_ot_pool_alloc(struct pool_head *pool, size_t size, bool flag_clear, char **err);
|
||||||
|
void *flt_ot_pool_strndup(struct pool_head *pool, const char *s, size_t size, char **err);
|
||||||
|
void flt_ot_pool_free(struct pool_head *pool, void **ptr);
|
||||||
|
|
||||||
|
struct buffer *flt_ot_trash_alloc(bool flag_clear, char **err);
|
||||||
|
void flt_ot_trash_free(struct buffer **ptr);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_POOL_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
126
addons/ot/include/scope.h
Normal file
126
addons/ot/include/scope.h
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_SCOPE_H_
|
||||||
|
#define _OPENTRACING_SCOPE_H_
|
||||||
|
|
||||||
|
#define FLT_OT_SCOPE_SPAN_FINISH_REQ "*req*"
|
||||||
|
#define FLT_OT_SCOPE_SPAN_FINISH_RES "*res*"
|
||||||
|
#define FLT_OT_SCOPE_SPAN_FINISH_ALL "*"
|
||||||
|
|
||||||
|
#define FLT_OT_RT_CTX(a) ((struct flt_ot_runtime_context *)(a))
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_SCOPE_SPAN(f,a) \
|
||||||
|
FLT_OT_DBG(3, "%s%p:{ '%s' %zu %u %hhu %p %d %p %p }", \
|
||||||
|
(f), (a), FLT_OT_STR_HDR_ARGS(a, id), (a)->smp_opt_dir, \
|
||||||
|
(a)->flag_finish, (a)->span, (a)->ref_type, (a)->ref_span, (a)->ref_ctx)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_SCOPE_CONTEXT(f,a) \
|
||||||
|
FLT_OT_DBG(3, "%s%p:{ '%s' %zu %u %hhu %p }", \
|
||||||
|
(f), (a), FLT_OT_STR_HDR_ARGS(a, id), (a)->smp_opt_dir, \
|
||||||
|
(a)->flag_finish, (a)->context)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_SCOPE_DATA(f,a) \
|
||||||
|
FLT_OT_DBG(3, "%s%p:{ %p %d %p %p %d }", \
|
||||||
|
(f), (a), (a)->tags, (a)->num_tags, (a)->baggage, (a)->log_fields, (a)->num_log_fields)
|
||||||
|
|
||||||
|
#define FLT_OT_DBG_RUNTIME_CONTEXT(f,a) \
|
||||||
|
FLT_OT_DBG(3, "%s%p:{ %p %p '%s' %hhu %hhu 0x%02hhx 0x%08x %s %s }", \
|
||||||
|
(f), (a), (a)->stream, (a)->filter, (a)->uuid, (a)->flag_harderr, \
|
||||||
|
(a)->flag_disabled, (a)->logging, (a)->analyzers, flt_ot_list_debug(&((a)->spans)), \
|
||||||
|
flt_ot_list_debug(&((a)->contexts)))
|
||||||
|
|
||||||
|
#define FLT_OT_CONST_STR_HDR(a) \
|
||||||
|
struct { \
|
||||||
|
const char *a; \
|
||||||
|
size_t a##_len; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct flt_ot_scope_data {
|
||||||
|
struct otc_tag tags[FLT_OT_MAXTAGS]; /* Defined tags. */
|
||||||
|
int num_tags; /* The number of tags used. */
|
||||||
|
struct otc_text_map *baggage; /* Defined baggage. */
|
||||||
|
struct otc_log_field log_fields[OTC_MAXLOGFIELDS]; /* Defined logs. */
|
||||||
|
int num_log_fields; /* The number of log fields used. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flt_ot_runtime_context->spans */
|
||||||
|
struct flt_ot_scope_span {
|
||||||
|
FLT_OT_CONST_STR_HDR(id); /* The span operation name/len. */
|
||||||
|
uint smp_opt_dir; /* SMP_OPT_DIR_RE(Q|S) */
|
||||||
|
bool flag_finish; /* Whether the span is marked for completion. */
|
||||||
|
struct otc_span *span; /* The current span. */
|
||||||
|
otc_span_reference_type_t ref_type; /* Span reference type. */
|
||||||
|
struct otc_span *ref_span; /* Span to which the current span refers. */
|
||||||
|
struct otc_span_context *ref_ctx; /* Span context to which the current span refers. */
|
||||||
|
struct list list; /* Used to chain this structure. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flt_ot_runtime_context->contexts */
|
||||||
|
struct flt_ot_scope_context {
|
||||||
|
FLT_OT_CONST_STR_HDR(id); /* The span context name/len. */
|
||||||
|
uint smp_opt_dir; /* SMP_OPT_DIR_RE(Q|S) */
|
||||||
|
bool flag_finish; /* Whether the span context is marked for completion. */
|
||||||
|
struct otc_span_context *context; /* The current span context. */
|
||||||
|
struct list list; /* Used to chain this structure. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The runtime filter context attached to a stream. */
|
||||||
|
struct flt_ot_runtime_context {
|
||||||
|
struct stream *stream; /* The stream to which the filter is attached. */
|
||||||
|
struct filter *filter; /* The OpenTracing filter. */
|
||||||
|
char uuid[40]; /* Randomly generated UUID. */
|
||||||
|
bool flag_harderr; /* [0 1] */
|
||||||
|
bool flag_disabled; /* [0 1] */
|
||||||
|
uint8_t logging; /* [0 1 3] */
|
||||||
|
uint analyzers; /* Executed channel analyzers. */
|
||||||
|
struct list spans; /* The scope spans. */
|
||||||
|
struct list contexts; /* The scope contexts. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DEBUG_OT
|
||||||
|
# define flt_ot_pools_info() while (0)
|
||||||
|
#else
|
||||||
|
void flt_ot_pools_info(void);
|
||||||
|
#endif
|
||||||
|
struct flt_ot_runtime_context *flt_ot_runtime_context_init(struct stream *s, struct filter *f, char **err);
|
||||||
|
void flt_ot_runtime_context_free(struct filter *f);
|
||||||
|
|
||||||
|
struct flt_ot_scope_span *flt_ot_scope_span_init(struct flt_ot_runtime_context *rt_ctx, const char *id, size_t id_len, otc_span_reference_type_t ref_type, const char *ref_id, size_t ref_id_len, uint dir, char **err);
|
||||||
|
void flt_ot_scope_span_free(struct flt_ot_scope_span **ptr);
|
||||||
|
struct flt_ot_scope_context *flt_ot_scope_context_init(struct flt_ot_runtime_context *rt_ctx, struct otc_tracer *tracer, const char *id, size_t id_len, const struct otc_text_map *text_map, uint dir, char **err);
|
||||||
|
void flt_ot_scope_context_free(struct flt_ot_scope_context **ptr);
|
||||||
|
void flt_ot_scope_data_free(struct flt_ot_scope_data *ptr);
|
||||||
|
|
||||||
|
int flt_ot_scope_finish_mark(const struct flt_ot_runtime_context *rt_ctx, const char *id, size_t id_len);
|
||||||
|
void flt_ot_scope_finish_marked(const struct flt_ot_runtime_context *rt_ctx, const struct timespec *ts_finish);
|
||||||
|
void flt_ot_scope_free_unused(struct flt_ot_runtime_context *rt_ctx, struct channel *chn);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_SCOPE_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
109
addons/ot/include/util.h
Normal file
109
addons/ot/include/util.h
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_UTIL_H_
|
||||||
|
#define _OPENTRACING_UTIL_H_
|
||||||
|
|
||||||
|
#define HTTP_METH_STR_OPTIONS "OPTIONS"
|
||||||
|
#define HTTP_METH_STR_GET "GET"
|
||||||
|
#define HTTP_METH_STR_HEAD "HEAD"
|
||||||
|
#define HTTP_METH_STR_POST "POST"
|
||||||
|
#define HTTP_METH_STR_PUT "PUT"
|
||||||
|
#define HTTP_METH_STR_DELETE "DELETE"
|
||||||
|
#define HTTP_METH_STR_TRACE "TRACE"
|
||||||
|
#define HTTP_METH_STR_CONNECT "CONNECT"
|
||||||
|
|
||||||
|
/* Defined in include/haproxy/channel-t.h. */
|
||||||
|
#define FLT_OT_AN_DEFINES \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_INSPECT_FE) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_WAIT_HTTP) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_HTTP_BODY) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_HTTP_PROCESS_FE) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_SWITCHING_RULES) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_INSPECT_BE) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_HTTP_PROCESS_BE) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_HTTP_TARPIT) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_SRV_RULES) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_HTTP_INNER) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_PRST_RDP_COOKIE) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_STICKING_RULES) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_HTTP_XFER_BODY) \
|
||||||
|
FLT_OT_AN_DEF(AN_REQ_WAIT_CLI) \
|
||||||
|
FLT_OT_AN_DEF(AN_RES_INSPECT) \
|
||||||
|
FLT_OT_AN_DEF(AN_RES_WAIT_HTTP) \
|
||||||
|
FLT_OT_AN_DEF(AN_RES_STORE_RULES) \
|
||||||
|
FLT_OT_AN_DEF(AN_RES_HTTP_PROCESS_BE) \
|
||||||
|
FLT_OT_AN_DEF(AN_RES_HTTP_PROCESS_FE) \
|
||||||
|
FLT_OT_AN_DEF(AN_RES_HTTP_XFER_BODY) \
|
||||||
|
FLT_OT_AN_DEF(AN_RES_WAIT_CLI)
|
||||||
|
|
||||||
|
#define FLT_OT_PROXIES_LIST_START() \
|
||||||
|
do { \
|
||||||
|
struct flt_conf *fconf; \
|
||||||
|
struct proxy *px; \
|
||||||
|
\
|
||||||
|
for (px = proxies_list; px != NULL; px = px->next) \
|
||||||
|
list_for_each_entry(fconf, &(px->filter_configs), list) \
|
||||||
|
if (fconf->id == ot_flt_id) { \
|
||||||
|
struct flt_ot_conf *conf = fconf->conf;
|
||||||
|
#define FLT_OT_PROXIES_LIST_END() \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
# define FLT_OT_ARGS_DUMP() do { if (flt_ot_debug.level & (1 << 2)) flt_ot_args_dump(args); } while (0)
|
||||||
|
#else
|
||||||
|
# define FLT_OT_ARGS_DUMP() while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DEBUG_OT
|
||||||
|
# define flt_ot_filters_dump() while (0)
|
||||||
|
#else
|
||||||
|
void flt_ot_args_dump(char **args);
|
||||||
|
void flt_ot_filters_dump(void);
|
||||||
|
const char *flt_ot_chn_label(const struct channel *chn);
|
||||||
|
const char *flt_ot_pr_mode(const struct stream *s);
|
||||||
|
const char *flt_ot_stream_pos(const struct stream *s);
|
||||||
|
const char *flt_ot_type(const struct filter *f);
|
||||||
|
const char *flt_ot_analyzer(uint an_bit);
|
||||||
|
const char *flt_ot_str_hex(const void *data, size_t size);
|
||||||
|
const char *flt_ot_str_ctrl(const void *data, size_t size);
|
||||||
|
const char *flt_ot_list_debug(const struct list *head);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ssize_t flt_ot_chunk_add(struct buffer *chk, const void *src, size_t n, char **err);
|
||||||
|
int flt_ot_args_count(char **args);
|
||||||
|
void flt_ot_args_to_str(char **args, int idx, char **str);
|
||||||
|
double flt_ot_strtod(const char *nptr, double limit_min, double limit_max, char **err);
|
||||||
|
int64_t flt_ot_strtoll(const char *nptr, int64_t limit_min, int64_t limit_max, char **err);
|
||||||
|
int flt_ot_sample_to_str(const struct sample_data *data, char *value, size_t size, char **err);
|
||||||
|
int flt_ot_sample_to_value(const char *key, const struct sample_data *data, struct otc_value *value, char **err);
|
||||||
|
int flt_ot_sample_add(struct stream *s, uint dir, struct flt_ot_conf_sample *sample, struct flt_ot_scope_data *data, int type, char **err);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_UTIL_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
55
addons/ot/include/vars.h
Normal file
55
addons/ot/include/vars.h
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef _OPENTRACING_VARS_H_
|
||||||
|
#define _OPENTRACING_VARS_H_
|
||||||
|
|
||||||
|
#define FLT_OT_VARS_SCOPE "txn"
|
||||||
|
#define FLT_OT_VAR_CTX_SIZE int8_t
|
||||||
|
#define FLT_OT_VAR_CHAR_DASH 'D'
|
||||||
|
#define FLT_OT_VAR_CHAR_SPACE 'S'
|
||||||
|
|
||||||
|
struct flt_ot_ctx {
|
||||||
|
char value[BUFSIZ];
|
||||||
|
int value_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*flt_ot_ctx_loop_cb)(struct sample *, size_t, const char *, const char *, const char *, FLT_OT_VAR_CTX_SIZE, char **, void *);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DEBUG_OT
|
||||||
|
# define flt_ot_vars_dump(...) while (0)
|
||||||
|
#else
|
||||||
|
void flt_ot_vars_dump(struct stream *s);
|
||||||
|
#endif
|
||||||
|
int flt_ot_var_register(const char *scope, const char *prefix, const char *name, char **err);
|
||||||
|
int flt_ot_var_set(struct stream *s, const char *scope, const char *prefix, const char *name, const char *value, uint opt, char **err);
|
||||||
|
int flt_ot_vars_unset(struct stream *s, const char *scope, const char *prefix, uint opt, char **err);
|
||||||
|
struct otc_text_map *flt_ot_vars_get(struct stream *s, const char *scope, const char *prefix, uint opt, char **err);
|
||||||
|
|
||||||
|
#endif /* _OPENTRACING_VARS_H_ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
397
addons/ot/src/cli.c
Normal file
397
addons/ot/src/cli.c
Normal file
|
|
@ -0,0 +1,397 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_set_msg -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* appctx -
|
||||||
|
* err -
|
||||||
|
* msg -
|
||||||
|
* cli_state -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
static void cmn_cli_set_msg(struct appctx *appctx, char *err, char *msg, int cli_state)
|
||||||
|
{
|
||||||
|
struct cli_print_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %p, %d", appctx, err, msg, cli_state);
|
||||||
|
|
||||||
|
if ((appctx == NULL) || ((err == NULL) && (msg == NULL)))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
ctx->err = (err == NULL) ? msg : err;
|
||||||
|
appctx->st0 = (ctx->err == NULL) ? CLI_ST_PROMPT : cli_state;
|
||||||
|
|
||||||
|
FLT_OT_DBG(1, "err(%d): \"%s\"", appctx->st0, ctx->err);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_parse_debug -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* payload -
|
||||||
|
* appctx -
|
||||||
|
* private -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_cli_parse_debug(char **args, char *payload, struct appctx *appctx, void *private)
|
||||||
|
{
|
||||||
|
char *err = NULL, *msg = NULL;
|
||||||
|
uint8_t value;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
|
||||||
|
|
||||||
|
FLT_OT_ARGS_DUMP();
|
||||||
|
|
||||||
|
if (FLT_OT_ARG_ISVALID(2)) {
|
||||||
|
value = flt_ot_strtoll(args[2], 0, 255, &err);
|
||||||
|
if (err == NULL) {
|
||||||
|
_HA_ATOMIC_STORE(&(flt_ot_debug.level), value);
|
||||||
|
|
||||||
|
(void)memprintf(&msg, FLT_OT_CLI_CMD " : debug level set to %hhu", value);
|
||||||
|
} else {
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = _HA_ATOMIC_LOAD(&(flt_ot_debug.level));
|
||||||
|
|
||||||
|
(void)memprintf(&msg, FLT_OT_CLI_CMD " : current debug level is %hhu", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmn_cli_set_msg(appctx, err, msg, CLI_ST_PRINT_DYNERR);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DEBUG_OT */
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_parse_disabled -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* payload -
|
||||||
|
* appctx -
|
||||||
|
* private -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_cli_parse_disabled(char **args, char *payload, struct appctx *appctx, void *private)
|
||||||
|
{
|
||||||
|
char *msg = NULL;
|
||||||
|
bool value = (uintptr_t)private;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
|
||||||
|
|
||||||
|
FLT_OT_ARGS_DUMP();
|
||||||
|
|
||||||
|
FLT_OT_PROXIES_LIST_START() {
|
||||||
|
_HA_ATOMIC_STORE(&(conf->tracer->flag_disabled), value);
|
||||||
|
|
||||||
|
(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : filter %sabled", FLT_OT_CLI_MSG_CAT(msg), value ? "dis" : "en");
|
||||||
|
} FLT_OT_PROXIES_LIST_END();
|
||||||
|
|
||||||
|
cmn_cli_set_msg(appctx, NULL, msg, CLI_ST_PRINT_DYNERR);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_parse_option -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* payload -
|
||||||
|
* appctx -
|
||||||
|
* private -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_cli_parse_option(char **args, char *payload, struct appctx *appctx, void *private)
|
||||||
|
{
|
||||||
|
char *msg = NULL;
|
||||||
|
bool value = (uintptr_t)private;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
|
||||||
|
|
||||||
|
FLT_OT_ARGS_DUMP();
|
||||||
|
|
||||||
|
FLT_OT_PROXIES_LIST_START() {
|
||||||
|
_HA_ATOMIC_STORE(&(conf->tracer->flag_harderr), value);
|
||||||
|
|
||||||
|
(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : filter set %s-errors", FLT_OT_CLI_MSG_CAT(msg), value ? "hard" : "soft");
|
||||||
|
} FLT_OT_PROXIES_LIST_END();
|
||||||
|
|
||||||
|
cmn_cli_set_msg(appctx, NULL, msg, CLI_ST_PRINT_DYNERR);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_parse_logging -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* payload -
|
||||||
|
* appctx -
|
||||||
|
* private -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_cli_parse_logging(char **args, char *payload, struct appctx *appctx, void *private)
|
||||||
|
{
|
||||||
|
char *err = NULL, *msg = NULL;
|
||||||
|
uint8_t value;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
|
||||||
|
|
||||||
|
FLT_OT_ARGS_DUMP();
|
||||||
|
|
||||||
|
if (FLT_OT_ARG_ISVALID(2)) {
|
||||||
|
if (strcasecmp(args[2], FLT_OT_CLI_LOGGING_OFF) == 0) {
|
||||||
|
value = FLT_OT_LOGGING_OFF;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(args[2], FLT_OT_CLI_LOGGING_ON) == 0) {
|
||||||
|
value = FLT_OT_LOGGING_ON;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(args[2], FLT_OT_CLI_LOGGING_NOLOGNORM) == 0) {
|
||||||
|
value = FLT_OT_LOGGING_ON | FLT_OT_LOGGING_NOLOGNORM;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(void)memprintf(&err, "'%s' : invalid value, use <" FLT_OT_CLI_LOGGING_OFF " | " FLT_OT_CLI_LOGGING_ON " | " FLT_OT_CLI_LOGGING_NOLOGNORM ">", args[2]);
|
||||||
|
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval == 0) {
|
||||||
|
FLT_OT_PROXIES_LIST_START() {
|
||||||
|
_HA_ATOMIC_STORE(&(conf->tracer->logging), value);
|
||||||
|
|
||||||
|
(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : logging is %s", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_CLI_LOGGING_STATE(value));
|
||||||
|
} FLT_OT_PROXIES_LIST_END();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FLT_OT_PROXIES_LIST_START() {
|
||||||
|
value = _HA_ATOMIC_LOAD(&(conf->tracer->logging));
|
||||||
|
|
||||||
|
(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : logging is currently %s", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_CLI_LOGGING_STATE(value));
|
||||||
|
} FLT_OT_PROXIES_LIST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
cmn_cli_set_msg(appctx, err, msg, CLI_ST_PRINT_DYNERR);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_parse_rate -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* payload -
|
||||||
|
* appctx -
|
||||||
|
* private -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_cli_parse_rate(char **args, char *payload, struct appctx *appctx, void *private)
|
||||||
|
{
|
||||||
|
char *err = NULL, *msg = NULL;
|
||||||
|
uint32_t value;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
|
||||||
|
|
||||||
|
FLT_OT_ARGS_DUMP();
|
||||||
|
|
||||||
|
if (FLT_OT_ARG_ISVALID(2)) {
|
||||||
|
value = FLT_OT_FLOAT_U32(flt_ot_strtod(args[2], 0.0, FLT_OT_RATE_LIMIT_MAX, &err), FLT_OT_RATE_LIMIT_MAX);
|
||||||
|
if (err == NULL) {
|
||||||
|
FLT_OT_PROXIES_LIST_START() {
|
||||||
|
_HA_ATOMIC_STORE(&(conf->tracer->rate_limit), value);
|
||||||
|
|
||||||
|
(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : rate limit set to %.2f", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_U32_FLOAT(value, FLT_OT_RATE_LIMIT_MAX));
|
||||||
|
} FLT_OT_PROXIES_LIST_END();
|
||||||
|
} else {
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FLT_OT_PROXIES_LIST_START() {
|
||||||
|
value = _HA_ATOMIC_LOAD(&(conf->tracer->rate_limit));
|
||||||
|
|
||||||
|
(void)memprintf(&msg, "%s%s" FLT_OT_CLI_CMD " : current rate limit is %.2f", FLT_OT_CLI_MSG_CAT(msg), FLT_OT_U32_FLOAT(value, FLT_OT_RATE_LIMIT_MAX));
|
||||||
|
} FLT_OT_PROXIES_LIST_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
cmn_cli_set_msg(appctx, err, msg, CLI_ST_PRINT_DYNERR);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_parse_status -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* payload -
|
||||||
|
* appctx -
|
||||||
|
* private -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_cli_parse_status(char **args, char *payload, struct appctx *appctx, void *private)
|
||||||
|
{
|
||||||
|
const char *nl = "";
|
||||||
|
char *msg = NULL;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %p, %p", args, payload, appctx, private);
|
||||||
|
|
||||||
|
FLT_OT_ARGS_DUMP();
|
||||||
|
flt_ot_filters_dump();
|
||||||
|
|
||||||
|
(void)memprintf(&msg, " " FLT_OT_OPT_NAME " filter status\n" FLT_OT_STR_DASH_78);
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
(void)memprintf(&msg, "%s\n debug level: 0x%02hhx\n", msg, flt_ot_debug.level);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FLT_OT_PROXIES_LIST_START() {
|
||||||
|
(void)memprintf(&msg, "%s\n%s filter %s\n", msg, nl, conf->id);
|
||||||
|
(void)memprintf(&msg, "%s configuration: %s\n", msg, conf->cfg_file);
|
||||||
|
(void)memprintf(&msg, "%s disable count: %" PRIu64 " %" PRIu64 "\n\n", msg, conf->cnt.disabled[0], conf->cnt.disabled[1]);
|
||||||
|
(void)memprintf(&msg, "%s tracer %s\n", msg, conf->tracer->id);
|
||||||
|
(void)memprintf(&msg, "%s configuration: %s\n", msg, conf->tracer->config);
|
||||||
|
(void)memprintf(&msg, "%s plugin: %s\n", msg, conf->tracer->plugin);
|
||||||
|
(void)memprintf(&msg, "%s rate limit: %.2f %%\n", msg, FLT_OT_U32_FLOAT(conf->tracer->rate_limit, FLT_OT_RATE_LIMIT_MAX));
|
||||||
|
(void)memprintf(&msg, "%s hard errors: %s\n", msg, FLT_OT_STR_FLAG_YN(conf->tracer->flag_harderr));
|
||||||
|
(void)memprintf(&msg, "%s disabled: %s\n", msg, FLT_OT_STR_FLAG_YN(conf->tracer->flag_disabled));
|
||||||
|
(void)memprintf(&msg, "%s logging: %s\n", msg, FLT_OT_CLI_LOGGING_STATE(conf->tracer->logging));
|
||||||
|
(void)memprintf(&msg, "%s analyzers: %08x", msg, conf->tracer->analyzers);
|
||||||
|
|
||||||
|
nl = "\n";
|
||||||
|
} FLT_OT_PROXIES_LIST_END();
|
||||||
|
|
||||||
|
cmn_cli_set_msg(appctx, NULL, msg, CLI_ST_PRINT_DYNERR);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct cli_kw_list cli_kws = { { }, {
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
{ { FLT_OT_CLI_CMD, "debug", NULL }, FLT_OT_CLI_CMD " debug [level] : set the OT filter debug level (default: get current debug level)", flt_ot_cli_parse_debug, NULL, NULL, NULL, 0 },
|
||||||
|
#endif
|
||||||
|
{ { FLT_OT_CLI_CMD, "disable", NULL }, FLT_OT_CLI_CMD " disable : disable the OT filter", flt_ot_cli_parse_disabled, NULL, NULL, (void *)1, 0 },
|
||||||
|
{ { FLT_OT_CLI_CMD, "enable", NULL }, FLT_OT_CLI_CMD " enable : enable the OT filter", flt_ot_cli_parse_disabled, NULL, NULL, (void *)0, 0 },
|
||||||
|
{ { FLT_OT_CLI_CMD, "soft-errors", NULL }, FLT_OT_CLI_CMD " soft-errors : turning off hard-errors mode", flt_ot_cli_parse_option, NULL, NULL, (void *)0, 0 },
|
||||||
|
{ { FLT_OT_CLI_CMD, "hard-errors", NULL }, FLT_OT_CLI_CMD " hard-errors : enabling hard-errors mode", flt_ot_cli_parse_option, NULL, NULL, (void *)1, 0 },
|
||||||
|
{ { FLT_OT_CLI_CMD, "logging", NULL }, FLT_OT_CLI_CMD " logging [state] : set logging state (default: get current logging state)", flt_ot_cli_parse_logging, NULL, NULL, NULL, 0 },
|
||||||
|
{ { FLT_OT_CLI_CMD, "rate", NULL }, FLT_OT_CLI_CMD " rate [value] : set the rate limit (default: get current rate value)", flt_ot_cli_parse_rate, NULL, NULL, NULL, 0 },
|
||||||
|
{ { FLT_OT_CLI_CMD, "status", NULL }, FLT_OT_CLI_CMD " status : show the OT filter status", flt_ot_cli_parse_status, NULL, NULL, NULL, 0 },
|
||||||
|
{ /* END */ }
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_cli_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* This function takes no arguments.
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_cli_init(void)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("");
|
||||||
|
|
||||||
|
/* Register CLI keywords. */
|
||||||
|
cli_register_kw(&cli_kws);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
764
addons/ot/src/conf.c
Normal file
764
addons/ot/src/conf.c
Normal file
|
|
@ -0,0 +1,764 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_hdr_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* size -
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static void *flt_ot_conf_hdr_init(size_t size, const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_hdr *retptr = NULL, *ptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%zu, \"%s\", %d, %p, %p:%p", size, id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (head != NULL)
|
||||||
|
list_for_each_entry(ptr, head, list)
|
||||||
|
if (strcmp(ptr->id, id) == 0) {
|
||||||
|
FLT_OT_ERR("'%s' : already defined", id);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
retptr = FLT_OT_CALLOC(1, size);
|
||||||
|
if (retptr != NULL) {
|
||||||
|
retptr->id_len = strlen(id);
|
||||||
|
if (retptr->id_len >= FLT_OT_ID_MAXLEN)
|
||||||
|
FLT_OT_ERR("'%s' : name too long", id);
|
||||||
|
else
|
||||||
|
retptr->id = FLT_OT_STRDUP(id);
|
||||||
|
|
||||||
|
if (retptr->id == NULL)
|
||||||
|
FLT_OT_FREE_CLEAR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retptr != NULL) {
|
||||||
|
retptr->cfg_line = linenum;
|
||||||
|
|
||||||
|
if (head != NULL)
|
||||||
|
LIST_APPEND(head, &(retptr->list));
|
||||||
|
} else {
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_ph_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_ph *flt_ot_conf_ph_init(const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_ph *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p, %p:%p", id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, head, err);
|
||||||
|
if (retptr != NULL)
|
||||||
|
FLT_OT_DBG_CONF_PH("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_ph_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_ph_free(struct flt_ot_conf_ph **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_PH("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->id);
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_sample_expr_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_sample_expr *flt_ot_conf_sample_expr_init(const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_sample_expr *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p, %p:%p", id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, head, err);
|
||||||
|
if (retptr != NULL)
|
||||||
|
FLT_OT_DBG_CONF_SAMPLE_EXPR("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_sample_expr_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_sample_expr_free(struct flt_ot_conf_sample_expr **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SAMPLE_EXPR("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->value);
|
||||||
|
release_sample_expr((*ptr)->expr);
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_sample_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_sample *flt_ot_conf_sample_init(char **args, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_sample *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %d, %p, %p:%p", args, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), args[1], linenum, head, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
flt_ot_args_to_str(args, 2, &(retptr->value));
|
||||||
|
if (retptr->value == NULL) {
|
||||||
|
FLT_OT_FREE_CLEAR(retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
retptr->num_exprs = flt_ot_args_count(args) - 2;
|
||||||
|
LIST_INIT(&(retptr->exprs));
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SAMPLE("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_sample_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_sample_free(struct flt_ot_conf_sample **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SAMPLE("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->key);
|
||||||
|
FLT_OT_FREE((*ptr)->value);
|
||||||
|
FLT_OT_LIST_DESTROY(sample_expr, &((*ptr)->exprs));
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_str_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_str *flt_ot_conf_str_init(const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_str *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p, %p:%p", id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, head, err);
|
||||||
|
if (retptr != NULL)
|
||||||
|
FLT_OT_DBG_CONF_STR("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_str_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_str_free(struct flt_ot_conf_str **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_STR("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->str);
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_context_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_context *flt_ot_conf_context_init(const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_context *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p, %p:%p", id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, head, err);
|
||||||
|
if (retptr != NULL)
|
||||||
|
FLT_OT_DBG_CONF_CONTEXT("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_context_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_context_free(struct flt_ot_conf_context **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_CONTEXT("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->id);
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_span_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_span *flt_ot_conf_span_init(const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_span *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p, %p:%p", id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, head, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
LIST_INIT(&(retptr->tags));
|
||||||
|
LIST_INIT(&(retptr->logs));
|
||||||
|
LIST_INIT(&(retptr->baggages));
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SPAN("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_span_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_span_free(struct flt_ot_conf_span **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SPAN("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->id);
|
||||||
|
FLT_OT_FREE((*ptr)->ref_id);
|
||||||
|
FLT_OT_FREE((*ptr)->ctx_id);
|
||||||
|
FLT_OT_LIST_DESTROY(sample, &((*ptr)->tags));
|
||||||
|
FLT_OT_LIST_DESTROY(sample, &((*ptr)->logs));
|
||||||
|
FLT_OT_LIST_DESTROY(sample, &((*ptr)->baggages));
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_scope_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_scope *flt_ot_conf_scope_init(const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_scope *retptr = NULL;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p, %p:%p", id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, head, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
LIST_INIT(&(retptr->acls));
|
||||||
|
LIST_INIT(&(retptr->contexts));
|
||||||
|
LIST_INIT(&(retptr->spans));
|
||||||
|
LIST_INIT(&(retptr->finish));
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SCOPE("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_scope_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_scope_free(struct flt_ot_conf_scope **ptr)
|
||||||
|
{
|
||||||
|
struct acl *acl, *aclback;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SCOPE("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->id);
|
||||||
|
list_for_each_entry_safe(acl, aclback, &((*ptr)->acls), list) {
|
||||||
|
prune_acl(acl);
|
||||||
|
FLT_OT_LIST_DEL(&(acl->list));
|
||||||
|
FLT_OT_FREE(acl);
|
||||||
|
}
|
||||||
|
free_acl_cond((*ptr)->cond);
|
||||||
|
FLT_OT_LIST_DESTROY(context, &((*ptr)->contexts));
|
||||||
|
FLT_OT_LIST_DESTROY(span, &((*ptr)->spans));
|
||||||
|
FLT_OT_LIST_DESTROY(str, &((*ptr)->finish));
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_group_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* head -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_group *flt_ot_conf_group_init(const char *id, int linenum, struct list *head, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_group *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p, %p:%p", id, linenum, head, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, head, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
LIST_INIT(&(retptr->ph_scopes));
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_GROUP("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_group_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_group_free(struct flt_ot_conf_group **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_GROUP("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->id);
|
||||||
|
FLT_OT_LIST_DESTROY(ph_scope, &((*ptr)->ph_scopes));
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_tracer_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* id -
|
||||||
|
* linenum -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf_tracer *flt_ot_conf_tracer_init(const char *id, int linenum, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf_tracer *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %d, %p:%p", id, linenum, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_conf_hdr_init(sizeof(*retptr), id, linenum, NULL, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
retptr->rate_limit = FLT_OT_FLOAT_U32(FLT_OT_RATE_LIMIT_MAX, FLT_OT_RATE_LIMIT_MAX);
|
||||||
|
init_new_proxy(&(retptr->proxy_log));
|
||||||
|
LIST_INIT(&(retptr->acls));
|
||||||
|
LIST_INIT(&(retptr->ph_groups));
|
||||||
|
LIST_INIT(&(retptr->ph_scopes));
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_TRACER("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_tracer_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_tracer_free(struct flt_ot_conf_tracer **ptr)
|
||||||
|
{
|
||||||
|
struct acl *acl, *aclback;
|
||||||
|
struct logger *logger, *loggerback;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_TRACER("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->id);
|
||||||
|
FLT_OT_FREE((*ptr)->config);
|
||||||
|
FLT_OT_FREE((*ptr)->cfgbuf);
|
||||||
|
FLT_OT_FREE((*ptr)->plugin);
|
||||||
|
FLT_OT_DBG(2, "- deleting acls list %s", flt_ot_list_debug(&((*ptr)->acls)));
|
||||||
|
list_for_each_entry_safe(acl, aclback, &((*ptr)->acls), list) {
|
||||||
|
prune_acl(acl);
|
||||||
|
FLT_OT_LIST_DEL(&(acl->list));
|
||||||
|
FLT_OT_FREE(acl);
|
||||||
|
}
|
||||||
|
FLT_OT_DBG(2, "- deleting proxy_log.loggers list %s", flt_ot_list_debug(&((*ptr)->proxy_log.loggers)));
|
||||||
|
list_for_each_entry_safe(logger, loggerback, &((*ptr)->proxy_log.loggers), list) {
|
||||||
|
LIST_DELETE(&(logger->list));
|
||||||
|
FLT_OT_FREE(logger);
|
||||||
|
}
|
||||||
|
FLT_OT_LIST_DESTROY(ph_group, &((*ptr)->ph_groups));
|
||||||
|
FLT_OT_LIST_DESTROY(ph_scope, &((*ptr)->ph_scopes));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* px -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_conf *flt_ot_conf_init(struct proxy *px)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p", px);
|
||||||
|
|
||||||
|
retptr = FLT_OT_CALLOC(1, sizeof(*retptr));
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
retptr->proxy = px;
|
||||||
|
LIST_INIT(&(retptr->groups));
|
||||||
|
LIST_INIT(&(retptr->scopes));
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF("- init ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_conf_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_conf_free(struct flt_ot_conf **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF("- free ", *ptr);
|
||||||
|
|
||||||
|
FLT_OT_FREE((*ptr)->id);
|
||||||
|
FLT_OT_FREE((*ptr)->cfg_file);
|
||||||
|
flt_ot_conf_tracer_free(&((*ptr)->tracer));
|
||||||
|
FLT_OT_LIST_DESTROY(group, &((*ptr)->groups));
|
||||||
|
FLT_OT_LIST_DESTROY(scope, &((*ptr)->scopes));
|
||||||
|
FLT_OT_FREE_CLEAR(*ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
338
addons/ot/src/event.c
Normal file
338
addons/ot/src/event.c
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define FLT_OT_EVENT_DEF(a,b,c,d,e,f) { AN_##b##_##a, SMP_OPT_DIR_##b, SMP_VAL_FE_##c, SMP_VAL_BE_##d, e, f },
|
||||||
|
const struct flt_ot_event_data flt_ot_event_data[FLT_OT_EVENT_MAX] = { FLT_OT_EVENT_DEFINES };
|
||||||
|
#undef FLT_OT_EVENT_DEF
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_run_span -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* f -
|
||||||
|
* chn -
|
||||||
|
* dir -
|
||||||
|
* span -
|
||||||
|
* data -
|
||||||
|
* conf_span -
|
||||||
|
* ts -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* Returns a negative value if an error occurs, 0 if it needs to wait,
|
||||||
|
* any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int flt_ot_scope_run_span(struct stream *s, struct filter *f, struct channel *chn, uint dir, struct flt_ot_scope_span *span, struct flt_ot_scope_data *data, const struct flt_ot_conf_span *conf_span, const struct timespec *ts, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf *conf = FLT_OT_CONF(f);
|
||||||
|
int retval = FLT_OT_RET_OK;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %p, %u, %p, %p, %p, %p, %p:%p", s, f, chn, dir, span, data, conf_span, ts, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (span == NULL)
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
if (span->span == NULL) {
|
||||||
|
span->span = ot_span_init(conf->tracer->tracer, span->id, ts, NULL, span->ref_type, FLT_OT_DEREF(span->ref_ctx, idx, -1), span->ref_span, data->tags, data->num_tags, err);
|
||||||
|
if (span->span == NULL)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
else if (data->num_tags > 0)
|
||||||
|
if (ot_span_tag(span->span, data->tags, data->num_tags) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
if ((span->span != NULL) && (data->baggage != NULL))
|
||||||
|
if (ot_span_set_baggage(span->span, data->baggage) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
if ((span->span != NULL) && (data->num_log_fields > 0))
|
||||||
|
if (ot_span_log(span->span, data->log_fields, data->num_log_fields) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
if ((span->span != NULL) && (conf_span->ctx_id != NULL)) {
|
||||||
|
struct otc_http_headers_writer writer;
|
||||||
|
struct otc_text_map *text_map = NULL;
|
||||||
|
struct otc_span_context *span_ctx;
|
||||||
|
|
||||||
|
span_ctx = ot_inject_http_headers(conf->tracer->tracer, span->span, &writer, err);
|
||||||
|
if (span_ctx != NULL) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (conf_span->ctx_flags & (FLT_OT_CTX_USE_VARS | FLT_OT_CTX_USE_HEADERS)) {
|
||||||
|
for (text_map = &(writer.text_map); i < text_map->count; i++) {
|
||||||
|
#ifdef USE_OT_VARS
|
||||||
|
if (!(conf_span->ctx_flags & FLT_OT_CTX_USE_VARS))
|
||||||
|
/* Do nothing. */;
|
||||||
|
else if (flt_ot_var_register(FLT_OT_VARS_SCOPE, conf_span->ctx_id, text_map->key[i], err) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
else if (flt_ot_var_set(s, FLT_OT_VARS_SCOPE, conf_span->ctx_id, text_map->key[i], text_map->value[i], dir, err) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(conf_span->ctx_flags & FLT_OT_CTX_USE_HEADERS))
|
||||||
|
/* Do nothing. */;
|
||||||
|
else if (flt_ot_http_header_set(chn, conf_span->ctx_id, text_map->key[i], text_map->value[i], err) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span_ctx->destroy(&span_ctx);
|
||||||
|
otc_text_map_destroy(&text_map, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_run -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* f -
|
||||||
|
* chn -
|
||||||
|
* conf_scope -
|
||||||
|
* ts -
|
||||||
|
* dir -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* Returns a negative value if an error occurs, 0 if it needs to wait,
|
||||||
|
* any other value otherwise.
|
||||||
|
*/
|
||||||
|
int flt_ot_scope_run(struct stream *s, struct filter *f, struct channel *chn, struct flt_ot_conf_scope *conf_scope, const struct timespec *ts, uint dir, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf *conf = FLT_OT_CONF(f);
|
||||||
|
struct flt_ot_conf_context *conf_ctx;
|
||||||
|
struct flt_ot_conf_span *conf_span;
|
||||||
|
struct flt_ot_conf_str *finish;
|
||||||
|
struct timespec ts_now;
|
||||||
|
int retval = FLT_OT_RET_OK;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %p, %p, %p, %u, %p:%p", s, f, chn, conf_scope, ts, dir, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
|
||||||
|
FLT_OT_DBG(3, "run scope '%s' %d", conf_scope->id, conf_scope->event);
|
||||||
|
FLT_OT_DBG_CONF_SCOPE("run scope ", conf_scope);
|
||||||
|
|
||||||
|
if (ts == NULL) {
|
||||||
|
(void)clock_gettime(CLOCK_MONOTONIC, &ts_now);
|
||||||
|
|
||||||
|
ts = &ts_now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf_scope->cond != NULL) {
|
||||||
|
enum acl_test_res res;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
res = acl_exec_cond(conf_scope->cond, s->be, s->sess, s, dir | SMP_OPT_FINAL);
|
||||||
|
rc = acl_pass(res);
|
||||||
|
if (conf_scope->cond->pol == ACL_COND_UNLESS)
|
||||||
|
rc = !rc;
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "the ACL rule %s", rc ? "matches" : "does not match");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the rule does not match, the current scope is skipped.
|
||||||
|
*
|
||||||
|
* If it is a root span, further processing of the session is
|
||||||
|
* disabled. As soon as the first span is encountered which
|
||||||
|
* is marked as root, further search is interrupted.
|
||||||
|
*/
|
||||||
|
if (!rc) {
|
||||||
|
list_for_each_entry(conf_span, &(conf_scope->spans), list)
|
||||||
|
if (conf_span->flag_root) {
|
||||||
|
FLT_OT_DBG(0, "session disabled");
|
||||||
|
|
||||||
|
FLT_OT_RT_CTX(f->ctx)->flag_disabled = 1;
|
||||||
|
|
||||||
|
_HA_ATOMIC_ADD(conf->cnt.disabled + 0, 1);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(conf_ctx, &(conf_scope->contexts), list) {
|
||||||
|
struct otc_text_map *text_map = NULL;
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "run context '%s' -> '%s'", conf_scope->id, conf_ctx->id);
|
||||||
|
FLT_OT_DBG_CONF_CONTEXT("run context ", conf_ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The OpenTracing context is read from the HTTP header
|
||||||
|
* or from HAProxy variables.
|
||||||
|
*/
|
||||||
|
if (conf_ctx->flags & FLT_OT_CTX_USE_HEADERS)
|
||||||
|
text_map = flt_ot_http_headers_get(chn, conf_ctx->id, conf_ctx->id_len, err);
|
||||||
|
#ifdef USE_OT_VARS
|
||||||
|
else
|
||||||
|
text_map = flt_ot_vars_get(s, FLT_OT_VARS_SCOPE, conf_ctx->id, dir, err);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (text_map != NULL) {
|
||||||
|
if (flt_ot_scope_context_init(f->ctx, conf->tracer->tracer, conf_ctx->id, conf_ctx->id_len, text_map, dir, err) == NULL)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
otc_text_map_destroy(&text_map, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
} else {
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(conf_span, &(conf_scope->spans), list) {
|
||||||
|
struct flt_ot_scope_data data;
|
||||||
|
struct flt_ot_scope_span *span;
|
||||||
|
struct flt_ot_conf_sample *sample;
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "run span '%s' -> '%s'", conf_scope->id, conf_span->id);
|
||||||
|
FLT_OT_DBG_CONF_SPAN("run span ", conf_span);
|
||||||
|
|
||||||
|
(void)memset(&data, 0, sizeof(data));
|
||||||
|
|
||||||
|
span = flt_ot_scope_span_init(f->ctx, conf_span->id, conf_span->id_len, conf_span->ref_type, conf_span->ref_id, conf_span->ref_id_len, dir, err);
|
||||||
|
if (span == NULL)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
list_for_each_entry(sample, &(conf_span->tags), list) {
|
||||||
|
FLT_OT_DBG(3, "adding tag '%s' -> '%s'", sample->key, sample->value);
|
||||||
|
|
||||||
|
if (flt_ot_sample_add(s, dir, sample, &data, FLT_OT_EVENT_SAMPLE_TAG, err) == FLT_OT_RET_ERROR)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(sample, &(conf_span->logs), list) {
|
||||||
|
FLT_OT_DBG(3, "adding log '%s' -> '%s'", sample->key, sample->value);
|
||||||
|
|
||||||
|
if (flt_ot_sample_add(s, dir, sample, &data, FLT_OT_EVENT_SAMPLE_LOG, err) == FLT_OT_RET_ERROR)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(sample, &(conf_span->baggages), list) {
|
||||||
|
FLT_OT_DBG(3, "adding baggage '%s' -> '%s'", sample->key, sample->value);
|
||||||
|
|
||||||
|
if (flt_ot_sample_add(s, dir, sample, &data, FLT_OT_EVENT_SAMPLE_BAGGAGE, err) == FLT_OT_RET_ERROR)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval != FLT_OT_RET_ERROR)
|
||||||
|
if (flt_ot_scope_run_span(s, f, chn, dir, span, &data, conf_span, ts, err) == FLT_OT_RET_ERROR)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
flt_ot_scope_data_free(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(finish, &(conf_scope->finish), list)
|
||||||
|
if (flt_ot_scope_finish_mark(f->ctx, finish->str, finish->str_len) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
flt_ot_scope_finish_marked(f->ctx, ts);
|
||||||
|
flt_ot_scope_free_unused(f->ctx, chn);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_event_run -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* f -
|
||||||
|
* chn -
|
||||||
|
* event -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* Returns a negative value if an error occurs, 0 if it needs to wait,
|
||||||
|
* any other value otherwise.
|
||||||
|
*/
|
||||||
|
int flt_ot_event_run(struct stream *s, struct filter *f, struct channel *chn, int event, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_conf *conf = FLT_OT_CONF(f);
|
||||||
|
struct flt_ot_conf_scope *conf_scope;
|
||||||
|
struct timespec ts;
|
||||||
|
int retval = FLT_OT_RET_OK;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %p, %d, %p:%p", s, f, chn, event, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
|
||||||
|
FLT_OT_DBG(3, "run event '%s' %d", flt_ot_event_data[event].name, event);
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
_HA_ATOMIC_ADD(conf->cnt.event[event].htx + (htx_is_empty(htxbuf(&(chn->buf))) ? 1 : 0), 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FLT_OT_RT_CTX(f->ctx)->analyzers |= flt_ot_event_data[event].an_bit;
|
||||||
|
|
||||||
|
/* All spans should be created/completed at the same time. */
|
||||||
|
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is possible that there are defined multiple scopes that use the
|
||||||
|
* same event. Therefore, there must not be a 'break' here, ie an
|
||||||
|
* exit from the 'for' loop.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(conf_scope, &(conf->scopes), list) {
|
||||||
|
if (conf_scope->event != event)
|
||||||
|
/* Do nothing. */;
|
||||||
|
else if (!conf_scope->flag_used)
|
||||||
|
FLT_OT_DBG(3, "scope '%s' %d not used", conf_scope->id, conf_scope->event);
|
||||||
|
else if (flt_ot_scope_run(s, f, chn, conf_scope, &ts, flt_ot_event_data[event].smp_opt_dir, err) == FLT_OT_RET_ERROR)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_OT_VARS
|
||||||
|
flt_ot_vars_dump(s);
|
||||||
|
#endif
|
||||||
|
flt_ot_http_headers_dump(chn);
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "event = %d, chn = %p, s->req = %p, s->res = %p", event, chn, &(s->req), &(s->res));
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
1182
addons/ot/src/filter.c
Normal file
1182
addons/ot/src/filter.c
Normal file
File diff suppressed because it is too large
Load diff
354
addons/ot/src/group.c
Normal file
354
addons/ot/src/group.c
Normal file
|
|
@ -0,0 +1,354 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define FLT_OT_GROUP_DEF(a,b,c) { a, b, c },
|
||||||
|
const struct flt_ot_group_data flt_ot_group_data[] = { FLT_OT_GROUP_DEFINES };
|
||||||
|
#undef FLT_OT_GROUP_DEF
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_group_action -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rule -
|
||||||
|
* px -
|
||||||
|
* sess -
|
||||||
|
* s -
|
||||||
|
* opts -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* This is the action_ptr callback of a rule associated to the
|
||||||
|
* FLT_OT_ACTION_GROUP action.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* The function returns ACT_RET_CONT if processing is finished (with error or
|
||||||
|
* not), otherwise, it returns ACT_RET_YIELD if the action is in progress.
|
||||||
|
*/
|
||||||
|
static enum act_return flt_ot_group_action(struct act_rule *rule, struct proxy *px, struct session *sess, struct stream *s, int opts)
|
||||||
|
{
|
||||||
|
const struct filter *filter;
|
||||||
|
const struct flt_conf *fconf;
|
||||||
|
const struct flt_ot_conf *conf;
|
||||||
|
const struct flt_ot_conf_group *conf_group;
|
||||||
|
const struct flt_ot_runtime_context *rt_ctx = NULL;
|
||||||
|
const struct flt_ot_conf_ph *ph_scope;
|
||||||
|
char *err = NULL;
|
||||||
|
int i, rc;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %p, %p, %d", rule, px, sess, s, opts);
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "from: %d, arg.act %p:{ %p %p %p %p }", rule->from, &(rule->arg.act), rule->arg.act.p[0], rule->arg.act.p[1], rule->arg.act.p[2], rule->arg.act.p[3]);
|
||||||
|
|
||||||
|
fconf = rule->arg.act.p[FLT_OT_ARG_FLT_CONF];
|
||||||
|
conf = rule->arg.act.p[FLT_OT_ARG_CONF];
|
||||||
|
conf_group = ((const struct flt_ot_conf_ph *)(rule->arg.act.p[FLT_OT_ARG_GROUP]))->ptr;
|
||||||
|
|
||||||
|
if ((fconf == NULL) || (conf == NULL) || (conf_group == NULL)) {
|
||||||
|
FLT_OT_LOG(LOG_ERR, FLT_OT_ACTION_GROUP ": internal error, invalid group action");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->tracer->flag_disabled) {
|
||||||
|
FLT_OT_DBG(1, "filter '%s' disabled, group action '%s' ignored", conf->id, conf_group->id);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the OpenTracing filter instance from the current stream. */
|
||||||
|
list_for_each_entry(filter, &(s->strm_flt.filters), list)
|
||||||
|
if (filter->config == fconf) {
|
||||||
|
rt_ctx = filter->ctx;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rt_ctx == NULL) {
|
||||||
|
FLT_OT_DBG(1, "cannot find filter, probably not attached to the stream");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
|
||||||
|
}
|
||||||
|
else if (flt_ot_is_disabled(filter FLT_OT_DBG_ARGS(, -1))) {
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FLT_OT_DBG(3, "run group '%s'", conf_group->id);
|
||||||
|
FLT_OT_DBG_CONF_GROUP("run group ", conf_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the value of rule->from; in case it is incorrect,
|
||||||
|
* report an error.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_group_data); i++)
|
||||||
|
if (flt_ot_group_data[i].act_from == rule->from)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i >= FLT_OT_TABLESIZE(flt_ot_group_data)) {
|
||||||
|
FLT_OT_LOG(LOG_ERR, FLT_OT_ACTION_GROUP ": internal error, invalid rule->from=%d", rule->from);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(ph_scope, &(conf_group->ph_scopes), list) {
|
||||||
|
rc = flt_ot_scope_run(s, rt_ctx->filter, &(s->res), ph_scope->ptr, NULL, SMP_OPT_DIR_RES, &err);
|
||||||
|
if ((rc == FLT_OT_RET_ERROR) && (opts & ACT_OPT_FINAL)) {
|
||||||
|
/* XXX */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_group_check -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rule -
|
||||||
|
* px -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* This is the check_ptr callback of a rule associated to the
|
||||||
|
* FLT_OT_ACTION_GROUP action.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* The function returns 1 in success case, otherwise,
|
||||||
|
* it returns 0 and err is filled.
|
||||||
|
*/
|
||||||
|
static int flt_ot_group_check(struct act_rule *rule, struct proxy *px, char **err)
|
||||||
|
{
|
||||||
|
struct flt_conf *fconf_tmp, *fconf = NULL;
|
||||||
|
struct flt_ot_conf *conf;
|
||||||
|
struct flt_ot_conf_ph *ph_group;
|
||||||
|
const char *filter_id;
|
||||||
|
const char *group_id;
|
||||||
|
bool flag_found = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %p:%p", rule, px, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
filter_id = rule->arg.act.p[FLT_OT_ARG_FILTER_ID];
|
||||||
|
group_id = rule->arg.act.p[FLT_OT_ARG_GROUP_ID];
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "checking filter_id='%s', group_id='%s'", filter_id, group_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the value of rule->from; in case it is incorrect,
|
||||||
|
* report an error.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_group_data); i++)
|
||||||
|
if (flt_ot_group_data[i].act_from == rule->from)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i >= FLT_OT_TABLESIZE(flt_ot_group_data)) {
|
||||||
|
FLT_OT_ERR("internal error, unexpected rule->from=%d, please report this bug!", rule->from);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to find the OpenTracing filter by checking all filters
|
||||||
|
* for the proxy <px>.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(fconf_tmp, &(px->filter_configs), list) {
|
||||||
|
conf = fconf_tmp->conf;
|
||||||
|
|
||||||
|
if (fconf_tmp->id != ot_flt_id) {
|
||||||
|
/* This is not an OpenTracing filter. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strcmp(conf->id, filter_id) == 0) {
|
||||||
|
/* This is the good filter ID. */
|
||||||
|
fconf = fconf_tmp;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fconf == NULL) {
|
||||||
|
FLT_OT_ERR("unable to find the OpenTracing filter '%s' used by the " FLT_OT_ACTION_GROUP " '%s'", filter_id, group_id);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to find if the group is defined in the OpenTracing filter
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(ph_group, &(conf->tracer->ph_groups), list)
|
||||||
|
if (strcmp(ph_group->id, group_id) == 0) {
|
||||||
|
flag_found = 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flag_found) {
|
||||||
|
FLT_OT_ERR("unable to find group '%s' in the OpenTracing filter '%s' configuration", group_id, filter_id);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_FILTER_ID]);
|
||||||
|
FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_GROUP_ID]);
|
||||||
|
|
||||||
|
rule->arg.act.p[FLT_OT_ARG_FLT_CONF] = fconf;
|
||||||
|
rule->arg.act.p[FLT_OT_ARG_CONF] = conf;
|
||||||
|
rule->arg.act.p[FLT_OT_ARG_GROUP] = ph_group;
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_group_release -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rule -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* This is the release_ptr callback of a rule associated to the
|
||||||
|
* FLT_OT_ACTION_GROUP action.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
static void flt_ot_group_release(struct act_rule *rule)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p", rule);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_group_parse -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* cur_arg -
|
||||||
|
* px -
|
||||||
|
* rule -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* Returns ACT_RET_PRS_ERR if an error occurs, ACT_RET_PRS_OK otherwise.
|
||||||
|
*/
|
||||||
|
static enum act_parse_ret flt_ot_group_parse(const char **args, int *cur_arg, struct proxy *px, struct act_rule *rule, char **err)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p, %p, %p, %p, %p:%p", args, cur_arg, px, rule, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (!FLT_OT_ARG_ISVALID(*cur_arg) ||
|
||||||
|
!FLT_OT_ARG_ISVALID(*cur_arg + 1) ||
|
||||||
|
(FLT_OT_ARG_ISVALID(*cur_arg + 2) &&
|
||||||
|
(strcmp(args[*cur_arg + 2], FLT_OT_CONDITION_IF) != 0) &&
|
||||||
|
(strcmp(args[*cur_arg + 2], FLT_OT_CONDITION_UNLESS) != 0))) {
|
||||||
|
FLT_OT_ERR("expects: <filter-id> <group-id> [{ if | unless } ...]");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the OpenTracing filter id. */
|
||||||
|
rule->arg.act.p[FLT_OT_ARG_FILTER_ID] = FLT_OT_STRDUP(args[*cur_arg]);
|
||||||
|
if (rule->arg.act.p[FLT_OT_ARG_FILTER_ID] == NULL) {
|
||||||
|
FLT_OT_ERR("%s : out of memory", args[*cur_arg]);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the OpenTracing group id. */
|
||||||
|
rule->arg.act.p[FLT_OT_ARG_GROUP_ID] = FLT_OT_STRDUP(args[*cur_arg + 1]);
|
||||||
|
if (rule->arg.act.p[FLT_OT_ARG_GROUP_ID] == NULL) {
|
||||||
|
FLT_OT_ERR("%s : out of memory", args[*cur_arg + 1]);
|
||||||
|
|
||||||
|
FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_FILTER_ID]);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
rule->action = ACT_CUSTOM;
|
||||||
|
rule->action_ptr = flt_ot_group_action;
|
||||||
|
rule->check_ptr = flt_ot_group_check;
|
||||||
|
rule->release_ptr = flt_ot_group_release;
|
||||||
|
|
||||||
|
*cur_arg += 2;
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(ACT_RET_PRS_OK, enum act_parse_ret, "%d");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct action_kw_list tcp_req_action_kws = { ILH, {
|
||||||
|
{ FLT_OT_ACTION_GROUP, flt_ot_group_parse },
|
||||||
|
{ /* END */ },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
INITCALL1(STG_REGISTER, tcp_req_cont_keywords_register, &tcp_req_action_kws);
|
||||||
|
|
||||||
|
static struct action_kw_list tcp_res_action_kws = { ILH, {
|
||||||
|
{ FLT_OT_ACTION_GROUP, flt_ot_group_parse },
|
||||||
|
{ /* END */ },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
INITCALL1(STG_REGISTER, tcp_res_cont_keywords_register, &tcp_res_action_kws);
|
||||||
|
|
||||||
|
static struct action_kw_list http_req_action_kws = { ILH, {
|
||||||
|
{ FLT_OT_ACTION_GROUP, flt_ot_group_parse },
|
||||||
|
{ /* END */ },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_action_kws);
|
||||||
|
|
||||||
|
static struct action_kw_list http_res_action_kws = { ILH, {
|
||||||
|
{ FLT_OT_ACTION_GROUP, flt_ot_group_parse },
|
||||||
|
{ /* END */ },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
INITCALL1(STG_REGISTER, http_res_keywords_register, &http_res_action_kws);
|
||||||
|
|
||||||
|
static struct action_kw_list http_after_res_actions_kws = { ILH, {
|
||||||
|
{ FLT_OT_ACTION_GROUP, flt_ot_group_parse },
|
||||||
|
{ /* END */ },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
INITCALL1(STG_REGISTER, http_after_res_keywords_register, &http_after_res_actions_kws);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
312
addons/ot/src/http.c
Normal file
312
addons/ot/src/http.c
Normal file
|
|
@ -0,0 +1,312 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_http_headers_dump -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* chn -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_http_headers_dump(const struct channel *chn)
|
||||||
|
{
|
||||||
|
const struct htx *htx;
|
||||||
|
int32_t pos;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p", chn);
|
||||||
|
|
||||||
|
if (chn == NULL)
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
htx = htxbuf(&(chn->buf));
|
||||||
|
|
||||||
|
if (htx_is_empty(htx))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
|
||||||
|
struct htx_blk *blk = htx_get_blk(htx, pos);
|
||||||
|
enum htx_blk_type type = htx_get_blk_type(blk);
|
||||||
|
|
||||||
|
if (type == HTX_BLK_HDR) {
|
||||||
|
struct ist n = htx_get_blk_name(htx, blk);
|
||||||
|
struct ist v = htx_get_blk_value(htx, blk);
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "'%.*s: %.*s'", (int)n.len, n.ptr, (int)v.len, v.ptr);
|
||||||
|
}
|
||||||
|
else if (type == HTX_BLK_EOH)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DEBUG_OT */
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_http_headers_get -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* chn -
|
||||||
|
* prefix -
|
||||||
|
* len -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* This function is very similar to function http_action_set_header(), from
|
||||||
|
* the HAProxy source.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct otc_text_map *flt_ot_http_headers_get(struct channel *chn, const char *prefix, size_t len, char **err)
|
||||||
|
{
|
||||||
|
const struct htx *htx;
|
||||||
|
size_t prefix_len = (!FLT_OT_STR_ISVALID(prefix) || (len == 0)) ? 0 : (len + 1);
|
||||||
|
int32_t pos;
|
||||||
|
struct otc_text_map *retptr = NULL;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %zu, %p:%p", chn, prefix, len, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (chn == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The keyword 'inject' allows you to define the name of the OpenTracing
|
||||||
|
* context without using a prefix. In that case all HTTP headers are
|
||||||
|
* transferred because it is not possible to separate them from the
|
||||||
|
* OpenTracing context (this separation is usually done via a prefix).
|
||||||
|
*
|
||||||
|
* When using the 'extract' keyword, the context name must be specified.
|
||||||
|
* To allow all HTTP headers to be extracted, the first character of
|
||||||
|
* that name must be set to FLT_OT_PARSE_CTX_IGNORE_NAME.
|
||||||
|
*/
|
||||||
|
if (FLT_OT_STR_ISVALID(prefix) && (*prefix == FLT_OT_PARSE_CTX_IGNORE_NAME))
|
||||||
|
prefix_len = 0;
|
||||||
|
|
||||||
|
htx = htxbuf(&(chn->buf));
|
||||||
|
|
||||||
|
for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
|
||||||
|
struct htx_blk *blk = htx_get_blk(htx, pos);
|
||||||
|
enum htx_blk_type type = htx_get_blk_type(blk);
|
||||||
|
|
||||||
|
if (type == HTX_BLK_HDR) {
|
||||||
|
struct ist v, n = htx_get_blk_name(htx, blk);
|
||||||
|
|
||||||
|
if ((prefix_len == 0) || ((n.len >= prefix_len) && (strncasecmp(n.ptr, prefix, len) == 0))) {
|
||||||
|
if (retptr == NULL) {
|
||||||
|
retptr = otc_text_map_new(NULL, 8);
|
||||||
|
if (retptr == NULL) {
|
||||||
|
FLT_OT_ERR("failed to create HTTP header data");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v = htx_get_blk_value(htx, blk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case the data of the HTTP header is not
|
||||||
|
* specified, v.ptr will have some non-null
|
||||||
|
* value and v.len will be equal to 0. The
|
||||||
|
* otc_text_map_add() function will not
|
||||||
|
* interpret this well. In this case v.ptr
|
||||||
|
* is set to an empty string.
|
||||||
|
*/
|
||||||
|
if (v.len == 0)
|
||||||
|
v = ist("");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here, an HTTP header (which is actually part
|
||||||
|
* of the span context is added to the text_map.
|
||||||
|
*
|
||||||
|
* Before adding, the prefix is removed from the
|
||||||
|
* HTTP header name.
|
||||||
|
*/
|
||||||
|
if (otc_text_map_add(retptr, n.ptr + prefix_len, n.len - prefix_len, v.ptr, v.len, OTC_TEXT_MAP_DUP_KEY | OTC_TEXT_MAP_DUP_VALUE) == -1) {
|
||||||
|
FLT_OT_ERR("failed to add HTTP header data");
|
||||||
|
|
||||||
|
otc_text_map_destroy(&retptr, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == HTX_BLK_EOH)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ot_text_map_show(retptr);
|
||||||
|
|
||||||
|
if ((retptr != NULL) && (retptr->count == 0)) {
|
||||||
|
FLT_OT_DBG(2, "WARNING: no HTTP headers found");
|
||||||
|
|
||||||
|
otc_text_map_destroy(&retptr, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_http_header_set -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* chn -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* value -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* This function is very similar to function http_action_set_header(), from
|
||||||
|
* the HAProxy source.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_http_header_set(struct channel *chn, const char *prefix, const char *name, const char *value, char **err)
|
||||||
|
{
|
||||||
|
struct http_hdr_ctx ctx = { .blk = NULL };
|
||||||
|
struct ist ist_name;
|
||||||
|
struct buffer *buffer = NULL;
|
||||||
|
struct htx *htx;
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", %p:%p", chn, prefix, name, value, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if ((chn == NULL) || (!FLT_OT_STR_ISVALID(prefix) && !FLT_OT_STR_ISVALID(name)))
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
htx = htxbuf(&(chn->buf));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Very rare (about 1% of cases), htx is empty.
|
||||||
|
* In order to avoid segmentation fault, we exit this function.
|
||||||
|
*/
|
||||||
|
if (htx_is_empty(htx)) {
|
||||||
|
FLT_OT_ERR("HTX is empty");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FLT_OT_STR_ISVALID(prefix)) {
|
||||||
|
ist_name = ist2((char *)name, strlen(name));
|
||||||
|
}
|
||||||
|
else if (!FLT_OT_STR_ISVALID(name)) {
|
||||||
|
ist_name = ist2((char *)prefix, strlen(prefix));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer = flt_ot_trash_alloc(0, err);
|
||||||
|
if (buffer == NULL)
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
(void)chunk_printf(buffer, "%s-%s", prefix, name);
|
||||||
|
|
||||||
|
ist_name = ist2(buffer->area, buffer->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove all occurrences of the header. */
|
||||||
|
while (http_find_header(htx, ist(""), &ctx, 1) == 1) {
|
||||||
|
struct ist n = htx_get_blk_name(htx, ctx.blk);
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
struct ist v = htx_get_blk_value(htx, ctx.blk);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the <name> parameter is not set, then remove all headers
|
||||||
|
* that start with the contents of the <prefix> parameter.
|
||||||
|
*/
|
||||||
|
if (!FLT_OT_STR_ISVALID(name))
|
||||||
|
n.len = ist_name.len;
|
||||||
|
|
||||||
|
if (isteqi(n, ist_name))
|
||||||
|
if (http_remove_header(htx, &ctx) == 1)
|
||||||
|
FLT_OT_DBG(3, "HTTP header '%.*s: %.*s' removed", (int)n.len, n.ptr, (int)v.len, v.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the value pointer has a value of NULL, the HTTP header is not set
|
||||||
|
* after deletion.
|
||||||
|
*/
|
||||||
|
if (value == NULL) {
|
||||||
|
/* Do nothing. */
|
||||||
|
}
|
||||||
|
else if (http_add_header(htx, ist_name, ist(value), 1) == 1) {
|
||||||
|
retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "HTTP header '%s: %s' added", ist_name.ptr, value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FLT_OT_ERR("failed to set HTTP header '%s: %s'", ist_name.ptr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
flt_ot_trash_free(&buffer);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_http_headers_remove -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* chn -
|
||||||
|
* prefix -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_http_headers_remove(struct channel *chn, const char *prefix, char **err)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %p:%p", chn, prefix, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retval = flt_ot_http_header_set(chn, prefix, NULL, NULL, err);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
1067
addons/ot/src/opentracing.c
Normal file
1067
addons/ot/src/opentracing.c
Normal file
File diff suppressed because it is too large
Load diff
1230
addons/ot/src/parser.c
Normal file
1230
addons/ot/src/parser.c
Normal file
File diff suppressed because it is too large
Load diff
223
addons/ot/src/pool.c
Normal file
223
addons/ot/src/pool.c
Normal file
|
|
@ -0,0 +1,223 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_pool_alloc -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* pool -
|
||||||
|
* size -
|
||||||
|
* flag_clear -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
void *flt_ot_pool_alloc(struct pool_head *pool, size_t size, bool flag_clear, char **err)
|
||||||
|
{
|
||||||
|
void *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %zu, %hhu, %p:%p", pool, size, flag_clear, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (pool != NULL) {
|
||||||
|
retptr = pool_alloc(pool);
|
||||||
|
if (retptr != NULL)
|
||||||
|
FLT_OT_DBG(2, "POOL_ALLOC: %s:%d(%p %zu)", __func__, __LINE__, retptr, FLT_OT_DEREF(pool, size, size));
|
||||||
|
} else {
|
||||||
|
retptr = FLT_OT_MALLOC(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
else if (flag_clear)
|
||||||
|
(void)memset(retptr, 0, size);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_pool_strndup -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* pool -
|
||||||
|
* s -
|
||||||
|
* size -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
void *flt_ot_pool_strndup(struct pool_head *pool, const char *s, size_t size, char **err)
|
||||||
|
{
|
||||||
|
void *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%.*s\", %zu, %p:%p", pool, (int)size, s, size, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (pool != NULL) {
|
||||||
|
retptr = pool_alloc(pool);
|
||||||
|
if (retptr != NULL) {
|
||||||
|
(void)memcpy(retptr, s, MIN(pool->size - 1, size));
|
||||||
|
|
||||||
|
((uint8_t *)retptr)[MIN(pool->size - 1, size)] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retptr = FLT_OT_STRNDUP(s, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retptr != NULL)
|
||||||
|
FLT_OT_DBG(2, "POOL_STRNDUP: %s:%d(%p %zu)", __func__, __LINE__, retptr, FLT_OT_DEREF(pool, size, size));
|
||||||
|
else
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_pool_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* pool -
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_pool_free(struct pool_head *pool, void **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p, %p:%p", pool, FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "POOL_FREE: %s:%d(%p %u)", __func__, __LINE__, *ptr, FLT_OT_DEREF(pool, size, 0));
|
||||||
|
|
||||||
|
if (pool != NULL)
|
||||||
|
pool_free(pool, *ptr);
|
||||||
|
else
|
||||||
|
FLT_OT_FREE(*ptr);
|
||||||
|
|
||||||
|
*ptr = NULL;
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_trash_alloc -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* flag_clear -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct buffer *flt_ot_trash_alloc(bool flag_clear, char **err)
|
||||||
|
{
|
||||||
|
struct buffer *retptr;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%hhu, %p:%p", flag_clear, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
#ifdef USE_TRASH_CHUNK
|
||||||
|
retptr = alloc_trash_chunk();
|
||||||
|
if (retptr != NULL)
|
||||||
|
FLT_OT_DBG(2, "TRASH_ALLOC: %s:%d(%p %zu)", __func__, __LINE__, retptr, retptr->size);
|
||||||
|
#else
|
||||||
|
retptr = FLT_OT_MALLOC(sizeof(*retptr));
|
||||||
|
if (retptr != NULL) {
|
||||||
|
chunk_init(retptr, FLT_OT_MALLOC(global.tune.bufsize), global.tune.bufsize);
|
||||||
|
if (retptr->area == NULL)
|
||||||
|
FLT_OT_FREE_CLEAR(retptr);
|
||||||
|
else
|
||||||
|
*(retptr->area) = '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
else if (flag_clear)
|
||||||
|
(void)memset(retptr->area, 0, retptr->size);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_trash_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_trash_free(struct buffer **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "TRASH_FREE: %s:%d(%p %zu)", __func__, __LINE__, *ptr, (*ptr)->size);
|
||||||
|
|
||||||
|
#ifdef USE_TRASH_CHUNK
|
||||||
|
free_trash_chunk(*ptr);
|
||||||
|
#else
|
||||||
|
FLT_OT_FREE((*ptr)->area);
|
||||||
|
FLT_OT_FREE(*ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*ptr = NULL;
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
634
addons/ot/src/scope.c
Normal file
634
addons/ot/src/scope.c
Normal file
|
|
@ -0,0 +1,634 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
static struct pool_head *pool_head_ot_scope_span __read_mostly = NULL;
|
||||||
|
static struct pool_head *pool_head_ot_scope_context __read_mostly = NULL;
|
||||||
|
static struct pool_head *pool_head_ot_runtime_context __read_mostly = NULL;
|
||||||
|
|
||||||
|
#ifdef USE_POOL_OT_SCOPE_SPAN
|
||||||
|
REGISTER_POOL(&pool_head_ot_scope_span, "ot_scope_span", sizeof(struct flt_ot_scope_span));
|
||||||
|
#endif
|
||||||
|
#ifdef USE_POOL_OT_SCOPE_CONTEXT
|
||||||
|
REGISTER_POOL(&pool_head_ot_scope_context, "ot_scope_context", sizeof(struct flt_ot_scope_context));
|
||||||
|
#endif
|
||||||
|
#ifdef USE_POOL_OT_RUNTIME_CONTEXT
|
||||||
|
REGISTER_POOL(&pool_head_ot_runtime_context, "ot_runtime_context", sizeof(struct flt_ot_runtime_context));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_pools_info -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* This function takes no arguments.
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_pools_info(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* In case we have some error in the configuration file,
|
||||||
|
* it is possible that this pool was not initialized.
|
||||||
|
*/
|
||||||
|
#ifdef USE_POOL_BUFFER
|
||||||
|
FLT_OT_DBG(2, "sizeof_pool(buffer) = %u", FLT_OT_DEREF(pool_head_buffer, size, 0));
|
||||||
|
#endif
|
||||||
|
#ifdef USE_TRASH_CHUNK
|
||||||
|
FLT_OT_DBG(2, "sizeof_pool(trash) = %u", FLT_OT_DEREF(pool_head_trash, size, 0));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_POOL_OT_SCOPE_SPAN
|
||||||
|
FLT_OT_DBG(2, "sizeof_pool(ot_scope_span) = %u", pool_head_ot_scope_span->size);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_POOL_OT_SCOPE_CONTEXT
|
||||||
|
FLT_OT_DBG(2, "sizeof_pool(ot_scope_context) = %u", pool_head_ot_scope_context->size);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_POOL_OT_RUNTIME_CONTEXT
|
||||||
|
FLT_OT_DBG(2, "sizeof_pool(ot_runtime_context) = %u", pool_head_ot_runtime_context->size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DEBUG_OT */
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_runtime_context_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* f -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_runtime_context *flt_ot_runtime_context_init(struct stream *s, struct filter *f, char **err)
|
||||||
|
{
|
||||||
|
const struct flt_ot_conf *conf = FLT_OT_CONF(f);
|
||||||
|
struct buffer uuid;
|
||||||
|
struct flt_ot_runtime_context *retptr = NULL;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %p:%p", s, f, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
retptr = flt_ot_pool_alloc(pool_head_ot_runtime_context, sizeof(*retptr), 1, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
retptr->stream = s;
|
||||||
|
retptr->filter = f;
|
||||||
|
retptr->flag_harderr = conf->tracer->flag_harderr;
|
||||||
|
retptr->flag_disabled = conf->tracer->flag_disabled;
|
||||||
|
retptr->logging = conf->tracer->logging;
|
||||||
|
LIST_INIT(&(retptr->spans));
|
||||||
|
LIST_INIT(&(retptr->contexts));
|
||||||
|
|
||||||
|
uuid = b_make(retptr->uuid, sizeof(retptr->uuid), 0, 0);
|
||||||
|
ha_generate_uuid_v4(&uuid);
|
||||||
|
|
||||||
|
#ifdef USE_OT_VARS
|
||||||
|
/*
|
||||||
|
* The HAProxy variable 'sess.ot.uuid' is registered here,
|
||||||
|
* after which its value is set to runtime context UUID.
|
||||||
|
*/
|
||||||
|
if (flt_ot_var_register(FLT_OT_VAR_UUID, err) != -1)
|
||||||
|
(void)flt_ot_var_set(s, FLT_OT_VAR_UUID, retptr->uuid, SMP_OPT_DIR_REQ, err);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FLT_OT_DBG_RUNTIME_CONTEXT("session context: ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_runtime_context_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* f -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_runtime_context_free(struct filter *f)
|
||||||
|
{
|
||||||
|
struct flt_ot_runtime_context *rt_ctx = f->ctx;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p", f);
|
||||||
|
|
||||||
|
if (rt_ctx == NULL)
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_RUNTIME_CONTEXT("session context: ", rt_ctx);
|
||||||
|
|
||||||
|
if (!LIST_ISEMPTY(&(rt_ctx->spans))) {
|
||||||
|
struct timespec ts;
|
||||||
|
struct flt_ot_scope_span *span, *span_back;
|
||||||
|
|
||||||
|
/* All spans should be completed at the same time. */
|
||||||
|
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(span, span_back, &(rt_ctx->spans), list) {
|
||||||
|
ot_span_finish(&(span->span), &ts, NULL, NULL, NULL);
|
||||||
|
flt_ot_scope_span_free(&span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LIST_ISEMPTY(&(rt_ctx->contexts))) {
|
||||||
|
struct flt_ot_scope_context *ctx, *ctx_back;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(ctx, ctx_back, &(rt_ctx->contexts), list)
|
||||||
|
flt_ot_scope_context_free(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
flt_ot_pool_free(pool_head_ot_runtime_context, &(f->ctx));
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_span_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rt_ctx -
|
||||||
|
* id -
|
||||||
|
* id_len -
|
||||||
|
* ref_type -
|
||||||
|
* ref_id -
|
||||||
|
* ref_id_len -
|
||||||
|
* dir -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_scope_span *flt_ot_scope_span_init(struct flt_ot_runtime_context *rt_ctx, const char *id, size_t id_len, otc_span_reference_type_t ref_type, const char *ref_id, size_t ref_id_len, uint dir, char **err)
|
||||||
|
{
|
||||||
|
struct otc_span *ref_span = NULL;
|
||||||
|
struct otc_span_context *ref_ctx = NULL;
|
||||||
|
struct flt_ot_scope_span *span, *retptr = NULL;
|
||||||
|
struct flt_ot_scope_context *ctx;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %zu, %d, \"%s\", %zu, %u, %p:%p", rt_ctx, id, id_len, ref_type, ref_id, ref_id_len, dir, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if ((rt_ctx == NULL) || (id == NULL))
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||||
|
if ((span->id_len == id_len) && (memcmp(span->id, id, id_len) == 0)) {
|
||||||
|
FLT_OT_DBG(2, "found span %p", span);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref_id != NULL) {
|
||||||
|
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||||
|
if ((span->id_len == ref_id_len) && (memcmp(span->id, ref_id, ref_id_len) == 0)) {
|
||||||
|
ref_span = span->span;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref_span != NULL) {
|
||||||
|
FLT_OT_DBG(2, "found referenced span %p", span);
|
||||||
|
} else {
|
||||||
|
list_for_each_entry(ctx, &(rt_ctx->contexts), list)
|
||||||
|
if ((ctx->id_len == ref_id_len) && (memcmp(ctx->id, ref_id, ref_id_len) == 0)) {
|
||||||
|
ref_ctx = ctx->context;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref_ctx != NULL) {
|
||||||
|
FLT_OT_DBG(2, "found referenced context %p", ctx);
|
||||||
|
} else {
|
||||||
|
FLT_OT_ERR("cannot find referenced span/context '%s'", ref_id);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retptr = flt_ot_pool_alloc(pool_head_ot_scope_span, sizeof(*retptr), 1, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
retptr->id = id;
|
||||||
|
retptr->id_len = id_len;
|
||||||
|
retptr->smp_opt_dir = dir;
|
||||||
|
retptr->ref_type = ref_type;
|
||||||
|
retptr->ref_span = ref_span;
|
||||||
|
retptr->ref_ctx = ref_ctx;
|
||||||
|
LIST_INSERT(&(rt_ctx->spans), &(retptr->list));
|
||||||
|
|
||||||
|
FLT_OT_DBG_SCOPE_SPAN("new span ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_span_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_scope_span_free(struct flt_ot_scope_span **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_SCOPE_SPAN("", *ptr);
|
||||||
|
|
||||||
|
/* If the span is still active, do nothing. */
|
||||||
|
if ((*ptr)->span != NULL) {
|
||||||
|
FLT_OT_DBG(2, "cannot finish active span");
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
flt_ot_pool_free(pool_head_ot_scope_span, (void **)ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_context_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rt_ctx -
|
||||||
|
* tracer -
|
||||||
|
* id -
|
||||||
|
* id_len -
|
||||||
|
* text_map -
|
||||||
|
* dir -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct flt_ot_scope_context *flt_ot_scope_context_init(struct flt_ot_runtime_context *rt_ctx, struct otc_tracer *tracer, const char *id, size_t id_len, const struct otc_text_map *text_map, uint dir, char **err)
|
||||||
|
{
|
||||||
|
struct otc_http_headers_reader reader;
|
||||||
|
struct otc_span_context *span_ctx;
|
||||||
|
struct flt_ot_scope_context *retptr = NULL;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, \"%s\", %zu, %p, %u, %p:%p", rt_ctx, tracer, id, id_len, text_map, dir, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if ((rt_ctx == NULL) || (tracer == NULL) || (id == NULL) || (text_map == NULL))
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
list_for_each_entry(retptr, &(rt_ctx->contexts), list)
|
||||||
|
if ((retptr->id_len == id_len) && (memcmp(retptr->id, id, id_len) == 0)) {
|
||||||
|
FLT_OT_DBG(2, "found context %p", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
retptr = flt_ot_pool_alloc(pool_head_ot_scope_context, sizeof(*retptr), 1, err);
|
||||||
|
if (retptr == NULL)
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
|
||||||
|
span_ctx = ot_extract_http_headers(tracer, &reader, text_map, err);
|
||||||
|
if (span_ctx == NULL) {
|
||||||
|
flt_ot_scope_context_free(&retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
retptr->id = id;
|
||||||
|
retptr->id_len = id_len;
|
||||||
|
retptr->smp_opt_dir = dir;
|
||||||
|
retptr->context = span_ctx;
|
||||||
|
LIST_INSERT(&(rt_ctx->contexts), &(retptr->list));
|
||||||
|
|
||||||
|
FLT_OT_DBG_SCOPE_CONTEXT("new context ", retptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_context_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_scope_context_free(struct flt_ot_scope_context **ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p:%p", FLT_OT_DPTR_ARGS(ptr));
|
||||||
|
|
||||||
|
if ((ptr == NULL) || (*ptr == NULL))
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_SCOPE_CONTEXT("", *ptr);
|
||||||
|
|
||||||
|
if ((*ptr)->context != NULL)
|
||||||
|
(*ptr)->context->destroy(&((*ptr)->context));
|
||||||
|
|
||||||
|
FLT_OT_LIST_DEL(&((*ptr)->list));
|
||||||
|
flt_ot_pool_free(pool_head_ot_scope_context, (void **)ptr);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_data_free -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_scope_data_free(struct flt_ot_scope_data *ptr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p", ptr);
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
FLT_OT_DBG_SCOPE_DATA("", ptr);
|
||||||
|
|
||||||
|
for (i = 0; i < ptr->num_tags; i++)
|
||||||
|
if (ptr->tags[i].value.type == otc_value_string)
|
||||||
|
FLT_OT_FREE_VOID(ptr->tags[i].value.value.string_value);
|
||||||
|
otc_text_map_destroy(&(ptr->baggage), OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
for (i = 0; i < ptr->num_log_fields; i++)
|
||||||
|
if (ptr->log_fields[i].value.type == otc_value_string)
|
||||||
|
FLT_OT_FREE_VOID(ptr->log_fields[i].value.value.string_value);
|
||||||
|
|
||||||
|
(void)memset(ptr, 0, sizeof(*ptr));
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_finish_mark -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rt_ctx -
|
||||||
|
* id -
|
||||||
|
* id_len -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_scope_finish_mark(const struct flt_ot_runtime_context *rt_ctx, const char *id, size_t id_len)
|
||||||
|
{
|
||||||
|
struct flt_ot_scope_span *span;
|
||||||
|
struct flt_ot_scope_context *ctx;
|
||||||
|
int span_cnt = 0, ctx_cnt = 0, retval;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", %zu", rt_ctx, id, id_len);
|
||||||
|
|
||||||
|
if (FLT_OT_STR_CMP(FLT_OT_SCOPE_SPAN_FINISH_ALL, id, id_len)) {
|
||||||
|
list_for_each_entry(span, &(rt_ctx->spans), list) {
|
||||||
|
span->flag_finish = 1;
|
||||||
|
span_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(ctx, &(rt_ctx->contexts), list) {
|
||||||
|
ctx->flag_finish = 1;
|
||||||
|
ctx_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "marked %d span(s), %d context(s)", span_cnt, ctx_cnt);
|
||||||
|
}
|
||||||
|
else if (FLT_OT_STR_CMP(FLT_OT_SCOPE_SPAN_FINISH_REQ, id, id_len)) {
|
||||||
|
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||||
|
if (span->smp_opt_dir == SMP_OPT_DIR_REQ) {
|
||||||
|
span->flag_finish = 1;
|
||||||
|
span_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(ctx, &(rt_ctx->contexts), list)
|
||||||
|
if (ctx->smp_opt_dir == SMP_OPT_DIR_REQ) {
|
||||||
|
ctx->flag_finish = 1;
|
||||||
|
span_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "marked REQuest channel %d span(s), %d context(s)", span_cnt, ctx_cnt);
|
||||||
|
}
|
||||||
|
else if (FLT_OT_STR_CMP(FLT_OT_SCOPE_SPAN_FINISH_RES, id, id_len)) {
|
||||||
|
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||||
|
if (span->smp_opt_dir == SMP_OPT_DIR_RES) {
|
||||||
|
span->flag_finish = 1;
|
||||||
|
span_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(ctx, &(rt_ctx->contexts), list)
|
||||||
|
if (ctx->smp_opt_dir == SMP_OPT_DIR_RES) {
|
||||||
|
ctx->flag_finish = 1;
|
||||||
|
ctx_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "marked RESponse channel %d span(s), %d context(s)", span_cnt, ctx_cnt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||||
|
if ((span->id_len == id_len) && (memcmp(span->id, id, id_len) == 0)) {
|
||||||
|
span->flag_finish = 1;
|
||||||
|
span_cnt++;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(ctx, &(rt_ctx->contexts), list)
|
||||||
|
if ((ctx->id_len == id_len) && (memcmp(ctx->id, id, id_len) == 0)) {
|
||||||
|
ctx->flag_finish = 1;
|
||||||
|
ctx_cnt++;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (span_cnt > 0)
|
||||||
|
FLT_OT_DBG(2, "marked span '%s'", id);
|
||||||
|
if (ctx_cnt > 0)
|
||||||
|
FLT_OT_DBG(2, "marked context '%s'", id);
|
||||||
|
if ((span_cnt + ctx_cnt) == 0)
|
||||||
|
FLT_OT_DBG(2, "cannot find span/context '%s'", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = span_cnt + ctx_cnt;
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_finish_marked -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rt_ctx -
|
||||||
|
* ts_finish -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* Finish marked spans.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_scope_finish_marked(const struct flt_ot_runtime_context *rt_ctx, const struct timespec *ts_finish)
|
||||||
|
{
|
||||||
|
struct flt_ot_scope_span *span;
|
||||||
|
struct flt_ot_scope_context *ctx;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p", rt_ctx, ts_finish);
|
||||||
|
|
||||||
|
list_for_each_entry(span, &(rt_ctx->spans), list)
|
||||||
|
if (span->flag_finish) {
|
||||||
|
FLT_OT_DBG_SCOPE_SPAN("finishing span ", span);
|
||||||
|
|
||||||
|
ot_span_finish(&(span->span), ts_finish, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
span->flag_finish = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(ctx, &(rt_ctx->contexts), list)
|
||||||
|
if (ctx->flag_finish) {
|
||||||
|
FLT_OT_DBG_SCOPE_CONTEXT("finishing context ", ctx);
|
||||||
|
|
||||||
|
if (ctx->context != NULL)
|
||||||
|
ctx->context->destroy(&(ctx->context));
|
||||||
|
|
||||||
|
ctx->flag_finish = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_scope_free_unused -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* rt_ctx -
|
||||||
|
* chn -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_scope_free_unused(struct flt_ot_runtime_context *rt_ctx, struct channel *chn)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p", rt_ctx);
|
||||||
|
|
||||||
|
if (rt_ctx == NULL)
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
|
||||||
|
if (!LIST_ISEMPTY(&(rt_ctx->spans))) {
|
||||||
|
struct flt_ot_scope_span *span, *span_back;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(span, span_back, &(rt_ctx->spans), list)
|
||||||
|
if (span->span == NULL)
|
||||||
|
flt_ot_scope_span_free(&span);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LIST_ISEMPTY(&(rt_ctx->contexts))) {
|
||||||
|
struct flt_ot_scope_context *ctx, *ctx_back;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(ctx, ctx_back, &(rt_ctx->contexts), list)
|
||||||
|
if (ctx->context == NULL) {
|
||||||
|
/*
|
||||||
|
* All headers and variables associated with
|
||||||
|
* the context in question should be deleted.
|
||||||
|
*/
|
||||||
|
(void)flt_ot_http_headers_remove(chn, ctx->id, NULL);
|
||||||
|
#ifdef USE_OT_VARS
|
||||||
|
(void)flt_ot_vars_unset(rt_ctx->stream, FLT_OT_VARS_SCOPE, ctx->id, ctx->smp_opt_dir, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
flt_ot_scope_context_free(&ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_DBG_RUNTIME_CONTEXT("session context: ", rt_ctx);
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
815
addons/ot/src/util.c
Normal file
815
addons/ot/src/util.c
Normal file
|
|
@ -0,0 +1,815 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_args_dump -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_args_dump(char **args)
|
||||||
|
{
|
||||||
|
int i, argc;
|
||||||
|
|
||||||
|
argc = flt_ot_args_count(args);
|
||||||
|
|
||||||
|
(void)fprintf(stderr, FLT_OT_DBG_FMT("%.*sargs[%d]: { '%s' "), flt_ot_dbg_indent_level, FLT_OT_DBG_INDENT, argc, args[0]);
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
(void)fprintf(stderr, "'%s' ", args[i]);
|
||||||
|
|
||||||
|
(void)fprintf(stderr, "}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_filters_dump -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* This function takes no arguments.
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_filters_dump(void)
|
||||||
|
{
|
||||||
|
struct flt_conf *fconf;
|
||||||
|
struct proxy *px;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("");
|
||||||
|
|
||||||
|
for (px = proxies_list; px != NULL; px = px->next) {
|
||||||
|
FLT_OT_DBG(2, "proxy '%s'", px->id);
|
||||||
|
|
||||||
|
list_for_each_entry(fconf, &(px->filter_configs), list)
|
||||||
|
if (fconf->id == ot_flt_id) {
|
||||||
|
struct flt_ot_conf *conf = fconf->conf;
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, " OT filter '%s'", conf->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_chn_label -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* chn -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_chn_label(const struct channel *chn)
|
||||||
|
{
|
||||||
|
return (chn->flags & CF_ISRESP) ? "RESponse" : "REQuest";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_pr_mode -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_pr_mode(const struct stream *s)
|
||||||
|
{
|
||||||
|
struct proxy *px = (s->flags & SF_BE_ASSIGNED) ? s->be : strm_fe(s);
|
||||||
|
|
||||||
|
return (px->mode == PR_MODE_HTTP) ? "HTTP" : "TCP";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_stream_pos -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_stream_pos(const struct stream *s)
|
||||||
|
{
|
||||||
|
return (s->flags & SF_BE_ASSIGNED) ? "backend" : "frontend";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_type -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* f -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_type(const struct filter *f)
|
||||||
|
{
|
||||||
|
return (f->flags & FLT_FL_IS_BACKEND_FILTER) ? "backend" : "frontend";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_analyzer -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* an_bit -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_analyzer(uint an_bit)
|
||||||
|
{
|
||||||
|
#define FLT_OT_AN_DEF(a) { a, #a },
|
||||||
|
static const struct {
|
||||||
|
uint an_bit;
|
||||||
|
const char *str;
|
||||||
|
} flt_ot_an[] = { FLT_OT_AN_DEFINES };
|
||||||
|
#undef FLT_OT_AN_DEF
|
||||||
|
const char *retptr = "invalid an_bit";
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_an); i++)
|
||||||
|
if (flt_ot_an[i].an_bit == an_bit) {
|
||||||
|
retptr = flt_ot_an[i].str;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_str_hex -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* data -
|
||||||
|
* size -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_str_hex(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
static THREAD_LOCAL char retbuf[BUFSIZ];
|
||||||
|
const uint8_t *ptr = data;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
return "(null)";
|
||||||
|
else if (size == 0)
|
||||||
|
return "()";
|
||||||
|
|
||||||
|
for (i = 0, size <<= 1; (i < (sizeof(retbuf) - 2)) && (i < size); ptr++) {
|
||||||
|
retbuf[i++] = FLT_OT_NIBBLE_TO_HEX(*ptr >> 4);
|
||||||
|
retbuf[i++] = FLT_OT_NIBBLE_TO_HEX(*ptr & 0x0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
retbuf[i] = '\0';
|
||||||
|
|
||||||
|
return retbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_str_ctrl -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* data -
|
||||||
|
* size -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_str_ctrl(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
static THREAD_LOCAL char retbuf[BUFSIZ];
|
||||||
|
const uint8_t *ptr = data;
|
||||||
|
size_t i, n = 0;
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
return "(null)";
|
||||||
|
else if (size == 0)
|
||||||
|
return "()";
|
||||||
|
|
||||||
|
for (i = 0; (n < (sizeof(retbuf) - 1)) && (i < size); i++)
|
||||||
|
retbuf[n++] = ((ptr[i] >= 0x20) && (ptr[i] <= 0x7e)) ? ptr[i] : '.';
|
||||||
|
|
||||||
|
retbuf[n] = '\0';
|
||||||
|
|
||||||
|
return retbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_list_debug -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* head -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
const char *flt_ot_list_debug(const struct list *head)
|
||||||
|
{
|
||||||
|
FLT_OT_BUFFER_THR(retbuf, 4, 64, retptr);
|
||||||
|
|
||||||
|
if ((head == NULL) || LIST_ISEMPTY(head)) {
|
||||||
|
(void)strncpy(retptr, (head == NULL) ? "{ null list }" : "{ empty list }", sizeof(retbuf[0]));
|
||||||
|
}
|
||||||
|
else if (head->p == head->n) {
|
||||||
|
(void)snprintf(retptr, sizeof(retbuf[0]), "{ %p * 1 }", head->p);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const struct list *ptr;
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
for (ptr = head->n; ptr != head; ptr = ptr->n, count++);
|
||||||
|
|
||||||
|
(void)snprintf(retptr, sizeof(retbuf[0]), "{ %p %p %zu }", head->p, head->n, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DEBUG_OT */
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_chunk_add -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* chk -
|
||||||
|
* src -
|
||||||
|
* n -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
ssize_t flt_ot_chunk_add(struct buffer *chk, const void *src, size_t n, char **err)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p, %p, %zu, %p:%p", chk, src, n, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if ((chk == NULL) || (src == NULL))
|
||||||
|
FLT_OT_RETURN_EX(-1, ssize_t, "%ld");
|
||||||
|
|
||||||
|
if (chk->area == NULL)
|
||||||
|
chunk_init(chk, FLT_OT_CALLOC(1, global.tune.bufsize), global.tune.bufsize);
|
||||||
|
|
||||||
|
if (chk->area == NULL) {
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(-1, ssize_t, "%ld");
|
||||||
|
}
|
||||||
|
else if (n > (chk->size - chk->data)) {
|
||||||
|
FLT_OT_ERR("chunk size too small");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(-1, ssize_t, "%ld");
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)memcpy(chk->area + chk->data, src, n);
|
||||||
|
chk->data += n;
|
||||||
|
|
||||||
|
FLT_OT_RETURN_EX(chk->data, ssize_t, "%ld");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_args_count -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_args_count(char **args)
|
||||||
|
{
|
||||||
|
int i, retval = 0;
|
||||||
|
|
||||||
|
if (args == NULL)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is possible that some arguments within the configuration line
|
||||||
|
* are not specified; that is, they are set to a blank string.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* keyword '' arg_2
|
||||||
|
*
|
||||||
|
* In that case the content of the args field will be like this:
|
||||||
|
* args[0]: 'keyword'
|
||||||
|
* args[1]: NULL pointer
|
||||||
|
* args[2]: 'arg_2'
|
||||||
|
* args[3 .. MAX_LINE_ARGS): NULL pointers
|
||||||
|
*
|
||||||
|
* The total number of arguments is the index of the last argument
|
||||||
|
* (increased by 1) that is not a NULL pointer.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < MAX_LINE_ARGS; i++)
|
||||||
|
if (FLT_OT_ARG_ISVALID(i))
|
||||||
|
retval = i + 1;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_args_to_str -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* args -
|
||||||
|
* idx -
|
||||||
|
* str -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_args_to_str(char **args, int idx, char **str)
|
||||||
|
{
|
||||||
|
int i, argc;
|
||||||
|
|
||||||
|
if ((args == NULL) || (*args == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
argc = flt_ot_args_count(args);
|
||||||
|
|
||||||
|
for (i = idx; i < argc; i++)
|
||||||
|
(void)memprintf(str, "%s%s%s", (*str == NULL) ? "" : *str, (i == idx) ? "" : " ", (args[i] == NULL) ? "" : args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_strtod -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* nptr -
|
||||||
|
* limit_min -
|
||||||
|
* limit_max -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
double flt_ot_strtod(const char *nptr, double limit_min, double limit_max, char **err)
|
||||||
|
{
|
||||||
|
char *endptr = NULL;
|
||||||
|
double retval;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
retval = strtod(nptr, &endptr);
|
||||||
|
if ((errno != 0) || FLT_OT_STR_ISVALID(endptr))
|
||||||
|
FLT_OT_ERR("'%s' : invalid value", nptr);
|
||||||
|
else if (!FLT_OT_IN_RANGE(retval, limit_min, limit_max))
|
||||||
|
FLT_OT_ERR("'%s' : value out of range [%.2f, %.2f]", nptr, limit_min, limit_max);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_strtoll -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* nptr -
|
||||||
|
* limit_min -
|
||||||
|
* limit_max -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int64_t flt_ot_strtoll(const char *nptr, int64_t limit_min, int64_t limit_max, char **err)
|
||||||
|
{
|
||||||
|
char *endptr = NULL;
|
||||||
|
int64_t retval;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
retval = strtoll(nptr, &endptr, 0);
|
||||||
|
if ((errno != 0) || FLT_OT_STR_ISVALID(endptr))
|
||||||
|
FLT_OT_ERR("'%s' : invalid value", nptr);
|
||||||
|
else if (!FLT_OT_IN_RANGE(retval, limit_min, limit_max))
|
||||||
|
FLT_OT_ERR("'%s' : value out of range [%" PRId64 ", %" PRId64 "]", nptr, limit_min, limit_max);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_sample_to_str -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* data -
|
||||||
|
* value -
|
||||||
|
* size -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_sample_to_str(const struct sample_data *data, char *value, size_t size, char **err)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %p, %zu, %p:%p", data, value, size, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if ((data == NULL) || (value == NULL) || (size == 0))
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
*value = '\0';
|
||||||
|
|
||||||
|
if (data->type == SMP_T_ANY) {
|
||||||
|
FLT_OT_ERR("invalid sample data type %d", data->type);
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_BOOL) {
|
||||||
|
value[0] = data->u.sint ? '1' : '0';
|
||||||
|
value[1] = '\0';
|
||||||
|
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_SINT) {
|
||||||
|
retval = snprintf(value, size, "%lld", data->u.sint);
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_ADDR) {
|
||||||
|
/* This type is never used to qualify a sample. */
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_IPV4) {
|
||||||
|
if (INET_ADDRSTRLEN > size)
|
||||||
|
FLT_OT_ERR("sample data size too large");
|
||||||
|
else if (inet_ntop(AF_INET, &(data->u.ipv4), value, INET_ADDRSTRLEN) == NULL)
|
||||||
|
FLT_OT_ERR("invalid IPv4 address");
|
||||||
|
else
|
||||||
|
retval = strlen(value);
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_IPV6) {
|
||||||
|
if (INET6_ADDRSTRLEN > size)
|
||||||
|
FLT_OT_ERR("sample data size too large");
|
||||||
|
else if (inet_ntop(AF_INET6, &(data->u.ipv6), value, INET6_ADDRSTRLEN) == NULL)
|
||||||
|
FLT_OT_ERR("invalid IPv6 address");
|
||||||
|
else
|
||||||
|
retval = strlen(value);
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_STR) {
|
||||||
|
if (data->u.str.data >= size) {
|
||||||
|
FLT_OT_ERR("sample data size too large");
|
||||||
|
}
|
||||||
|
else if (data->u.str.data > 0) {
|
||||||
|
retval = data->u.str.data;
|
||||||
|
memcpy(value, data->u.str.area, retval);
|
||||||
|
value[retval] = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* There is no content to add but we will still return
|
||||||
|
* the correct status.
|
||||||
|
*/
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_BIN) {
|
||||||
|
FLT_OT_ERR("invalid sample data type %d", data->type);
|
||||||
|
}
|
||||||
|
else if (data->type != SMP_T_METH) {
|
||||||
|
FLT_OT_ERR("invalid sample data type %d", data->type);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_OPTIONS) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_OPTIONS);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_OPTIONS, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_GET) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_GET);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_GET, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_HEAD) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_HEAD);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_HEAD, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_POST) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_POST);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_POST, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_PUT) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_PUT);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_PUT, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_DELETE) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_DELETE);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_DELETE, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_TRACE) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_TRACE);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_TRACE, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_CONNECT) {
|
||||||
|
retval = FLT_OT_STR_SIZE(HTTP_METH_STR_CONNECT);
|
||||||
|
|
||||||
|
(void)memcpy(value, HTTP_METH_STR_CONNECT, retval + 1);
|
||||||
|
}
|
||||||
|
else if (data->u.meth.meth == HTTP_METH_OTHER) {
|
||||||
|
if (data->u.meth.str.data >= size) {
|
||||||
|
FLT_OT_ERR("sample data size too large");
|
||||||
|
} else {
|
||||||
|
retval = data->u.meth.str.data;
|
||||||
|
memcpy(value, data->u.meth.str.area, retval);
|
||||||
|
value[retval] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FLT_OT_ERR("invalid HTTP method");
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_sample_to_value -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* key -
|
||||||
|
* data -
|
||||||
|
* value -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_sample_to_value(const char *key, const struct sample_data *data, struct otc_value *value, char **err)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", %p, %p, %p:%p", key, data, value, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if ((data == NULL) || (value == NULL))
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
if (data->type == SMP_T_BOOL) {
|
||||||
|
value->type = otc_value_bool;
|
||||||
|
value->value.bool_value = data->u.sint ? 1 : 0;
|
||||||
|
|
||||||
|
retval = sizeof(value->value.bool_value);
|
||||||
|
}
|
||||||
|
else if (data->type == SMP_T_SINT) {
|
||||||
|
value->type = otc_value_int64;
|
||||||
|
value->value.int64_value = data->u.sint;
|
||||||
|
|
||||||
|
retval = sizeof(value->value.int64_value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value->type = otc_value_string;
|
||||||
|
value->value.string_value = FLT_OT_MALLOC(global.tune.bufsize);
|
||||||
|
|
||||||
|
if (value->value.string_value == NULL)
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
else
|
||||||
|
retval = flt_ot_sample_to_str(data, (char *)value->value.string_value, global.tune.bufsize, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_sample_add -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* dir -
|
||||||
|
* sample -
|
||||||
|
* data -
|
||||||
|
* type -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* Returns a negative value if an error occurs, 0 if it needs to wait,
|
||||||
|
* any other value otherwise.
|
||||||
|
*/
|
||||||
|
int flt_ot_sample_add(struct stream *s, uint dir, struct flt_ot_conf_sample *sample, struct flt_ot_scope_data *data, int type, char **err)
|
||||||
|
{
|
||||||
|
const struct flt_ot_conf_sample_expr *expr;
|
||||||
|
struct sample smp;
|
||||||
|
struct otc_value value;
|
||||||
|
struct buffer buffer;
|
||||||
|
int idx = 0, rc, retval = FLT_OT_RET_OK;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %u, %p, %p, %d, %p:%p", s, dir, data, sample, type, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
FLT_OT_DBG_CONF_SAMPLE("sample ", sample);
|
||||||
|
|
||||||
|
(void)memset(&buffer, 0, sizeof(buffer));
|
||||||
|
|
||||||
|
list_for_each_entry(expr, &(sample->exprs), list) {
|
||||||
|
FLT_OT_DBG_CONF_SAMPLE_EXPR("sample expression ", expr);
|
||||||
|
|
||||||
|
(void)memset(&smp, 0, sizeof(smp));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have only one expression to process, then the data
|
||||||
|
* type that is the result of the expression is converted to
|
||||||
|
* an equivalent data type (if possible) that is written to
|
||||||
|
* the tracer.
|
||||||
|
*
|
||||||
|
* If conversion is not possible, or if we have multiple
|
||||||
|
* expressions to process, then the result is converted to
|
||||||
|
* a string and as such sent to the tracer.
|
||||||
|
*/
|
||||||
|
if (sample_process(s->be, s->sess, s, dir | SMP_OPT_FINAL, expr->expr, &smp) != NULL) {
|
||||||
|
FLT_OT_DBG(3, "data type %d: '%s'", smp.data.type, expr->value);
|
||||||
|
} else {
|
||||||
|
FLT_OT_DBG(2, "WARNING: failed to fetch '%s' value", expr->value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case the fetch failed, we will set the result
|
||||||
|
* (sample) to an empty static string.
|
||||||
|
*/
|
||||||
|
(void)memset(&(smp.data), 0, sizeof(smp.data));
|
||||||
|
smp.data.type = SMP_T_STR;
|
||||||
|
smp.data.u.str.area = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sample->num_exprs == 1) && (type == FLT_OT_EVENT_SAMPLE_TAG)) {
|
||||||
|
if (flt_ot_sample_to_value(sample->key, &(smp.data), &value, err) == -1)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
} else {
|
||||||
|
if (buffer.area == NULL) {
|
||||||
|
chunk_init(&buffer, FLT_OT_CALLOC(1, global.tune.bufsize), global.tune.bufsize);
|
||||||
|
if (buffer.area == NULL) {
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = flt_ot_sample_to_str(&(smp.data), buffer.area + buffer.data, buffer.size - buffer.data, err);
|
||||||
|
if (rc == -1) {
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
} else {
|
||||||
|
buffer.data += rc;
|
||||||
|
|
||||||
|
if (sample->num_exprs == ++idx) {
|
||||||
|
value.type = otc_value_string;
|
||||||
|
value.value.string_value = buffer.area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval == FLT_OT_RET_ERROR) {
|
||||||
|
/* Do nothing. */
|
||||||
|
}
|
||||||
|
else if (type == FLT_OT_EVENT_SAMPLE_TAG) {
|
||||||
|
struct otc_tag *tag = data->tags + data->num_tags++;
|
||||||
|
|
||||||
|
tag->key = sample->key;
|
||||||
|
(void)memcpy(&(tag->value), &value, sizeof(tag->value));
|
||||||
|
}
|
||||||
|
else if (type == FLT_OT_EVENT_SAMPLE_LOG) {
|
||||||
|
struct otc_log_field *log_field = data->log_fields + data->num_log_fields++;
|
||||||
|
|
||||||
|
log_field->key = sample->key;
|
||||||
|
(void)memcpy(&(log_field->value), &value, sizeof(log_field->value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (data->baggage == NULL)
|
||||||
|
data->baggage = otc_text_map_new(NULL, FLT_OT_MAXBAGGAGES);
|
||||||
|
|
||||||
|
if (data->baggage == NULL) {
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
else if (otc_text_map_add(data->baggage, sample->key, 0, value.value.string_value, 0, 0) == -1) {
|
||||||
|
FLT_OT_ERR("out of memory");
|
||||||
|
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FLT_OT_DBG(3, "baggage[%zu]: '%s' -> '%s'", data->baggage->count - 1, data->baggage->key[data->baggage->count - 1], data->baggage->value[data->baggage->count - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
841
addons/ot/src/vars.c
Normal file
841
addons/ot/src/vars.c
Normal file
|
|
@ -0,0 +1,841 @@
|
||||||
|
/***
|
||||||
|
* Copyright 2020 HAProxy Technologies
|
||||||
|
*
|
||||||
|
* This file is part of the HAProxy OpenTracing filter.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include "../include/include.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_OT
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_vars_scope_dump -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* vars -
|
||||||
|
* scope -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* Function prints the contents of all variables defined for a particular
|
||||||
|
* scope.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
static void flt_ot_vars_scope_dump(struct vars *vars, const char *scope)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (vars == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vars_rdlock(vars);
|
||||||
|
for (i = 0; i < VAR_NAME_ROOTS; i++) {
|
||||||
|
struct ceb_node *node = cebu64_imm_first(&(vars->name_root[i]));
|
||||||
|
|
||||||
|
for ( ; node != NULL; node = cebu64_imm_next(&(vars->name_root[i]), node)) {
|
||||||
|
struct var *var = container_of(node, struct var, name_node);
|
||||||
|
|
||||||
|
FLT_OT_DBG(2, "'%s.%016" PRIx64 "' -> '%.*s'", scope, var->name_hash, (int)b_data(&(var->data.u.str)), b_orig(&(var->data.u.str)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vars_rdunlock(vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_vars_dump -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* Function prints the contents of all variables grouped by individual
|
||||||
|
* scope.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
void flt_ot_vars_dump(struct stream *s)
|
||||||
|
{
|
||||||
|
FLT_OT_FUNC("%p", s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It would be nice if we could use the get_vars() function from HAProxy
|
||||||
|
* source here to get the value of the 'vars' pointer, but it is defined
|
||||||
|
* as 'static inline', so unfortunately none of this is possible.
|
||||||
|
*/
|
||||||
|
flt_ot_vars_scope_dump(&(proc_vars), "PROC");
|
||||||
|
flt_ot_vars_scope_dump(&(s->sess->vars), "SESS");
|
||||||
|
flt_ot_vars_scope_dump(&(s->vars_txn), "TXN");
|
||||||
|
flt_ot_vars_scope_dump(&(s->vars_reqres), "REQ/RES");
|
||||||
|
|
||||||
|
FLT_OT_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DEBUG_OT */
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_smp_init -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* smp -
|
||||||
|
* opt -
|
||||||
|
* type -
|
||||||
|
* data -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* The function initializes the value of the 'smp' structure. If the 'data'
|
||||||
|
* argument is set, then the 'sample_data' member of the 'smp' structure is
|
||||||
|
* also initialized.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* This function does not return a value.
|
||||||
|
*/
|
||||||
|
static inline void flt_ot_smp_init(struct stream *s, struct sample *smp, uint opt, int type, const char *data)
|
||||||
|
{
|
||||||
|
(void)memset(smp, 0, sizeof(*smp));
|
||||||
|
(void)smp_set_owner(smp, s->be, s->sess, s, opt | SMP_OPT_FINAL);
|
||||||
|
|
||||||
|
if (data != NULL) {
|
||||||
|
smp->data.type = type;
|
||||||
|
|
||||||
|
chunk_initstr(&(smp->data.u.str), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_smp_add -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* data -
|
||||||
|
* blk -
|
||||||
|
* len -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_smp_add(struct sample_data *data, const char *name, size_t len, char **err)
|
||||||
|
{
|
||||||
|
bool flag_alloc = 0;
|
||||||
|
int retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%.*s\", %zu, %p:%p", data, (int)len, name, len, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
FLT_OT_DBG_BUF(2, &(data->u.str));
|
||||||
|
|
||||||
|
if (b_orig(&(data->u.str)) == NULL) {
|
||||||
|
data->type = SMP_T_BIN;
|
||||||
|
chunk_init(&(data->u.str), FLT_OT_MALLOC(global.tune.bufsize), global.tune.bufsize);
|
||||||
|
|
||||||
|
flag_alloc = (b_orig(&(data->u.str)) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b_orig(&(data->u.str)) == NULL) {
|
||||||
|
FLT_OT_ERR("failed to add ctx '%.*s', not enough memory", (int)len, name);
|
||||||
|
}
|
||||||
|
else if (len > ((UINT64_C(1) << ((sizeof(FLT_OT_VAR_CTX_SIZE) << 3) - 1)) - 1)) {
|
||||||
|
FLT_OT_ERR("failed to add ctx '%.*s', too long name", (int)len, name);
|
||||||
|
}
|
||||||
|
else if ((len + sizeof(FLT_OT_VAR_CTX_SIZE)) > b_room(&(data->u.str))) {
|
||||||
|
FLT_OT_ERR("failed to add ctx '%.*s', too many names", (int)len, name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
retval = b_data(&(data->u.str));
|
||||||
|
|
||||||
|
b_putchr(&(data->u.str), len);
|
||||||
|
(void)__b_putblk(&(data->u.str), name, len);
|
||||||
|
|
||||||
|
FLT_OT_DBG_BUF(2, &(data->u.str));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((retval == FLT_OT_RET_ERROR) && flag_alloc)
|
||||||
|
FLT_OT_FREE(b_orig(&(data->u.str)));
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_normalize_name -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* var_name -
|
||||||
|
* size -
|
||||||
|
* len -
|
||||||
|
* name -
|
||||||
|
* flag_cpy -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_normalize_name(char *var_name, size_t size, int *len, const char *name, bool flag_cpy, char **err)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %zu, %p, \"%s\", %hhu, %p:%p", var_name, size, len, name, flag_cpy, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (!FLT_OT_STR_ISVALID(name))
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case the name of the variable consists of several elements,
|
||||||
|
* the character '.' is added between them.
|
||||||
|
*/
|
||||||
|
if ((*len == 0) || (var_name[*len - 1] == '.'))
|
||||||
|
/* Do nothing. */;
|
||||||
|
else if (*len < (size - 1))
|
||||||
|
var_name[(*len)++] = '.';
|
||||||
|
else {
|
||||||
|
FLT_OT_ERR("failed to normalize variable name, buffer too small");
|
||||||
|
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag_cpy) {
|
||||||
|
/* Copy variable name without modification. */
|
||||||
|
retval = strlen(name);
|
||||||
|
if ((*len + retval + 1) > size) {
|
||||||
|
FLT_OT_ERR("failed to normalize variable name, buffer too small");
|
||||||
|
|
||||||
|
retval = -1;
|
||||||
|
} else {
|
||||||
|
(void)memcpy(var_name + *len, name, retval + 1);
|
||||||
|
|
||||||
|
*len += retval;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* HAProxy does not allow the use of variable names containing '-'
|
||||||
|
* or ' '. This of course applies to HTTP header names as well.
|
||||||
|
* Also, here the capital letters are converted to lowercase.
|
||||||
|
*/
|
||||||
|
while (retval != -1)
|
||||||
|
if (*len >= (size - 1)) {
|
||||||
|
FLT_OT_ERR("failed to normalize variable name, buffer too small");
|
||||||
|
|
||||||
|
retval = -1;
|
||||||
|
} else {
|
||||||
|
uint8_t ch = name[retval];
|
||||||
|
|
||||||
|
if (ch == '\0')
|
||||||
|
break;
|
||||||
|
else if (ch == '-')
|
||||||
|
ch = FLT_OT_VAR_CHAR_DASH;
|
||||||
|
else if (ch == ' ')
|
||||||
|
ch = FLT_OT_VAR_CHAR_SPACE;
|
||||||
|
else if (isupper(ch))
|
||||||
|
ch = ist_lc[ch];
|
||||||
|
|
||||||
|
var_name[(*len)++] = ch;
|
||||||
|
retval++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var_name[*len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_DBG(3, "var_name: \"%s\" %d/%d", var_name, retval, *len);
|
||||||
|
|
||||||
|
if (retval == -1)
|
||||||
|
*len = retval;
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_var_name -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* flag_cpy -
|
||||||
|
* var_name -
|
||||||
|
* size -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* The function initializes the value of the 'smp' structure. If the 'data'
|
||||||
|
* argument is set, then the 'sample_data' member of the 'smp' structure is
|
||||||
|
* also initialized.
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_var_name(const char *scope, const char *prefix, const char *name, bool flag_cpy, char *var_name, size_t size, char **err)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", \"%s\", \"%s\", %hhu, %p, %zu, %p:%p", scope, prefix, name, flag_cpy, var_name, size, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
if (flt_ot_normalize_name(var_name, size, &retval, scope, 0, err) >= 0)
|
||||||
|
if (flt_ot_normalize_name(var_name, size, &retval, prefix, 0, err) >= 0)
|
||||||
|
(void)flt_ot_normalize_name(var_name, size, &retval, name, flag_cpy, err);
|
||||||
|
|
||||||
|
if (retval == -1)
|
||||||
|
FLT_OT_ERR("failed to construct variable name '%s.%s.%s'", scope, prefix, name);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_ctx_loop -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* smp -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* err -
|
||||||
|
* func -
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_ctx_loop(struct sample *smp, const char *scope, const char *prefix, char **err, flt_ot_ctx_loop_cb func, void *ptr)
|
||||||
|
{
|
||||||
|
FLT_OT_VAR_CTX_SIZE var_ctx_size;
|
||||||
|
char var_name[BUFSIZ], var_ctx[BUFSIZ];
|
||||||
|
int i, var_name_len, var_ctx_len, rc, n = 1, retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %p:%p, %p, %p", smp, scope, prefix, FLT_OT_DPTR_ARGS(err), func, ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The variable in which we will save the name of the OpenTracing
|
||||||
|
* context variable.
|
||||||
|
*/
|
||||||
|
var_name_len = flt_ot_var_name(scope, prefix, NULL, 0, var_name, sizeof(var_name), err);
|
||||||
|
if (var_name_len == -1)
|
||||||
|
FLT_OT_RETURN_INT(FLT_OT_RET_ERROR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we will try to find all the previously recorded variables from
|
||||||
|
* the currently set OpenTracing context. If we find the required
|
||||||
|
* variable and it is marked as deleted, we will mark it as active.
|
||||||
|
* If we do not find it, then it is added to the end of the previously
|
||||||
|
* saved names.
|
||||||
|
*/
|
||||||
|
if (vars_get_by_name(var_name, var_name_len, smp, NULL) == 0) {
|
||||||
|
FLT_OT_DBG(2, "ctx '%s' no variable found", var_name);
|
||||||
|
}
|
||||||
|
else if (smp->data.type != SMP_T_BIN) {
|
||||||
|
FLT_OT_ERR("ctx '%s' invalid data type %d", var_name, smp->data.type);
|
||||||
|
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FLT_OT_DBG_BUF(2, &(smp->data.u.str));
|
||||||
|
|
||||||
|
for (i = 0; i < b_data(&(smp->data.u.str)); i += sizeof(var_ctx_size) + var_ctx_len, n++) {
|
||||||
|
var_ctx_size = *((typeof(var_ctx_size) *)(b_orig(&(smp->data.u.str)) + i));
|
||||||
|
var_ctx_len = abs(var_ctx_size);
|
||||||
|
|
||||||
|
if ((i + sizeof(var_ctx_size) + var_ctx_len) > b_data(&(smp->data.u.str))) {
|
||||||
|
FLT_OT_ERR("ctx '%s' invalid data size", var_name);
|
||||||
|
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)memcpy(var_ctx, b_orig(&(smp->data.u.str)) + i + sizeof(var_ctx_size), var_ctx_len);
|
||||||
|
var_ctx[var_ctx_len] = '\0';
|
||||||
|
|
||||||
|
rc = func(smp, i, scope, prefix, var_ctx, var_ctx_size, err, ptr);
|
||||||
|
if (rc == FLT_OT_RET_ERROR) {
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (rc > 0) {
|
||||||
|
retval = n;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_ctx_set_cb -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* smp -
|
||||||
|
* idx -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* name_len -
|
||||||
|
* err -
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_ctx_set_cb(struct sample *smp, size_t idx, const char *scope, const char *prefix, const char *name, FLT_OT_VAR_CTX_SIZE name_len, char **err, void *ptr)
|
||||||
|
{
|
||||||
|
struct flt_ot_ctx *ctx = ptr;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %zu, \"%s\", \"%s\", \"%s\", %hhd, %p:%p, %p", smp, idx, scope, prefix, name, name_len, FLT_OT_DPTR_ARGS(err), ptr);
|
||||||
|
|
||||||
|
if ((name_len == ctx->value_len) && (strncmp(name, ctx->value, name_len) == 0)) {
|
||||||
|
FLT_OT_DBG(2, "ctx '%s' found\n", name);
|
||||||
|
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_ctx_set -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* opt -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_ctx_set(struct stream *s, const char *scope, const char *prefix, const char *name, uint opt, char **err)
|
||||||
|
{
|
||||||
|
struct flt_ot_ctx ctx;
|
||||||
|
struct sample smp_ctx;
|
||||||
|
char var_name[BUFSIZ];
|
||||||
|
bool flag_alloc = 0;
|
||||||
|
int rc, var_name_len, retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, name, opt, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The variable in which we will save the name of the OpenTracing
|
||||||
|
* context variable.
|
||||||
|
*/
|
||||||
|
var_name_len = flt_ot_var_name(scope, prefix, NULL, 0, var_name, sizeof(var_name), err);
|
||||||
|
if (var_name_len == -1)
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
/* Normalized name of the OpenTracing context variable. */
|
||||||
|
ctx.value_len = flt_ot_var_name(name, NULL, NULL, 0, ctx.value, sizeof(ctx.value), err);
|
||||||
|
if (ctx.value_len == -1)
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
||||||
|
|
||||||
|
retval = flt_ot_ctx_loop(&smp_ctx, scope, prefix, err, flt_ot_ctx_set_cb, &ctx);
|
||||||
|
if (retval == 0) {
|
||||||
|
rc = flt_ot_smp_add(&(smp_ctx.data), ctx.value, ctx.value_len, err);
|
||||||
|
if (rc == FLT_OT_RET_ERROR)
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
flag_alloc = (rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval == FLT_OT_RET_ERROR) {
|
||||||
|
/* Do nothing. */
|
||||||
|
}
|
||||||
|
else if (retval > 0) {
|
||||||
|
FLT_OT_DBG(2, "ctx '%s' data found", ctx.value);
|
||||||
|
}
|
||||||
|
else if (vars_set_by_name_ifexist(var_name, var_name_len, &smp_ctx) == 0) {
|
||||||
|
FLT_OT_ERR("failed to set ctx '%s'", var_name);
|
||||||
|
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FLT_OT_DBG(2, "ctx '%s' -> '%.*s' set", var_name, (int)b_data(&(smp_ctx.data.u.str)), b_orig(&(smp_ctx.data.u.str)));
|
||||||
|
|
||||||
|
retval = b_data(&(smp_ctx.data.u.str));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag_alloc)
|
||||||
|
FLT_OT_FREE(b_orig(&(smp_ctx.data.u.str)));
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_var_register -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_var_register(const char *scope, const char *prefix, const char *name, char **err)
|
||||||
|
{
|
||||||
|
struct arg arg;
|
||||||
|
char var_name[BUFSIZ];
|
||||||
|
int retval = -1, var_name_len;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("\"%s\", \"%s\", \"%s\", %p:%p", scope, prefix, name, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
var_name_len = flt_ot_var_name(scope, prefix, name, 0, var_name, sizeof(var_name), err);
|
||||||
|
if (var_name_len == -1)
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
/* Set <size> to 0 to not release var_name memory in vars_check_arg(). */
|
||||||
|
(void)memset(&arg, 0, sizeof(arg));
|
||||||
|
arg.type = ARGT_STR;
|
||||||
|
arg.data.str.area = var_name;
|
||||||
|
arg.data.str.data = var_name_len;
|
||||||
|
|
||||||
|
if (vars_check_arg(&arg, err) == 0) {
|
||||||
|
FLT_OT_ERR_APPEND("failed to register variable '%s': %s", var_name, *err);
|
||||||
|
} else {
|
||||||
|
FLT_OT_DBG(2, "variable '%s' registered", var_name);
|
||||||
|
|
||||||
|
retval = var_name_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_var_set -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* value -
|
||||||
|
* opt -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_var_set(struct stream *s, const char *scope, const char *prefix, const char *name, const char *value, uint opt, char **err)
|
||||||
|
{
|
||||||
|
struct sample smp;
|
||||||
|
char var_name[BUFSIZ];
|
||||||
|
int retval = -1, var_name_len;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, name, value, opt, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
var_name_len = flt_ot_var_name(scope, prefix, name, 0, var_name, sizeof(var_name), err);
|
||||||
|
if (var_name_len == -1)
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
|
||||||
|
flt_ot_smp_init(s, &smp, opt, SMP_T_STR, value);
|
||||||
|
|
||||||
|
if (vars_set_by_name_ifexist(var_name, var_name_len, &smp) == 0) {
|
||||||
|
FLT_OT_ERR("failed to set variable '%s'", var_name);
|
||||||
|
} else {
|
||||||
|
FLT_OT_DBG(2, "variable '%s' set", var_name);
|
||||||
|
|
||||||
|
retval = var_name_len;
|
||||||
|
|
||||||
|
if (strcmp(scope, FLT_OT_VARS_SCOPE) == 0)
|
||||||
|
retval = flt_ot_ctx_set(s, scope, prefix, name, opt, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_vars_unset_cb -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* smp -
|
||||||
|
* idx -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* name_len -
|
||||||
|
* err -
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_vars_unset_cb(struct sample *smp, size_t idx, const char *scope, const char *prefix, const char *name, FLT_OT_VAR_CTX_SIZE name_len, char **err, void *ptr)
|
||||||
|
{
|
||||||
|
struct sample smp_ctx;
|
||||||
|
char var_ctx[BUFSIZ];
|
||||||
|
int var_ctx_len, retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %zu, \"%s\", \"%s\", \"%s\", %hhd, %p:%p, %p", smp, idx, scope, prefix, name, name_len, FLT_OT_DPTR_ARGS(err), ptr);
|
||||||
|
|
||||||
|
var_ctx_len = flt_ot_var_name(scope, prefix, name, 1, var_ctx, sizeof(var_ctx), err);
|
||||||
|
if (var_ctx_len == -1) {
|
||||||
|
FLT_OT_ERR("ctx '%s' invalid", name);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
flt_ot_smp_init(smp->strm, &smp_ctx, smp->opt, 0, NULL);
|
||||||
|
|
||||||
|
if (vars_unset_by_name_ifexist(var_ctx, var_ctx_len, &smp_ctx) == 0) {
|
||||||
|
FLT_OT_ERR("ctx '%s' no variable found", var_ctx);
|
||||||
|
} else {
|
||||||
|
FLT_OT_DBG(2, "ctx '%s' unset", var_ctx);
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_vars_unset -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* opt -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
int flt_ot_vars_unset(struct stream *s, const char *scope, const char *prefix, uint opt, char **err)
|
||||||
|
{
|
||||||
|
struct sample smp_ctx;
|
||||||
|
char var_name[BUFSIZ];
|
||||||
|
int var_name_len, retval;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, opt, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
||||||
|
|
||||||
|
retval = flt_ot_ctx_loop(&smp_ctx, scope, prefix, err, flt_ot_vars_unset_cb, NULL);
|
||||||
|
if (retval != FLT_OT_RET_ERROR) {
|
||||||
|
/*
|
||||||
|
* After all ctx variables have been unset, the variable used
|
||||||
|
* to store their names should also be unset.
|
||||||
|
*/
|
||||||
|
var_name_len = flt_ot_var_name(scope, prefix, NULL, 0, var_name, sizeof(var_name), err);
|
||||||
|
if (var_name_len == -1)
|
||||||
|
FLT_OT_RETURN_INT(FLT_OT_RET_ERROR);
|
||||||
|
|
||||||
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
||||||
|
|
||||||
|
if (vars_unset_by_name_ifexist(var_name, var_name_len, &smp_ctx) == 0) {
|
||||||
|
FLT_OT_DBG(2, "variable '%s' not found", var_name);
|
||||||
|
} else {
|
||||||
|
FLT_OT_DBG(2, "variable '%s' unset", var_name);
|
||||||
|
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_vars_get_cb -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* smp -
|
||||||
|
* idx -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* name -
|
||||||
|
* name_len -
|
||||||
|
* err -
|
||||||
|
* ptr -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
static int flt_ot_vars_get_cb(struct sample *smp, size_t idx, const char *scope, const char *prefix, const char *name, FLT_OT_VAR_CTX_SIZE name_len, char **err, void *ptr)
|
||||||
|
{
|
||||||
|
struct otc_text_map **map = ptr;
|
||||||
|
struct sample smp_ctx;
|
||||||
|
char var_ctx[BUFSIZ], ot_var_name[BUFSIZ], ch;
|
||||||
|
int var_ctx_len, ot_var_name_len, retval = FLT_OT_RET_ERROR;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, %zu, \"%s\", \"%s\", \"%s\", %hhd, %p:%p, %p", smp, idx, scope, prefix, name, name_len, FLT_OT_DPTR_ARGS(err), ptr);
|
||||||
|
|
||||||
|
var_ctx_len = flt_ot_var_name(scope, prefix, name, 1, var_ctx, sizeof(var_ctx), err);
|
||||||
|
if (var_ctx_len == -1) {
|
||||||
|
FLT_OT_ERR("ctx '%s' invalid", name);
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
flt_ot_smp_init(smp->strm, &smp_ctx, smp->opt, 0, NULL);
|
||||||
|
|
||||||
|
if (vars_get_by_name(var_ctx, var_ctx_len, &smp_ctx, NULL) != 0) {
|
||||||
|
FLT_OT_DBG(2, "'%s' -> '%.*s'", var_ctx, (int)b_data(&(smp_ctx.data.u.str)), b_orig(&(smp_ctx.data.u.str)));
|
||||||
|
|
||||||
|
if (*map == NULL) {
|
||||||
|
*map = otc_text_map_new(NULL, 8);
|
||||||
|
if (*map == NULL) {
|
||||||
|
FLT_OT_ERR("failed to create map data");
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(FLT_OT_RET_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Eh, because the use of some characters is not allowed
|
||||||
|
* in the variable name, the conversion of the replaced
|
||||||
|
* characters to the original is performed here.
|
||||||
|
*/
|
||||||
|
for (ot_var_name_len = 0; (ch = name[ot_var_name_len]) != '\0'; ot_var_name_len++)
|
||||||
|
if (ot_var_name_len >= (FLT_OT_TABLESIZE(ot_var_name) - 1)) {
|
||||||
|
FLT_OT_ERR("failed to reverse variable name, buffer too small");
|
||||||
|
|
||||||
|
otc_text_map_destroy(map, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ot_var_name[ot_var_name_len] = (ch == FLT_OT_VAR_CHAR_DASH) ? '-' : ((ch == FLT_OT_VAR_CHAR_SPACE) ? ' ' : ch);
|
||||||
|
}
|
||||||
|
ot_var_name[ot_var_name_len] = '\0';
|
||||||
|
|
||||||
|
if (*map == NULL) {
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
else if (otc_text_map_add(*map, ot_var_name, ot_var_name_len, b_orig(&(smp_ctx.data.u.str)), b_data(&(smp_ctx.data.u.str)), OTC_TEXT_MAP_DUP_KEY | OTC_TEXT_MAP_DUP_VALUE) == -1) {
|
||||||
|
FLT_OT_ERR("failed to add map data");
|
||||||
|
|
||||||
|
otc_text_map_destroy(map, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
|
||||||
|
retval = FLT_OT_RET_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FLT_OT_DBG(2, "ctx '%s' no variable found", var_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_INT(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* NAME
|
||||||
|
* flt_ot_vars_get -
|
||||||
|
*
|
||||||
|
* ARGUMENTS
|
||||||
|
* s -
|
||||||
|
* scope -
|
||||||
|
* prefix -
|
||||||
|
* opt -
|
||||||
|
* err -
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
* -
|
||||||
|
*
|
||||||
|
* RETURN VALUE
|
||||||
|
* -
|
||||||
|
*/
|
||||||
|
struct otc_text_map *flt_ot_vars_get(struct stream *s, const char *scope, const char *prefix, uint opt, char **err)
|
||||||
|
{
|
||||||
|
struct sample smp_ctx;
|
||||||
|
struct otc_text_map *retptr = NULL;
|
||||||
|
|
||||||
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, opt, FLT_OT_DPTR_ARGS(err));
|
||||||
|
|
||||||
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
||||||
|
|
||||||
|
(void)flt_ot_ctx_loop(&smp_ctx, scope, prefix, err, flt_ot_vars_get_cb, &retptr);
|
||||||
|
|
||||||
|
ot_text_map_show(retptr);
|
||||||
|
|
||||||
|
if ((retptr != NULL) && (retptr->count == 0)) {
|
||||||
|
FLT_OT_DBG(2, "WARNING: no variables found");
|
||||||
|
|
||||||
|
otc_text_map_destroy(&retptr, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLT_OT_RETURN_PTR(retptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* c-indent-level: 8
|
||||||
|
* c-basic-offset: 8
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
||||||
|
*/
|
||||||
111
addons/ot/test/README-speed-cmp
Normal file
111
addons/ot/test/README-speed-cmp
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
--- rate-limit 100.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 650.95us 431.15us 46.44ms 96.67%
|
||||||
|
Req/Sec 1.44k 51.39 2.57k 74.89%
|
||||||
|
Latency Distribution
|
||||||
|
50% 608.00us
|
||||||
|
75% 760.00us
|
||||||
|
90% 0.91ms
|
||||||
|
99% 1.31ms
|
||||||
|
3434836 requests in 5.00m, 0.89GB read
|
||||||
|
Requests/sec: 11446.99
|
||||||
|
Transfer/sec: 3.03MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 50.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 398.00us 371.39us 22.56ms 97.23%
|
||||||
|
Req/Sec 2.32k 84.01 2.76k 74.84%
|
||||||
|
Latency Distribution
|
||||||
|
50% 350.00us
|
||||||
|
75% 467.00us
|
||||||
|
90% 593.00us
|
||||||
|
99% 1.03ms
|
||||||
|
5530848 requests in 5.00m, 1.43GB read
|
||||||
|
Requests/sec: 18434.31
|
||||||
|
Transfer/sec: 4.89MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 10.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 316.75us 351.92us 23.00ms 98.57%
|
||||||
|
Req/Sec 2.87k 94.02 3.22k 79.30%
|
||||||
|
Latency Distribution
|
||||||
|
50% 273.00us
|
||||||
|
75% 342.00us
|
||||||
|
90% 424.00us
|
||||||
|
99% 0.94ms
|
||||||
|
6859293 requests in 5.00m, 1.78GB read
|
||||||
|
Requests/sec: 22862.16
|
||||||
|
Transfer/sec: 6.06MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 2.5 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 307.90us 368.64us 26.08ms 98.71%
|
||||||
|
Req/Sec 2.96k 103.84 3.23k 83.76%
|
||||||
|
Latency Distribution
|
||||||
|
50% 264.00us
|
||||||
|
75% 327.00us
|
||||||
|
90% 402.00us
|
||||||
|
99% 0.97ms
|
||||||
|
7065667 requests in 5.00m, 1.83GB read
|
||||||
|
Requests/sec: 23550.37
|
||||||
|
Transfer/sec: 6.24MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 0.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 304.60us 376.36us 30.26ms 98.74%
|
||||||
|
Req/Sec 2.99k 106.93 3.24k 83.08%
|
||||||
|
Latency Distribution
|
||||||
|
50% 262.00us
|
||||||
|
75% 323.00us
|
||||||
|
90% 396.00us
|
||||||
|
99% 0.95ms
|
||||||
|
7136261 requests in 5.00m, 1.85GB read
|
||||||
|
Requests/sec: 23785.77
|
||||||
|
Transfer/sec: 6.31MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit disabled --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 300.90us 342.35us 22.13ms 98.74%
|
||||||
|
Req/Sec 3.00k 95.67 3.33k 81.11%
|
||||||
|
Latency Distribution
|
||||||
|
50% 261.00us
|
||||||
|
75% 322.00us
|
||||||
|
90% 394.00us
|
||||||
|
99% 806.00us
|
||||||
|
7159525 requests in 5.00m, 1.85GB read
|
||||||
|
Requests/sec: 23863.05
|
||||||
|
Transfer/sec: 6.33MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit off --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 302.51us 371.99us 30.26ms 98.77%
|
||||||
|
Req/Sec 3.00k 104.43 3.73k 83.74%
|
||||||
|
Latency Distribution
|
||||||
|
50% 260.00us
|
||||||
|
75% 321.00us
|
||||||
|
90% 394.00us
|
||||||
|
99% 0.89ms
|
||||||
|
7170345 requests in 5.00m, 1.86GB read
|
||||||
|
Requests/sec: 23898.19
|
||||||
|
Transfer/sec: 6.34MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
111
addons/ot/test/README-speed-ctx
Normal file
111
addons/ot/test/README-speed-ctx
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
--- rate-limit 100.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 2.49ms 799.87us 43.00ms 70.90%
|
||||||
|
Req/Sec 393.01 20.61 696.00 71.68%
|
||||||
|
Latency Distribution
|
||||||
|
50% 2.50ms
|
||||||
|
75% 3.00ms
|
||||||
|
90% 3.38ms
|
||||||
|
99% 4.23ms
|
||||||
|
939237 requests in 5.00m, 249.01MB read
|
||||||
|
Requests/sec: 3130.01
|
||||||
|
Transfer/sec: 849.75KB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 50.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 1.27ms 0.97ms 40.77ms 56.91%
|
||||||
|
Req/Sec 778.22 70.30 1.36k 69.10%
|
||||||
|
Latency Distribution
|
||||||
|
50% 1.36ms
|
||||||
|
75% 1.80ms
|
||||||
|
90% 2.49ms
|
||||||
|
99% 3.51ms
|
||||||
|
1859055 requests in 5.00m, 492.88MB read
|
||||||
|
Requests/sec: 6195.58
|
||||||
|
Transfer/sec: 1.64MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 10.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 442.00us 481.47us 31.61ms 90.27%
|
||||||
|
Req/Sec 2.25k 130.05 2.73k 72.83%
|
||||||
|
Latency Distribution
|
||||||
|
50% 287.00us
|
||||||
|
75% 526.00us
|
||||||
|
90% 0.92ms
|
||||||
|
99% 1.76ms
|
||||||
|
5380213 requests in 5.00m, 1.39GB read
|
||||||
|
Requests/sec: 17930.27
|
||||||
|
Transfer/sec: 4.75MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 2.5 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 346.65us 414.65us 28.50ms 95.63%
|
||||||
|
Req/Sec 2.75k 159.74 3.23k 84.68%
|
||||||
|
Latency Distribution
|
||||||
|
50% 271.00us
|
||||||
|
75% 353.00us
|
||||||
|
90% 505.00us
|
||||||
|
99% 1.55ms
|
||||||
|
6560093 requests in 5.00m, 1.70GB read
|
||||||
|
Requests/sec: 21864.43
|
||||||
|
Transfer/sec: 5.80MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 0.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 313.32us 402.25us 24.73ms 98.55%
|
||||||
|
Req/Sec 2.95k 145.03 3.21k 88.99%
|
||||||
|
Latency Distribution
|
||||||
|
50% 264.00us
|
||||||
|
75% 327.00us
|
||||||
|
90% 403.00us
|
||||||
|
99% 1.33ms
|
||||||
|
7050847 requests in 5.00m, 1.83GB read
|
||||||
|
Requests/sec: 23501.14
|
||||||
|
Transfer/sec: 6.23MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit disabled --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 310.19us 384.76us 22.18ms 98.66%
|
||||||
|
Req/Sec 2.96k 115.62 3.37k 84.30%
|
||||||
|
Latency Distribution
|
||||||
|
50% 265.00us
|
||||||
|
75% 327.00us
|
||||||
|
90% 402.00us
|
||||||
|
99% 1.10ms
|
||||||
|
7058682 requests in 5.00m, 1.83GB read
|
||||||
|
Requests/sec: 23526.70
|
||||||
|
Transfer/sec: 6.24MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit off --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 305.86us 367.56us 25.76ms 98.65%
|
||||||
|
Req/Sec 2.99k 116.93 3.43k 85.59%
|
||||||
|
Latency Distribution
|
||||||
|
50% 261.00us
|
||||||
|
75% 322.00us
|
||||||
|
90% 396.00us
|
||||||
|
99% 1.09ms
|
||||||
|
7137173 requests in 5.00m, 1.85GB read
|
||||||
|
Requests/sec: 23788.84
|
||||||
|
Transfer/sec: 6.31MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
111
addons/ot/test/README-speed-fe-be
Normal file
111
addons/ot/test/README-speed-fe-be
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
--- rate-limit 100.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 0.89ms 466.84us 35.44ms 94.39%
|
||||||
|
Req/Sec 1.09k 39.30 1.32k 72.60%
|
||||||
|
Latency Distribution
|
||||||
|
50% 823.00us
|
||||||
|
75% 1.00ms
|
||||||
|
90% 1.20ms
|
||||||
|
99% 2.14ms
|
||||||
|
2594524 requests in 5.00m, 687.86MB read
|
||||||
|
Requests/sec: 8645.83
|
||||||
|
Transfer/sec: 2.29MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 50.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 681.74us 463.28us 20.45ms 95.46%
|
||||||
|
Req/Sec 1.41k 54.00 1.60k 68.97%
|
||||||
|
Latency Distribution
|
||||||
|
50% 613.00us
|
||||||
|
75% 785.00us
|
||||||
|
90% 0.98ms
|
||||||
|
99% 2.06ms
|
||||||
|
3367473 requests in 5.00m, 0.87GB read
|
||||||
|
Requests/sec: 11222.76
|
||||||
|
Transfer/sec: 2.98MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 10.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 558.32us 458.54us 29.40ms 97.73%
|
||||||
|
Req/Sec 1.72k 60.67 2.05k 73.10%
|
||||||
|
Latency Distribution
|
||||||
|
50% 494.00us
|
||||||
|
75% 610.00us
|
||||||
|
90% 743.00us
|
||||||
|
99% 2.08ms
|
||||||
|
4105420 requests in 5.00m, 1.06GB read
|
||||||
|
Requests/sec: 13683.36
|
||||||
|
Transfer/sec: 3.63MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 2.5 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 542.66us 440.31us 22.63ms 97.88%
|
||||||
|
Req/Sec 1.76k 60.02 2.00k 72.27%
|
||||||
|
Latency Distribution
|
||||||
|
50% 481.00us
|
||||||
|
75% 588.00us
|
||||||
|
90% 710.00us
|
||||||
|
99% 2.05ms
|
||||||
|
4214525 requests in 5.00m, 1.09GB read
|
||||||
|
Requests/sec: 14046.76
|
||||||
|
Transfer/sec: 3.72MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 0.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 529.06us 414.38us 30.09ms 97.97%
|
||||||
|
Req/Sec 1.80k 59.34 2.05k 74.47%
|
||||||
|
Latency Distribution
|
||||||
|
50% 473.00us
|
||||||
|
75% 576.00us
|
||||||
|
90% 692.00us
|
||||||
|
99% 1.79ms
|
||||||
|
4287428 requests in 5.00m, 1.11GB read
|
||||||
|
Requests/sec: 14290.45
|
||||||
|
Transfer/sec: 3.79MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit disabled --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 517.81us 463.10us 36.81ms 98.25%
|
||||||
|
Req/Sec 1.85k 62.39 2.21k 75.65%
|
||||||
|
Latency Distribution
|
||||||
|
50% 458.00us
|
||||||
|
75% 558.00us
|
||||||
|
90% 670.00us
|
||||||
|
99% 1.96ms
|
||||||
|
4416273 requests in 5.00m, 1.14GB read
|
||||||
|
Requests/sec: 14719.43
|
||||||
|
Transfer/sec: 3.90MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit off --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 511.67us 428.18us 27.68ms 98.15%
|
||||||
|
Req/Sec 1.86k 60.67 2.05k 75.44%
|
||||||
|
Latency Distribution
|
||||||
|
50% 455.00us
|
||||||
|
75% 554.00us
|
||||||
|
90% 666.00us
|
||||||
|
99% 1.81ms
|
||||||
|
4441271 requests in 5.00m, 1.15GB read
|
||||||
|
Requests/sec: 14803.32
|
||||||
|
Transfer/sec: 3.92MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
111
addons/ot/test/README-speed-sa
Normal file
111
addons/ot/test/README-speed-sa
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
--- rate-limit 100.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 1.24ms 522.78us 35.59ms 79.12%
|
||||||
|
Req/Sec 767.71 38.72 3.02k 72.19%
|
||||||
|
Latency Distribution
|
||||||
|
50% 1.20ms
|
||||||
|
75% 1.51ms
|
||||||
|
90% 1.78ms
|
||||||
|
99% 2.37ms
|
||||||
|
1834067 requests in 5.00m, 486.25MB read
|
||||||
|
Requests/sec: 6111.57
|
||||||
|
Transfer/sec: 1.62MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 50.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 593.11us 476.81us 43.00ms 91.27%
|
||||||
|
Req/Sec 1.59k 81.15 2.07k 71.14%
|
||||||
|
Latency Distribution
|
||||||
|
50% 549.00us
|
||||||
|
75% 788.00us
|
||||||
|
90% 1.03ms
|
||||||
|
99% 1.62ms
|
||||||
|
3795987 requests in 5.00m, 0.98GB read
|
||||||
|
Requests/sec: 12650.65
|
||||||
|
Transfer/sec: 3.35MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 10.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 326.02us 355.00us 29.23ms 98.05%
|
||||||
|
Req/Sec 2.80k 88.05 3.30k 75.36%
|
||||||
|
Latency Distribution
|
||||||
|
50% 277.00us
|
||||||
|
75% 356.00us
|
||||||
|
90% 456.00us
|
||||||
|
99% 0.97ms
|
||||||
|
6675563 requests in 5.00m, 1.73GB read
|
||||||
|
Requests/sec: 22249.78
|
||||||
|
Transfer/sec: 5.90MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 2.5 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 311.77us 357.45us 24.11ms 98.62%
|
||||||
|
Req/Sec 2.91k 94.70 3.18k 78.52%
|
||||||
|
Latency Distribution
|
||||||
|
50% 268.00us
|
||||||
|
75% 334.00us
|
||||||
|
90% 413.00us
|
||||||
|
99% 0.94ms
|
||||||
|
6960933 requests in 5.00m, 1.80GB read
|
||||||
|
Requests/sec: 23201.07
|
||||||
|
Transfer/sec: 6.15MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit 0.0 --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 302.51us 330.50us 25.84ms 98.69%
|
||||||
|
Req/Sec 2.98k 91.46 3.40k 78.84%
|
||||||
|
Latency Distribution
|
||||||
|
50% 263.00us
|
||||||
|
75% 325.00us
|
||||||
|
90% 397.00us
|
||||||
|
99% 812.00us
|
||||||
|
7112084 requests in 5.00m, 1.84GB read
|
||||||
|
Requests/sec: 23705.14
|
||||||
|
Transfer/sec: 6.28MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit disabled --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 303.01us 353.98us 28.03ms 98.76%
|
||||||
|
Req/Sec 2.99k 93.97 3.34k 81.12%
|
||||||
|
Latency Distribution
|
||||||
|
50% 262.00us
|
||||||
|
75% 323.00us
|
||||||
|
90% 395.00us
|
||||||
|
99% 838.00us
|
||||||
|
7133837 requests in 5.00m, 1.85GB read
|
||||||
|
Requests/sec: 23777.95
|
||||||
|
Transfer/sec: 6.30MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- rate-limit off --------------------------------------------------
|
||||||
|
Running 5m test @ http://localhost:10080/index.html
|
||||||
|
8 threads and 8 connections
|
||||||
|
Thread Stats Avg Stdev Max +/- Stdev
|
||||||
|
Latency 302.61us 349.74us 25.48ms 98.75%
|
||||||
|
Req/Sec 2.99k 94.85 3.49k 80.75%
|
||||||
|
Latency Distribution
|
||||||
|
50% 262.00us
|
||||||
|
75% 323.00us
|
||||||
|
90% 395.00us
|
||||||
|
99% 822.00us
|
||||||
|
7132714 requests in 5.00m, 1.85GB read
|
||||||
|
Requests/sec: 23773.35
|
||||||
|
Transfer/sec: 6.30MB
|
||||||
|
----------------------------------------------------------------------
|
||||||
5
addons/ot/test/be/cfg-dd.json
Normal file
5
addons/ot/test/be/cfg-dd.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"service": "BE",
|
||||||
|
"agent_host": "localhost",
|
||||||
|
"agent_port": 8126
|
||||||
|
}
|
||||||
34
addons/ot/test/be/cfg-jaeger.yml
Normal file
34
addons/ot/test/be/cfg-jaeger.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
service_name:
|
||||||
|
BE
|
||||||
|
|
||||||
|
###
|
||||||
|
# When using configuration object to instantiate the tracer, the type of
|
||||||
|
# sampling can be selected via sampler.type and sampler.param properties.
|
||||||
|
# Jaeger libraries support the following samplers:
|
||||||
|
#
|
||||||
|
# - Constant (sampler.type=const) sampler always makes the same decision for
|
||||||
|
# all traces. It either samples all traces (sampler.param=1) or none of
|
||||||
|
# them (sampler.param=0).
|
||||||
|
#
|
||||||
|
# - Probabilistic (sampler.type=probabilistic) sampler makes a random sampling
|
||||||
|
# decision with the probability of sampling equal to the value of
|
||||||
|
# sampler.param property. For example, with sampler.param=0.1 approximately
|
||||||
|
# 1 in 10 traces will be sampled.
|
||||||
|
#
|
||||||
|
# - Rate Limiting (sampler.type=ratelimiting) sampler uses a leaky bucket rate
|
||||||
|
# limiter to ensure that traces are sampled with a certain constant rate.
|
||||||
|
# For example, when sampler.param=2.0 it will sample requests with the rate
|
||||||
|
# of 2 traces per second.
|
||||||
|
#
|
||||||
|
# - Remote (sampler.type=remote, which is also the default) sampler consults
|
||||||
|
# Jaeger agent for the appropriate sampling strategy to use in the current
|
||||||
|
# service. This allows controlling the sampling strategies in the services
|
||||||
|
# from a central configuration in Jaeger backend, or even dynamically.
|
||||||
|
#
|
||||||
|
sampler:
|
||||||
|
type: ratelimiting
|
||||||
|
param: 10.0
|
||||||
|
|
||||||
|
reporter:
|
||||||
|
logSpans: true
|
||||||
|
localAgentHostPort: localhost:6831
|
||||||
4
addons/ot/test/be/cfg-zipkin.json
Normal file
4
addons/ot/test/be/cfg-zipkin.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"service_name": "BE",
|
||||||
|
"collector_host": "localhost"
|
||||||
|
}
|
||||||
37
addons/ot/test/be/haproxy.cfg
Normal file
37
addons/ot/test/be/haproxy.cfg
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
global
|
||||||
|
# nbthread 1
|
||||||
|
maxconn 5000
|
||||||
|
hard-stop-after 10s
|
||||||
|
# log localhost:514 local7 debug
|
||||||
|
# debug
|
||||||
|
stats socket /tmp/haproxy-be.sock mode 666 level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option httpclose
|
||||||
|
retries 3
|
||||||
|
maxconn 4000
|
||||||
|
timeout connect 5000
|
||||||
|
timeout client 50000
|
||||||
|
timeout server 50000
|
||||||
|
|
||||||
|
listen stats
|
||||||
|
mode http
|
||||||
|
bind *:8002
|
||||||
|
stats uri /
|
||||||
|
stats admin if TRUE
|
||||||
|
stats refresh 10s
|
||||||
|
|
||||||
|
frontend ot-test-be-frontend
|
||||||
|
bind *:11080
|
||||||
|
mode http
|
||||||
|
default_backend servers-backend
|
||||||
|
|
||||||
|
filter opentracing id ot-test-be config be/ot.cfg
|
||||||
|
|
||||||
|
backend servers-backend
|
||||||
|
mode http
|
||||||
|
server server-1 127.0.0.1:8000
|
||||||
62
addons/ot/test/be/ot.cfg
Normal file
62
addons/ot/test/be/ot.cfg
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
[ot-test-be]
|
||||||
|
ot-tracer ot-test-tracer
|
||||||
|
config be/cfg-jaeger.yml
|
||||||
|
plugin libjaeger_opentracing_plugin-0.5.0.so
|
||||||
|
# log localhost:514 local7 debug
|
||||||
|
option dontlog-normal
|
||||||
|
option hard-errors
|
||||||
|
no option disabled
|
||||||
|
|
||||||
|
scopes frontend_http_request
|
||||||
|
scopes backend_tcp_request
|
||||||
|
scopes backend_http_request
|
||||||
|
scopes client_session_end
|
||||||
|
|
||||||
|
scopes server_session_start
|
||||||
|
scopes tcp_response
|
||||||
|
scopes http_response
|
||||||
|
scopes server_session_end
|
||||||
|
|
||||||
|
ot-scope frontend_http_request
|
||||||
|
extract "ot-ctx" use-headers
|
||||||
|
span "HAProxy session" child-of "ot-ctx" root
|
||||||
|
baggage "haproxy_id" var(sess.ot.uuid)
|
||||||
|
span "Client session" child-of "HAProxy session"
|
||||||
|
span "Frontend HTTP request" child-of "Client session"
|
||||||
|
tag "http.method" method
|
||||||
|
tag "http.url" url
|
||||||
|
tag "http.version" str("HTTP/") req.ver
|
||||||
|
event on-frontend-http-request
|
||||||
|
|
||||||
|
ot-scope backend_tcp_request
|
||||||
|
span "Backend TCP request" follows-from "Frontend HTTP request"
|
||||||
|
finish "Frontend HTTP request"
|
||||||
|
event on-backend-tcp-request
|
||||||
|
|
||||||
|
ot-scope backend_http_request
|
||||||
|
span "Backend HTTP request" follows-from "Backend TCP request"
|
||||||
|
finish "Backend TCP request"
|
||||||
|
event on-backend-http-request
|
||||||
|
|
||||||
|
ot-scope client_session_end
|
||||||
|
finish "Client session"
|
||||||
|
event on-client-session-end
|
||||||
|
|
||||||
|
ot-scope server_session_start
|
||||||
|
span "Server session" child-of "HAProxy session"
|
||||||
|
finish "Backend HTTP request"
|
||||||
|
event on-server-session-start
|
||||||
|
|
||||||
|
ot-scope tcp_response
|
||||||
|
span "TCP response" child-of "Server session"
|
||||||
|
event on-tcp-response
|
||||||
|
|
||||||
|
ot-scope http_response
|
||||||
|
span "HTTP response" follows-from "TCP response"
|
||||||
|
tag "http.status_code" status
|
||||||
|
finish "TCP response"
|
||||||
|
event on-http-response
|
||||||
|
|
||||||
|
ot-scope server_session_end
|
||||||
|
finish *
|
||||||
|
event on-server-session-end
|
||||||
5
addons/ot/test/cmp/cfg-dd.json
Normal file
5
addons/ot/test/cmp/cfg-dd.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"service": "CMP",
|
||||||
|
"agent_host": "localhost",
|
||||||
|
"agent_port": 8126
|
||||||
|
}
|
||||||
34
addons/ot/test/cmp/cfg-jaeger.yml
Normal file
34
addons/ot/test/cmp/cfg-jaeger.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
service_name:
|
||||||
|
CMP
|
||||||
|
|
||||||
|
###
|
||||||
|
# When using configuration object to instantiate the tracer, the type of
|
||||||
|
# sampling can be selected via sampler.type and sampler.param properties.
|
||||||
|
# Jaeger libraries support the following samplers:
|
||||||
|
#
|
||||||
|
# - Constant (sampler.type=const) sampler always makes the same decision for
|
||||||
|
# all traces. It either samples all traces (sampler.param=1) or none of
|
||||||
|
# them (sampler.param=0).
|
||||||
|
#
|
||||||
|
# - Probabilistic (sampler.type=probabilistic) sampler makes a random sampling
|
||||||
|
# decision with the probability of sampling equal to the value of
|
||||||
|
# sampler.param property. For example, with sampler.param=0.1 approximately
|
||||||
|
# 1 in 10 traces will be sampled.
|
||||||
|
#
|
||||||
|
# - Rate Limiting (sampler.type=ratelimiting) sampler uses a leaky bucket rate
|
||||||
|
# limiter to ensure that traces are sampled with a certain constant rate.
|
||||||
|
# For example, when sampler.param=2.0 it will sample requests with the rate
|
||||||
|
# of 2 traces per second.
|
||||||
|
#
|
||||||
|
# - Remote (sampler.type=remote, which is also the default) sampler consults
|
||||||
|
# Jaeger agent for the appropriate sampling strategy to use in the current
|
||||||
|
# service. This allows controlling the sampling strategies in the services
|
||||||
|
# from a central configuration in Jaeger backend, or even dynamically.
|
||||||
|
#
|
||||||
|
sampler:
|
||||||
|
type: ratelimiting
|
||||||
|
param: 10.0
|
||||||
|
|
||||||
|
reporter:
|
||||||
|
logSpans: true
|
||||||
|
localAgentHostPort: localhost:6831
|
||||||
4
addons/ot/test/cmp/cfg-zipkin.json
Normal file
4
addons/ot/test/cmp/cfg-zipkin.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"service_name": "CMP",
|
||||||
|
"collector_host": "localhost"
|
||||||
|
}
|
||||||
36
addons/ot/test/cmp/haproxy.cfg
Normal file
36
addons/ot/test/cmp/haproxy.cfg
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
global
|
||||||
|
# nbthread 1
|
||||||
|
maxconn 5000
|
||||||
|
hard-stop-after 10s
|
||||||
|
stats socket /tmp/haproxy.sock mode 666 level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option httpclose
|
||||||
|
retries 3
|
||||||
|
maxconn 4000
|
||||||
|
timeout connect 5000
|
||||||
|
timeout client 50000
|
||||||
|
timeout server 50000
|
||||||
|
|
||||||
|
listen stats
|
||||||
|
mode http
|
||||||
|
bind *:8001
|
||||||
|
stats uri /
|
||||||
|
stats admin if TRUE
|
||||||
|
stats refresh 10s
|
||||||
|
|
||||||
|
frontend ot-test-cmp-frontend
|
||||||
|
bind *:10080
|
||||||
|
mode http
|
||||||
|
default_backend servers-backend
|
||||||
|
|
||||||
|
acl acl-http-status-ok status 100:399
|
||||||
|
filter opentracing id ot-test-cmp config cmp/ot.cfg
|
||||||
|
|
||||||
|
backend servers-backend
|
||||||
|
mode http
|
||||||
|
server server-1 127.0.0.1:8000
|
||||||
83
addons/ot/test/cmp/ot.cfg
Normal file
83
addons/ot/test/cmp/ot.cfg
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
[ot-test-cmp]
|
||||||
|
ot-tracer ot-test-tracer
|
||||||
|
config cmp/cfg-jaeger.yml
|
||||||
|
plugin libjaeger_opentracing_plugin-0.5.0.so
|
||||||
|
# log localhost:514 local7 debug
|
||||||
|
option dontlog-normal
|
||||||
|
option hard-errors
|
||||||
|
no option disabled
|
||||||
|
rate-limit 100.0
|
||||||
|
|
||||||
|
scopes client_session_start
|
||||||
|
scopes frontend_tcp_request
|
||||||
|
scopes frontend_http_request
|
||||||
|
scopes backend_tcp_request
|
||||||
|
scopes backend_http_request
|
||||||
|
scopes server_unavailable
|
||||||
|
|
||||||
|
scopes server_session_start
|
||||||
|
scopes tcp_response
|
||||||
|
scopes http_response http_response-error server_session_end client_session_end
|
||||||
|
|
||||||
|
ot-scope client_session_start
|
||||||
|
span "HAProxy session" root
|
||||||
|
baggage "haproxy_id" var(sess.ot.uuid)
|
||||||
|
span "Client session" child-of "HAProxy session"
|
||||||
|
event on-client-session-start
|
||||||
|
|
||||||
|
ot-scope frontend_tcp_request
|
||||||
|
span "Frontend TCP request" child-of "Client session"
|
||||||
|
event on-frontend-tcp-request
|
||||||
|
|
||||||
|
ot-scope frontend_http_request
|
||||||
|
span "Frontend HTTP request" follows-from "Frontend TCP request"
|
||||||
|
tag "http.method" method
|
||||||
|
tag "http.url" url
|
||||||
|
tag "http.version" str("HTTP/") req.ver
|
||||||
|
finish "Frontend TCP request"
|
||||||
|
event on-frontend-http-request
|
||||||
|
|
||||||
|
ot-scope backend_tcp_request
|
||||||
|
span "Backend TCP request" follows-from "Frontend HTTP request"
|
||||||
|
finish "Frontend HTTP request"
|
||||||
|
event on-backend-tcp-request
|
||||||
|
|
||||||
|
ot-scope backend_http_request
|
||||||
|
span "Backend HTTP request" follows-from "Backend TCP request"
|
||||||
|
finish "Backend TCP request"
|
||||||
|
event on-backend-http-request
|
||||||
|
|
||||||
|
ot-scope server_unavailable
|
||||||
|
span "HAProxy session"
|
||||||
|
tag "error" bool(true)
|
||||||
|
log "status" str("503 Service Unavailable")
|
||||||
|
finish *
|
||||||
|
event on-server-unavailable
|
||||||
|
|
||||||
|
ot-scope server_session_start
|
||||||
|
span "Server session" child-of "HAProxy session"
|
||||||
|
finish "Backend HTTP request"
|
||||||
|
event on-server-session-start
|
||||||
|
|
||||||
|
ot-scope tcp_response
|
||||||
|
span "TCP response" child-of "Server session"
|
||||||
|
event on-tcp-response
|
||||||
|
|
||||||
|
ot-scope http_response
|
||||||
|
span "HTTP response" follows-from "TCP response"
|
||||||
|
tag "http.status_code" status
|
||||||
|
finish "TCP response"
|
||||||
|
event on-http-response
|
||||||
|
|
||||||
|
ot-scope http_response-error
|
||||||
|
span "HTTP response"
|
||||||
|
tag "error" bool(true)
|
||||||
|
event on-http-response if !acl-http-status-ok
|
||||||
|
|
||||||
|
ot-scope server_session_end
|
||||||
|
finish "HTTP response" "Server session"
|
||||||
|
event on-http-response
|
||||||
|
|
||||||
|
ot-scope client_session_end
|
||||||
|
finish "*"
|
||||||
|
event on-http-response
|
||||||
5
addons/ot/test/ctx/cfg-dd.json
Normal file
5
addons/ot/test/ctx/cfg-dd.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"service": "CTX",
|
||||||
|
"agent_host": "localhost",
|
||||||
|
"agent_port": 8126
|
||||||
|
}
|
||||||
34
addons/ot/test/ctx/cfg-jaeger.yml
Normal file
34
addons/ot/test/ctx/cfg-jaeger.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
service_name:
|
||||||
|
CTX
|
||||||
|
|
||||||
|
###
|
||||||
|
# When using configuration object to instantiate the tracer, the type of
|
||||||
|
# sampling can be selected via sampler.type and sampler.param properties.
|
||||||
|
# Jaeger libraries support the following samplers:
|
||||||
|
#
|
||||||
|
# - Constant (sampler.type=const) sampler always makes the same decision for
|
||||||
|
# all traces. It either samples all traces (sampler.param=1) or none of
|
||||||
|
# them (sampler.param=0).
|
||||||
|
#
|
||||||
|
# - Probabilistic (sampler.type=probabilistic) sampler makes a random sampling
|
||||||
|
# decision with the probability of sampling equal to the value of
|
||||||
|
# sampler.param property. For example, with sampler.param=0.1 approximately
|
||||||
|
# 1 in 10 traces will be sampled.
|
||||||
|
#
|
||||||
|
# - Rate Limiting (sampler.type=ratelimiting) sampler uses a leaky bucket rate
|
||||||
|
# limiter to ensure that traces are sampled with a certain constant rate.
|
||||||
|
# For example, when sampler.param=2.0 it will sample requests with the rate
|
||||||
|
# of 2 traces per second.
|
||||||
|
#
|
||||||
|
# - Remote (sampler.type=remote, which is also the default) sampler consults
|
||||||
|
# Jaeger agent for the appropriate sampling strategy to use in the current
|
||||||
|
# service. This allows controlling the sampling strategies in the services
|
||||||
|
# from a central configuration in Jaeger backend, or even dynamically.
|
||||||
|
#
|
||||||
|
sampler:
|
||||||
|
type: ratelimiting
|
||||||
|
param: 10.0
|
||||||
|
|
||||||
|
reporter:
|
||||||
|
logSpans: true
|
||||||
|
localAgentHostPort: localhost:6831
|
||||||
4
addons/ot/test/ctx/cfg-zipkin.json
Normal file
4
addons/ot/test/ctx/cfg-zipkin.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"service_name": "CTX",
|
||||||
|
"collector_host": "localhost"
|
||||||
|
}
|
||||||
38
addons/ot/test/ctx/haproxy.cfg
Normal file
38
addons/ot/test/ctx/haproxy.cfg
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
global
|
||||||
|
# nbthread 1
|
||||||
|
maxconn 5000
|
||||||
|
hard-stop-after 10s
|
||||||
|
stats socket /tmp/haproxy.sock mode 666 level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option httpclose
|
||||||
|
retries 3
|
||||||
|
maxconn 4000
|
||||||
|
timeout connect 5000
|
||||||
|
timeout client 50000
|
||||||
|
timeout server 50000
|
||||||
|
|
||||||
|
listen stats
|
||||||
|
mode http
|
||||||
|
bind *:8001
|
||||||
|
stats uri /
|
||||||
|
stats admin if TRUE
|
||||||
|
stats refresh 10s
|
||||||
|
|
||||||
|
frontend ot-test-ctx-frontend
|
||||||
|
bind *:10080
|
||||||
|
mode http
|
||||||
|
default_backend servers-backend
|
||||||
|
|
||||||
|
acl acl-http-status-ok status 100:399
|
||||||
|
filter opentracing id ot-test-ctx config ctx/ot.cfg
|
||||||
|
http-response ot-group ot-test-ctx http_response_group if acl-http-status-ok
|
||||||
|
http-after-response ot-group ot-test-ctx http_after_response_group if !acl-http-status-ok
|
||||||
|
|
||||||
|
backend servers-backend
|
||||||
|
mode http
|
||||||
|
server server-1 127.0.0.1:8000
|
||||||
197
addons/ot/test/ctx/ot.cfg
Normal file
197
addons/ot/test/ctx/ot.cfg
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
[ot-test-ctx]
|
||||||
|
ot-tracer ot-test-tracer
|
||||||
|
log localhost:514 local7 debug
|
||||||
|
config ctx/cfg-jaeger.yml
|
||||||
|
plugin libjaeger_opentracing_plugin-0.5.0.so
|
||||||
|
option dontlog-normal
|
||||||
|
option hard-errors
|
||||||
|
no option disabled
|
||||||
|
rate-limit 100.0
|
||||||
|
|
||||||
|
groups http_response_group
|
||||||
|
groups http_after_response_group
|
||||||
|
|
||||||
|
scopes client_session_start_1
|
||||||
|
scopes client_session_start_2
|
||||||
|
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 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 server_session_end
|
||||||
|
|
||||||
|
ot-group http_response_group
|
||||||
|
scopes http_response_1
|
||||||
|
scopes http_response_2
|
||||||
|
|
||||||
|
ot-scope http_response_1
|
||||||
|
span "HTTP response"
|
||||||
|
log "hdr.content" res.hdr("content-type") str("; length: ") res.hdr("content-length") str(" bytes")
|
||||||
|
|
||||||
|
ot-scope http_response_2
|
||||||
|
span "HTTP response"
|
||||||
|
log "hdr.date" res.hdr("date") str(" / ") res.hdr("last-modified")
|
||||||
|
|
||||||
|
ot-group http_after_response_group
|
||||||
|
scopes http_after_response
|
||||||
|
|
||||||
|
ot-scope http_after_response
|
||||||
|
span "HAProxy response" child-of "HAProxy session"
|
||||||
|
tag "error" bool(true)
|
||||||
|
tag "http.status_code" status
|
||||||
|
|
||||||
|
ot-scope client_session_start_1
|
||||||
|
span "HAProxy session" root
|
||||||
|
inject "ot_ctx_1" use-headers use-vars
|
||||||
|
baggage "haproxy_id" var(sess.ot.uuid)
|
||||||
|
event on-client-session-start
|
||||||
|
|
||||||
|
ot-scope client_session_start_2
|
||||||
|
extract "ot_ctx_1" use-vars
|
||||||
|
span "Client session" child-of "ot_ctx_1"
|
||||||
|
inject "ot_ctx_2" use-headers use-vars
|
||||||
|
event on-client-session-start
|
||||||
|
|
||||||
|
ot-scope frontend_tcp_request
|
||||||
|
extract "ot_ctx_2" use-vars
|
||||||
|
span "Frontend TCP request" child-of "ot_ctx_2"
|
||||||
|
inject "ot_ctx_3" use-headers use-vars
|
||||||
|
event on-frontend-tcp-request
|
||||||
|
|
||||||
|
ot-scope http_wait_request
|
||||||
|
extract "ot_ctx_3" use-vars
|
||||||
|
span "HTTP wait request" follows-from "ot_ctx_3"
|
||||||
|
inject "ot_ctx_4" use-headers use-vars
|
||||||
|
finish "Frontend TCP request" "ot_ctx_3"
|
||||||
|
event on-http-wait-request
|
||||||
|
|
||||||
|
ot-scope http_body_request
|
||||||
|
extract "ot_ctx_4" use-vars
|
||||||
|
span "HTTP body request" follows-from "ot_ctx_4"
|
||||||
|
inject "ot_ctx_5" use-headers use-vars
|
||||||
|
finish "HTTP wait request" "ot_ctx_4"
|
||||||
|
event on-http-body-request
|
||||||
|
|
||||||
|
ot-scope frontend_http_request
|
||||||
|
extract "ot_ctx_5" use-vars
|
||||||
|
span "Frontend HTTP request" follows-from "ot_ctx_5"
|
||||||
|
tag "http.method" method
|
||||||
|
tag "http.url" url
|
||||||
|
tag "http.version" str("HTTP/") req.ver
|
||||||
|
inject "ot_ctx_6" use-headers use-vars
|
||||||
|
finish "HTTP body request" "ot_ctx_5"
|
||||||
|
event on-frontend-http-request
|
||||||
|
|
||||||
|
ot-scope switching_rules_request
|
||||||
|
extract "ot_ctx_6" use-vars
|
||||||
|
span "Switching rules request" follows-from "ot_ctx_6"
|
||||||
|
inject "ot_ctx_7" use-headers use-vars
|
||||||
|
finish "Frontend HTTP request" "ot_ctx_6"
|
||||||
|
event on-switching-rules-request
|
||||||
|
|
||||||
|
ot-scope backend_tcp_request
|
||||||
|
extract "ot_ctx_7" use-vars
|
||||||
|
span "Backend TCP request" follows-from "ot_ctx_7"
|
||||||
|
inject "ot_ctx_8" use-headers use-vars
|
||||||
|
finish "Switching rules request" "ot_ctx_7"
|
||||||
|
event on-backend-tcp-request
|
||||||
|
|
||||||
|
ot-scope backend_http_request
|
||||||
|
extract "ot_ctx_8" use-vars
|
||||||
|
span "Backend HTTP request" follows-from "ot_ctx_8"
|
||||||
|
inject "ot_ctx_9" use-headers use-vars
|
||||||
|
finish "Backend TCP request" "ot_ctx_8"
|
||||||
|
event on-backend-http-request
|
||||||
|
|
||||||
|
ot-scope process_server_rules_request
|
||||||
|
extract "ot_ctx_9" use-vars
|
||||||
|
span "Process server rules request" follows-from "ot_ctx_9"
|
||||||
|
inject "ot_ctx_10" use-headers use-vars
|
||||||
|
finish "Backend HTTP request" "ot_ctx_9"
|
||||||
|
event on-process-server-rules-request
|
||||||
|
|
||||||
|
ot-scope http_process_request
|
||||||
|
extract "ot_ctx_10" use-vars
|
||||||
|
span "HTTP process request" follows-from "ot_ctx_10"
|
||||||
|
inject "ot_ctx_11" use-headers use-vars
|
||||||
|
finish "Process server rules request" "ot_ctx_10"
|
||||||
|
event on-http-process-request
|
||||||
|
|
||||||
|
ot-scope tcp_rdp_cookie_request
|
||||||
|
extract "ot_ctx_11" use-vars
|
||||||
|
span "TCP RDP cookie request" follows-from "ot_ctx_11"
|
||||||
|
inject "ot_ctx_12" use-headers use-vars
|
||||||
|
finish "HTTP process request" "ot_ctx_11"
|
||||||
|
event on-tcp-rdp-cookie-request
|
||||||
|
|
||||||
|
ot-scope process_sticking_rules_request
|
||||||
|
extract "ot_ctx_12" use-vars
|
||||||
|
span "Process sticking rules request" follows-from "ot_ctx_12"
|
||||||
|
inject "ot_ctx_13" use-headers use-vars
|
||||||
|
finish "TCP RDP cookie request" "ot_ctx_12"
|
||||||
|
event on-process-sticking-rules-request
|
||||||
|
|
||||||
|
ot-scope client_session_end
|
||||||
|
finish "Client session" "ot_ctx_2"
|
||||||
|
event on-client-session-end
|
||||||
|
|
||||||
|
ot-scope server_unavailable
|
||||||
|
finish *
|
||||||
|
event on-server-unavailable
|
||||||
|
|
||||||
|
ot-scope server_session_start
|
||||||
|
span "Server session" child-of "ot_ctx_1"
|
||||||
|
inject "ot_ctx_14" use-vars
|
||||||
|
extract "ot_ctx_13" use-vars
|
||||||
|
finish "Process sticking rules request" "ot_ctx_13"
|
||||||
|
event on-server-session-start
|
||||||
|
|
||||||
|
ot-scope tcp_response
|
||||||
|
extract "ot_ctx_14" use-vars
|
||||||
|
span "TCP response" child-of "ot_ctx_14"
|
||||||
|
inject "ot_ctx_15" use-vars
|
||||||
|
event on-tcp-response
|
||||||
|
|
||||||
|
ot-scope http_wait_response
|
||||||
|
extract "ot_ctx_15" use-vars
|
||||||
|
span "HTTP wait response" follows-from "ot_ctx_15"
|
||||||
|
inject "ot_ctx_16" use-headers use-vars
|
||||||
|
finish "TCP response" "ot_ctx_15"
|
||||||
|
event on-http-wait-response
|
||||||
|
|
||||||
|
ot-scope process_store_rules_response
|
||||||
|
extract "ot_ctx_16" use-vars
|
||||||
|
span "Process store rules response" follows-from "ot_ctx_16"
|
||||||
|
inject "ot_ctx_17" use-headers use-vars
|
||||||
|
finish "HTTP wait response" "ot_ctx_16"
|
||||||
|
event on-process-store-rules-response
|
||||||
|
|
||||||
|
ot-scope http_response
|
||||||
|
extract "ot_ctx_17" use-vars
|
||||||
|
span "HTTP response" follows-from "ot_ctx_17"
|
||||||
|
tag "http.status_code" status
|
||||||
|
finish "Process store rules response" "ot_ctx_17"
|
||||||
|
event on-http-response
|
||||||
|
|
||||||
|
ot-scope http_response-error
|
||||||
|
span "HTTP response"
|
||||||
|
tag "error" bool(true)
|
||||||
|
event on-http-response if !acl-http-status-ok
|
||||||
|
|
||||||
|
ot-scope server_session_end
|
||||||
|
finish *
|
||||||
|
event on-server-session-end
|
||||||
5
addons/ot/test/empty/cfg-dd.json
Normal file
5
addons/ot/test/empty/cfg-dd.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"service": "EMPTY",
|
||||||
|
"agent_host": "localhost",
|
||||||
|
"agent_port": 8126
|
||||||
|
}
|
||||||
34
addons/ot/test/empty/cfg-jaeger.yml
Normal file
34
addons/ot/test/empty/cfg-jaeger.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
service_name:
|
||||||
|
EMPTY
|
||||||
|
|
||||||
|
###
|
||||||
|
# When using configuration object to instantiate the tracer, the type of
|
||||||
|
# sampling can be selected via sampler.type and sampler.param properties.
|
||||||
|
# Jaeger libraries support the following samplers:
|
||||||
|
#
|
||||||
|
# - Constant (sampler.type=const) sampler always makes the same decision for
|
||||||
|
# all traces. It either samples all traces (sampler.param=1) or none of
|
||||||
|
# them (sampler.param=0).
|
||||||
|
#
|
||||||
|
# - Probabilistic (sampler.type=probabilistic) sampler makes a random sampling
|
||||||
|
# decision with the probability of sampling equal to the value of
|
||||||
|
# sampler.param property. For example, with sampler.param=0.1 approximately
|
||||||
|
# 1 in 10 traces will be sampled.
|
||||||
|
#
|
||||||
|
# - Rate Limiting (sampler.type=ratelimiting) sampler uses a leaky bucket rate
|
||||||
|
# limiter to ensure that traces are sampled with a certain constant rate.
|
||||||
|
# For example, when sampler.param=2.0 it will sample requests with the rate
|
||||||
|
# of 2 traces per second.
|
||||||
|
#
|
||||||
|
# - Remote (sampler.type=remote, which is also the default) sampler consults
|
||||||
|
# Jaeger agent for the appropriate sampling strategy to use in the current
|
||||||
|
# service. This allows controlling the sampling strategies in the services
|
||||||
|
# from a central configuration in Jaeger backend, or even dynamically.
|
||||||
|
#
|
||||||
|
sampler:
|
||||||
|
type: ratelimiting
|
||||||
|
param: 10.0
|
||||||
|
|
||||||
|
reporter:
|
||||||
|
logSpans: true
|
||||||
|
localAgentHostPort: localhost:6831
|
||||||
4
addons/ot/test/empty/cfg-zipkin.json
Normal file
4
addons/ot/test/empty/cfg-zipkin.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"service_name": "EMPTY",
|
||||||
|
"collector_host": "localhost"
|
||||||
|
}
|
||||||
30
addons/ot/test/empty/haproxy.cfg
Normal file
30
addons/ot/test/empty/haproxy.cfg
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
global
|
||||||
|
stats socket /tmp/haproxy.sock mode 666 level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option httpclose
|
||||||
|
timeout connect 5000
|
||||||
|
timeout client 50000
|
||||||
|
timeout server 50000
|
||||||
|
|
||||||
|
listen stats
|
||||||
|
mode http
|
||||||
|
bind *:8001
|
||||||
|
stats uri /
|
||||||
|
stats admin if TRUE
|
||||||
|
stats refresh 10s
|
||||||
|
|
||||||
|
frontend ot-test-empty
|
||||||
|
bind *:10080
|
||||||
|
mode http
|
||||||
|
default_backend servers-backend
|
||||||
|
|
||||||
|
filter opentracing id ot-test-empty config empty/ot.cfg
|
||||||
|
|
||||||
|
backend servers-backend
|
||||||
|
mode http
|
||||||
|
server server-1 127.0.0.1:8000
|
||||||
3
addons/ot/test/empty/ot.cfg
Normal file
3
addons/ot/test/empty/ot.cfg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
ot-tracer ot-test-tracer
|
||||||
|
config empty/cfg-jaeger.yml
|
||||||
|
plugin libjaeger_opentracing_plugin-0.5.0.so
|
||||||
5
addons/ot/test/fe/cfg-dd.json
Normal file
5
addons/ot/test/fe/cfg-dd.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"service": "FE",
|
||||||
|
"agent_host": "localhost",
|
||||||
|
"agent_port": 8126
|
||||||
|
}
|
||||||
34
addons/ot/test/fe/cfg-jaeger.yml
Normal file
34
addons/ot/test/fe/cfg-jaeger.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
service_name:
|
||||||
|
FE
|
||||||
|
|
||||||
|
###
|
||||||
|
# When using configuration object to instantiate the tracer, the type of
|
||||||
|
# sampling can be selected via sampler.type and sampler.param properties.
|
||||||
|
# Jaeger libraries support the following samplers:
|
||||||
|
#
|
||||||
|
# - Constant (sampler.type=const) sampler always makes the same decision for
|
||||||
|
# all traces. It either samples all traces (sampler.param=1) or none of
|
||||||
|
# them (sampler.param=0).
|
||||||
|
#
|
||||||
|
# - Probabilistic (sampler.type=probabilistic) sampler makes a random sampling
|
||||||
|
# decision with the probability of sampling equal to the value of
|
||||||
|
# sampler.param property. For example, with sampler.param=0.1 approximately
|
||||||
|
# 1 in 10 traces will be sampled.
|
||||||
|
#
|
||||||
|
# - Rate Limiting (sampler.type=ratelimiting) sampler uses a leaky bucket rate
|
||||||
|
# limiter to ensure that traces are sampled with a certain constant rate.
|
||||||
|
# For example, when sampler.param=2.0 it will sample requests with the rate
|
||||||
|
# of 2 traces per second.
|
||||||
|
#
|
||||||
|
# - Remote (sampler.type=remote, which is also the default) sampler consults
|
||||||
|
# Jaeger agent for the appropriate sampling strategy to use in the current
|
||||||
|
# service. This allows controlling the sampling strategies in the services
|
||||||
|
# from a central configuration in Jaeger backend, or even dynamically.
|
||||||
|
#
|
||||||
|
sampler:
|
||||||
|
type: ratelimiting
|
||||||
|
param: 10.0
|
||||||
|
|
||||||
|
reporter:
|
||||||
|
logSpans: true
|
||||||
|
localAgentHostPort: localhost:6831
|
||||||
4
addons/ot/test/fe/cfg-zipkin.json
Normal file
4
addons/ot/test/fe/cfg-zipkin.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"service_name": "FE",
|
||||||
|
"collector_host": "localhost"
|
||||||
|
}
|
||||||
37
addons/ot/test/fe/haproxy.cfg
Normal file
37
addons/ot/test/fe/haproxy.cfg
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
global
|
||||||
|
# nbthread 1
|
||||||
|
maxconn 5000
|
||||||
|
hard-stop-after 10s
|
||||||
|
# log localhost:514 local7 debug
|
||||||
|
# debug
|
||||||
|
stats socket /tmp/haproxy-fe.sock mode 666 level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option httpclose
|
||||||
|
retries 3
|
||||||
|
maxconn 4000
|
||||||
|
timeout connect 5000
|
||||||
|
timeout client 50000
|
||||||
|
timeout server 50000
|
||||||
|
|
||||||
|
listen stats
|
||||||
|
mode http
|
||||||
|
bind *:8001
|
||||||
|
stats uri /
|
||||||
|
stats admin if TRUE
|
||||||
|
stats refresh 10s
|
||||||
|
|
||||||
|
frontend ot-test-fe-frontend
|
||||||
|
bind *:10080
|
||||||
|
mode http
|
||||||
|
default_backend servers-backend
|
||||||
|
|
||||||
|
filter opentracing id ot-test-fe config fe/ot.cfg
|
||||||
|
|
||||||
|
backend servers-backend
|
||||||
|
mode http
|
||||||
|
server server-1 127.0.0.1:11080
|
||||||
74
addons/ot/test/fe/ot.cfg
Normal file
74
addons/ot/test/fe/ot.cfg
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
[ot-test-fe]
|
||||||
|
ot-tracer ot-test-tracer
|
||||||
|
config fe/cfg-jaeger.yml
|
||||||
|
plugin libjaeger_opentracing_plugin-0.5.0.so
|
||||||
|
# log localhost:514 local7 debug
|
||||||
|
option dontlog-normal
|
||||||
|
option hard-errors
|
||||||
|
no option disabled
|
||||||
|
rate-limit 100.0
|
||||||
|
|
||||||
|
scopes client_session_start
|
||||||
|
scopes frontend_tcp_request
|
||||||
|
scopes frontend_http_request
|
||||||
|
scopes backend_tcp_request
|
||||||
|
scopes backend_http_request
|
||||||
|
scopes client_session_end
|
||||||
|
|
||||||
|
scopes server_session_start
|
||||||
|
scopes tcp_response
|
||||||
|
scopes http_response
|
||||||
|
scopes server_session_end
|
||||||
|
|
||||||
|
ot-scope client_session_start
|
||||||
|
span "HAProxy session" root
|
||||||
|
baggage "haproxy_id" var(sess.ot.uuid)
|
||||||
|
span "Client session" child-of "HAProxy session"
|
||||||
|
event on-client-session-start
|
||||||
|
|
||||||
|
ot-scope frontend_tcp_request
|
||||||
|
span "Frontend TCP request" child-of "Client session"
|
||||||
|
event on-frontend-tcp-request
|
||||||
|
|
||||||
|
ot-scope frontend_http_request
|
||||||
|
span "Frontend HTTP request" follows-from "Frontend TCP request"
|
||||||
|
tag "http.method" method
|
||||||
|
tag "http.url" url
|
||||||
|
tag "http.version" str("HTTP/") req.ver
|
||||||
|
finish "Frontend TCP request"
|
||||||
|
event on-frontend-http-request
|
||||||
|
|
||||||
|
ot-scope backend_tcp_request
|
||||||
|
span "Backend TCP request" follows-from "Frontend HTTP request"
|
||||||
|
finish "Frontend HTTP request"
|
||||||
|
event on-backend-tcp-request
|
||||||
|
|
||||||
|
ot-scope backend_http_request
|
||||||
|
span "Backend HTTP request" follows-from "Backend TCP request"
|
||||||
|
finish "Backend TCP request"
|
||||||
|
span "HAProxy session"
|
||||||
|
inject "ot-ctx" use-headers
|
||||||
|
event on-backend-http-request
|
||||||
|
|
||||||
|
ot-scope client_session_end
|
||||||
|
finish "Client session"
|
||||||
|
event on-client-session-end
|
||||||
|
|
||||||
|
ot-scope server_session_start
|
||||||
|
span "Server session" child-of "HAProxy session"
|
||||||
|
finish "Backend HTTP request"
|
||||||
|
event on-server-session-start
|
||||||
|
|
||||||
|
ot-scope tcp_response
|
||||||
|
span "TCP response" child-of "Server session"
|
||||||
|
event on-tcp-response
|
||||||
|
|
||||||
|
ot-scope http_response
|
||||||
|
span "HTTP response" follows-from "TCP response"
|
||||||
|
tag "http.status_code" status
|
||||||
|
finish "TCP response"
|
||||||
|
event on-http-response
|
||||||
|
|
||||||
|
ot-scope server_session_end
|
||||||
|
finish *
|
||||||
|
event on-server-session-end
|
||||||
5
addons/ot/test/func-stat.sh
Executable file
5
addons/ot/test/func-stat.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
test ${#} -lt 1 && exit 1
|
||||||
|
|
||||||
|
awk '/ {$/ { sub(/\(.*/, "", $5); print $5 }' "${@}" | sort | uniq -c
|
||||||
45
addons/ot/test/get-opentracing-plugins.sh
Executable file
45
addons/ot/test/get-opentracing-plugins.sh
Executable file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
_ARG_DIR="${1:-.}"
|
||||||
|
|
||||||
|
|
||||||
|
get ()
|
||||||
|
{
|
||||||
|
local _arg_tracer="${1}"
|
||||||
|
local _arg_version="${2}"
|
||||||
|
local _arg_url="${3}"
|
||||||
|
local _arg_file="${4}"
|
||||||
|
local _var_tmpfile="_tmpfile_"
|
||||||
|
local _var_plugin="lib${_arg_tracer}_opentracing_plugin-${_arg_version}.so"
|
||||||
|
|
||||||
|
test -e "${_var_plugin}" && return 0
|
||||||
|
|
||||||
|
wget "https://github.com/${_arg_url}/releases/download/v${_arg_version}/${_arg_file}" -O "${_var_tmpfile}" || {
|
||||||
|
rm "${_var_tmpfile}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$(file ${_var_tmpfile})" in
|
||||||
|
*shared\ object*)
|
||||||
|
mv "${_var_tmpfile}" "${_var_plugin}" ;;
|
||||||
|
|
||||||
|
*gzip\ compressed\ data*)
|
||||||
|
gzip -cd "${_var_tmpfile}" > "${_var_plugin}"
|
||||||
|
rm "${_var_tmpfile}" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p "${_ARG_DIR}" && cd "${_ARG_DIR}" || exit 1
|
||||||
|
|
||||||
|
get dd 1.1.2 DataDog/dd-opentracing-cpp linux-amd64-libdd_opentracing_plugin.so.gz
|
||||||
|
get dd 1.2.0 DataDog/dd-opentracing-cpp linux-amd64-libdd_opentracing_plugin.so.gz
|
||||||
|
|
||||||
|
get jaeger 0.4.2 jaegertracing/jaeger-client-cpp libjaegertracing_plugin.linux_amd64.so
|
||||||
|
#et jaeger 0.5.0 jaegertracing/jaeger-client-cpp libjaegertracing_plugin.linux_amd64.so
|
||||||
|
#et jaeger 0.6.0 jaegertracing/jaeger-client-cpp libjaegertracing_plugin.linux_amd64.so
|
||||||
|
|
||||||
|
get lightstep 0.12.0 lightstep/lightstep-tracer-cpp linux-amd64-liblightstep_tracer_plugin.so.gz
|
||||||
|
get lightstep 0.13.0 lightstep/lightstep-tracer-cpp linux-amd64-liblightstep_tracer_plugin.so.gz
|
||||||
|
|
||||||
|
get zipkin 0.5.2 rnburn/zipkin-cpp-opentracing linux-amd64-libzipkin_opentracing_plugin.so.gz
|
||||||
1
addons/ot/test/index.html
Normal file
1
addons/ot/test/index.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<html><body><p>Did I err?</p></body></html>
|
||||||
13
addons/ot/test/run-cmp.sh
Executable file
13
addons/ot/test/run-cmp.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
_ARG_HAPROXY="${1:-$(realpath -L ${PWD}/../../../haproxy)}"
|
||||||
|
_ARGS="-f cmp/haproxy.cfg"
|
||||||
|
_LOG_DIR="_logs"
|
||||||
|
_LOG="${_LOG_DIR}/_log-$(basename "${0}" .sh)-$(date +%s)"
|
||||||
|
|
||||||
|
|
||||||
|
test -x "${_ARG_HAPROXY}" || exit 1
|
||||||
|
mkdir -p "${_LOG_DIR}" || exit 2
|
||||||
|
|
||||||
|
echo "executing: ${_ARG_HAPROXY} ${_ARGS} > ${_LOG}"
|
||||||
|
"${_ARG_HAPROXY}" ${_ARGS} >"${_LOG}" 2>&1
|
||||||
13
addons/ot/test/run-ctx.sh
Executable file
13
addons/ot/test/run-ctx.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
_ARG_HAPROXY="${1:-$(realpath -L ${PWD}/../../../haproxy)}"
|
||||||
|
_ARGS="-f ctx/haproxy.cfg"
|
||||||
|
_LOG_DIR="_logs"
|
||||||
|
_LOG="${_LOG_DIR}/_log-$(basename "${0}" .sh)-$(date +%s)"
|
||||||
|
|
||||||
|
|
||||||
|
test -x "${_ARG_HAPROXY}" || exit 1
|
||||||
|
mkdir -p "${_LOG_DIR}" || exit 2
|
||||||
|
|
||||||
|
echo "executing: ${_ARG_HAPROXY} ${_ARGS} > ${_LOG}"
|
||||||
|
"${_ARG_HAPROXY}" ${_ARGS} >"${_LOG}" 2>&1
|
||||||
47
addons/ot/test/run-fe-be.sh
Executable file
47
addons/ot/test/run-fe-be.sh
Executable file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
_ARG_HAPROXY="${1:-$(realpath -L ${PWD}/../../../haproxy)}"
|
||||||
|
_ARGS_FE="-f fe/haproxy.cfg"
|
||||||
|
_ARGS_BE="-f be/haproxy.cfg"
|
||||||
|
_TIME="$(date +%s)"
|
||||||
|
_LOG_DIR="_logs"
|
||||||
|
_LOG_FE="${_LOG_DIR}/_log-$(basename "${0}" fe-be.sh)fe-${_TIME}"
|
||||||
|
_LOG_BE="${_LOG_DIR}/_log-$(basename "${0}" fe-be.sh)be-${_TIME}"
|
||||||
|
|
||||||
|
|
||||||
|
__exit ()
|
||||||
|
{
|
||||||
|
test -z "${2}" && {
|
||||||
|
echo
|
||||||
|
echo "Script killed!"
|
||||||
|
|
||||||
|
echo "Waiting for jobs to complete..."
|
||||||
|
pkill --signal SIGUSR1 haproxy
|
||||||
|
wait
|
||||||
|
}
|
||||||
|
|
||||||
|
test -n "${1}" && {
|
||||||
|
echo
|
||||||
|
echo "${1}"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
exit ${2:-100}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
trap __exit INT TERM
|
||||||
|
|
||||||
|
test -x "${_ARG_HAPROXY}" || __exit "${_ARG_HAPROXY}: executable does not exist" 1
|
||||||
|
mkdir -p "${_LOG_DIR}" || __exit "${_ARG_HAPROXY}: cannot create log directory" 2
|
||||||
|
|
||||||
|
echo "\n------------------------------------------------------------------------"
|
||||||
|
echo "--- executing: ${_ARG_HAPROXY} ${_ARGS_BE} > ${_LOG_BE}"
|
||||||
|
"${_ARG_HAPROXY}" ${_ARGS_BE} >"${_LOG_BE}" 2>&1 &
|
||||||
|
|
||||||
|
echo "--- executing: ${_ARG_HAPROXY} ${_ARGS_FE} > ${_LOG_FE}"
|
||||||
|
"${_ARG_HAPROXY}" ${_ARGS_FE} >"${_LOG_FE}" 2>&1 &
|
||||||
|
echo "------------------------------------------------------------------------\n"
|
||||||
|
|
||||||
|
echo "Press CTRL-C to quit..."
|
||||||
|
wait
|
||||||
13
addons/ot/test/run-sa.sh
Executable file
13
addons/ot/test/run-sa.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
_ARG_HAPROXY="${1:-$(realpath -L ${PWD}/../../../haproxy)}"
|
||||||
|
_ARGS="-f sa/haproxy.cfg"
|
||||||
|
_LOG_DIR="_logs"
|
||||||
|
_LOG="${_LOG_DIR}/_log-$(basename "${0}" .sh)-$(date +%s)"
|
||||||
|
|
||||||
|
|
||||||
|
test -x "${_ARG_HAPROXY}" || exit 1
|
||||||
|
mkdir -p "${_LOG_DIR}" || exit 2
|
||||||
|
|
||||||
|
echo "executing: ${_ARG_HAPROXY} ${_ARGS} > ${_LOG}"
|
||||||
|
"${_ARG_HAPROXY}" ${_ARGS} >"${_LOG}" 2>&1
|
||||||
5
addons/ot/test/sa/cfg-dd.json
Normal file
5
addons/ot/test/sa/cfg-dd.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"service": "SA",
|
||||||
|
"agent_host": "localhost",
|
||||||
|
"agent_port": 8126
|
||||||
|
}
|
||||||
34
addons/ot/test/sa/cfg-jaeger.yml
Normal file
34
addons/ot/test/sa/cfg-jaeger.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
service_name:
|
||||||
|
SA
|
||||||
|
|
||||||
|
###
|
||||||
|
# When using configuration object to instantiate the tracer, the type of
|
||||||
|
# sampling can be selected via sampler.type and sampler.param properties.
|
||||||
|
# Jaeger libraries support the following samplers:
|
||||||
|
#
|
||||||
|
# - Constant (sampler.type=const) sampler always makes the same decision for
|
||||||
|
# all traces. It either samples all traces (sampler.param=1) or none of
|
||||||
|
# them (sampler.param=0).
|
||||||
|
#
|
||||||
|
# - Probabilistic (sampler.type=probabilistic) sampler makes a random sampling
|
||||||
|
# decision with the probability of sampling equal to the value of
|
||||||
|
# sampler.param property. For example, with sampler.param=0.1 approximately
|
||||||
|
# 1 in 10 traces will be sampled.
|
||||||
|
#
|
||||||
|
# - Rate Limiting (sampler.type=ratelimiting) sampler uses a leaky bucket rate
|
||||||
|
# limiter to ensure that traces are sampled with a certain constant rate.
|
||||||
|
# For example, when sampler.param=2.0 it will sample requests with the rate
|
||||||
|
# of 2 traces per second.
|
||||||
|
#
|
||||||
|
# - Remote (sampler.type=remote, which is also the default) sampler consults
|
||||||
|
# Jaeger agent for the appropriate sampling strategy to use in the current
|
||||||
|
# service. This allows controlling the sampling strategies in the services
|
||||||
|
# from a central configuration in Jaeger backend, or even dynamically.
|
||||||
|
#
|
||||||
|
sampler:
|
||||||
|
type: ratelimiting
|
||||||
|
param: 10.0
|
||||||
|
|
||||||
|
reporter:
|
||||||
|
logSpans: true
|
||||||
|
localAgentHostPort: localhost:6831
|
||||||
4
addons/ot/test/sa/cfg-zipkin.json
Normal file
4
addons/ot/test/sa/cfg-zipkin.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"service_name": "SA",
|
||||||
|
"collector_host": "localhost"
|
||||||
|
}
|
||||||
40
addons/ot/test/sa/haproxy.cfg
Normal file
40
addons/ot/test/sa/haproxy.cfg
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
global
|
||||||
|
# nbthread 1
|
||||||
|
maxconn 5000
|
||||||
|
hard-stop-after 10s
|
||||||
|
# log localhost:514 local7 debug
|
||||||
|
# debug
|
||||||
|
stats socket /tmp/haproxy.sock mode 666 level admin
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
option httpclose
|
||||||
|
retries 3
|
||||||
|
maxconn 4000
|
||||||
|
timeout connect 5000
|
||||||
|
timeout client 50000
|
||||||
|
timeout server 50000
|
||||||
|
|
||||||
|
listen stats
|
||||||
|
mode http
|
||||||
|
bind *:8001
|
||||||
|
stats uri /
|
||||||
|
stats admin if TRUE
|
||||||
|
stats refresh 10s
|
||||||
|
|
||||||
|
frontend ot-test-sa-frontend
|
||||||
|
bind *:10080
|
||||||
|
mode http
|
||||||
|
default_backend servers-backend
|
||||||
|
|
||||||
|
acl acl-http-status-ok status 100:399
|
||||||
|
filter opentracing id ot-test-sa config sa/ot.cfg
|
||||||
|
http-response ot-group ot-test-sa http_response_group if acl-http-status-ok
|
||||||
|
http-after-response ot-group ot-test-sa http_after_response_group if !acl-http-status-ok
|
||||||
|
|
||||||
|
backend servers-backend
|
||||||
|
mode http
|
||||||
|
server server-1 127.0.0.1:8000
|
||||||
160
addons/ot/test/sa/ot.cfg
Normal file
160
addons/ot/test/sa/ot.cfg
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
[ot-test-sa]
|
||||||
|
ot-tracer ot-test-tracer
|
||||||
|
log localhost:514 local7 debug
|
||||||
|
config sa/cfg-jaeger.yml
|
||||||
|
plugin libjaeger_opentracing_plugin-0.5.0.so
|
||||||
|
option dontlog-normal
|
||||||
|
option hard-errors
|
||||||
|
no option disabled
|
||||||
|
rate-limit 100.0
|
||||||
|
|
||||||
|
groups http_response_group
|
||||||
|
groups http_after_response_group
|
||||||
|
|
||||||
|
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 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 server_session_end
|
||||||
|
|
||||||
|
ot-group http_response_group
|
||||||
|
scopes http_response_1
|
||||||
|
scopes http_response_2
|
||||||
|
|
||||||
|
ot-scope http_response_1
|
||||||
|
span "HTTP response"
|
||||||
|
log "hdr.content" res.hdr("content-type") str("; length: ") res.hdr("content-length") str(" bytes")
|
||||||
|
|
||||||
|
ot-scope http_response_2
|
||||||
|
span "HTTP response"
|
||||||
|
log "hdr.date" res.hdr("date") str(" / ") res.hdr("last-modified")
|
||||||
|
|
||||||
|
ot-group http_after_response_group
|
||||||
|
scopes http_after_response
|
||||||
|
|
||||||
|
ot-scope http_after_response
|
||||||
|
span "HAProxy response" child-of "HAProxy session"
|
||||||
|
tag "error" bool(true)
|
||||||
|
tag "http.status_code" status
|
||||||
|
|
||||||
|
ot-scope client_session_start
|
||||||
|
span "HAProxy session" root
|
||||||
|
baggage "haproxy_id" var(sess.ot.uuid)
|
||||||
|
span "Client session" child-of "HAProxy session"
|
||||||
|
acl acl-test-src-ip src 127.0.0.1
|
||||||
|
event on-client-session-start if acl-test-src-ip
|
||||||
|
|
||||||
|
ot-scope frontend_tcp_request
|
||||||
|
span "Frontend TCP request" child-of "Client session"
|
||||||
|
event on-frontend-tcp-request
|
||||||
|
|
||||||
|
ot-scope http_wait_request
|
||||||
|
span "HTTP wait request" follows-from "Frontend TCP request"
|
||||||
|
finish "Frontend TCP request"
|
||||||
|
event on-http-wait-request
|
||||||
|
|
||||||
|
ot-scope http_body_request
|
||||||
|
span "HTTP body request" follows-from "HTTP wait request"
|
||||||
|
finish "HTTP wait request"
|
||||||
|
event on-http-body-request
|
||||||
|
|
||||||
|
ot-scope frontend_http_request
|
||||||
|
span "Frontend HTTP request" follows-from "HTTP body request"
|
||||||
|
tag "http.method" method
|
||||||
|
tag "http.url" url
|
||||||
|
tag "http.version" str("HTTP/") req.ver
|
||||||
|
finish "HTTP body request"
|
||||||
|
event on-frontend-http-request
|
||||||
|
|
||||||
|
ot-scope switching_rules_request
|
||||||
|
span "Switching rules request" follows-from "Frontend HTTP request"
|
||||||
|
finish "Frontend HTTP request"
|
||||||
|
event on-switching-rules-request
|
||||||
|
|
||||||
|
ot-scope backend_tcp_request
|
||||||
|
span "Backend TCP request" follows-from "Switching rules request"
|
||||||
|
finish "Switching rules request"
|
||||||
|
event on-backend-tcp-request
|
||||||
|
|
||||||
|
ot-scope backend_http_request
|
||||||
|
span "Backend HTTP request" follows-from "Backend TCP request"
|
||||||
|
finish "Backend TCP request"
|
||||||
|
event on-backend-http-request
|
||||||
|
|
||||||
|
ot-scope process_server_rules_request
|
||||||
|
span "Process server rules request" follows-from "Backend HTTP request"
|
||||||
|
finish "Backend HTTP request"
|
||||||
|
event on-process-server-rules-request
|
||||||
|
|
||||||
|
ot-scope http_process_request
|
||||||
|
span "HTTP process request" follows-from "Process server rules request"
|
||||||
|
finish "Process server rules request"
|
||||||
|
event on-http-process-request
|
||||||
|
|
||||||
|
ot-scope tcp_rdp_cookie_request
|
||||||
|
span "TCP RDP cookie request" follows-from "HTTP process request"
|
||||||
|
finish "HTTP process request"
|
||||||
|
event on-tcp-rdp-cookie-request
|
||||||
|
|
||||||
|
ot-scope process_sticking_rules_request
|
||||||
|
span "Process sticking rules request" follows-from "TCP RDP cookie request"
|
||||||
|
finish "TCP RDP cookie request"
|
||||||
|
event on-process-sticking-rules-request
|
||||||
|
|
||||||
|
ot-scope client_session_end
|
||||||
|
finish "Client session"
|
||||||
|
event on-client-session-end
|
||||||
|
|
||||||
|
ot-scope server_unavailable
|
||||||
|
finish *
|
||||||
|
event on-server-unavailable
|
||||||
|
|
||||||
|
ot-scope server_session_start
|
||||||
|
span "Server session" child-of "HAProxy session"
|
||||||
|
finish "Process sticking rules request"
|
||||||
|
event on-server-session-start
|
||||||
|
|
||||||
|
ot-scope tcp_response
|
||||||
|
span "TCP response" child-of "Server session"
|
||||||
|
event on-tcp-response
|
||||||
|
|
||||||
|
ot-scope http_wait_response
|
||||||
|
span "HTTP wait response" follows-from "TCP response"
|
||||||
|
finish "TCP response"
|
||||||
|
event on-http-wait-response
|
||||||
|
|
||||||
|
ot-scope process_store_rules_response
|
||||||
|
span "Process store rules response" follows-from "HTTP wait response"
|
||||||
|
finish "HTTP wait response"
|
||||||
|
event on-process-store-rules-response
|
||||||
|
|
||||||
|
ot-scope http_response
|
||||||
|
span "HTTP response" follows-from "Process store rules response"
|
||||||
|
tag "http.status_code" status
|
||||||
|
finish "Process store rules response"
|
||||||
|
event on-http-response
|
||||||
|
|
||||||
|
ot-scope http_response-error
|
||||||
|
span "HTTP response"
|
||||||
|
tag "error" bool(true)
|
||||||
|
event on-http-response if !acl-http-status-ok
|
||||||
|
|
||||||
|
ot-scope server_session_end
|
||||||
|
finish *
|
||||||
|
event on-server-session-end
|
||||||
117
addons/ot/test/test-speed.sh
Executable file
117
addons/ot/test/test-speed.sh
Executable file
|
|
@ -0,0 +1,117 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
_ARG_CFG="${1}"
|
||||||
|
_ARG_DIR="${2:-${1}}"
|
||||||
|
_LOG_DIR="_logs"
|
||||||
|
_HTTPD_PIDFILE="${_LOG_DIR}/thttpd.pid"
|
||||||
|
_USAGE_MSG="usage: $(basename "${0}") cfg [dir]"
|
||||||
|
|
||||||
|
|
||||||
|
sh_exit ()
|
||||||
|
{
|
||||||
|
test -z "${2}" && {
|
||||||
|
echo
|
||||||
|
echo "Script killed!"
|
||||||
|
}
|
||||||
|
|
||||||
|
test -n "${1}" && {
|
||||||
|
echo
|
||||||
|
echo "${1}"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
exit ${2:-64}
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_run ()
|
||||||
|
{
|
||||||
|
|
||||||
|
test -e "${_HTTPD_PIDFILE}" && return
|
||||||
|
|
||||||
|
thttpd -p 8000 -d . -nos -nov -l /dev/null -i "${_HTTPD_PIDFILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_stop ()
|
||||||
|
{
|
||||||
|
test -e "${_HTTPD_PIDFILE}" || return
|
||||||
|
|
||||||
|
kill -TERM "$(cat ${_HTTPD_PIDFILE})"
|
||||||
|
rm "${_HTTPD_PIDFILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
haproxy_run ()
|
||||||
|
{
|
||||||
|
_arg_ratio="${1}"
|
||||||
|
_var_sed_ot=
|
||||||
|
_var_sed_haproxy=
|
||||||
|
|
||||||
|
if test "${_arg_ratio}" = "disabled"; then
|
||||||
|
_var_sed_ot="s/no \(option disabled\)/\1/"
|
||||||
|
elif test "${_arg_ratio}" = "off"; then
|
||||||
|
_var_sed_haproxy="s/^\(.* filter opentracing .*\)/#\1/g; s/^\(.* ot-group .*\)/#\1/g"
|
||||||
|
else
|
||||||
|
_var_sed_ot="s/\(rate-limit\) 100.0/\1 ${_arg_ratio}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed "${_var_sed_haproxy}" "${_ARG_DIR}/haproxy.cfg.in" > "${_ARG_DIR}/haproxy.cfg"
|
||||||
|
sed "${_var_sed_ot}" "${_ARG_DIR}/ot.cfg.in" > "${_ARG_DIR}/ot.cfg"
|
||||||
|
|
||||||
|
if test "${_ARG_DIR}" = "fe"; then
|
||||||
|
if test "${_arg_ratio}" = "disabled" -o "${_arg_ratio}" = "off"; then
|
||||||
|
sed "${_var_sed_haproxy}" "be/haproxy.cfg.in" > "be/haproxy.cfg"
|
||||||
|
sed "${_var_sed_ot}" "be/ot.cfg.in" > "be/ot.cfg"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
./run-${_ARG_CFG}.sh &
|
||||||
|
sleep 5
|
||||||
|
}
|
||||||
|
|
||||||
|
wrk_run ()
|
||||||
|
{
|
||||||
|
_arg_ratio="${1}"
|
||||||
|
|
||||||
|
echo "--- rate-limit ${_arg_ratio} --------------------------------------------------"
|
||||||
|
wrk -c8 -d300 -t8 --latency http://localhost:10080/index.html
|
||||||
|
echo "----------------------------------------------------------------------"
|
||||||
|
echo
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
command -v thttpd >/dev/null 2>&1 || sh_exit "thttpd: command not found" 5
|
||||||
|
command -v wrk >/dev/null 2>&1 || sh_exit "wrk: command not found" 6
|
||||||
|
|
||||||
|
mkdir -p "${_LOG_DIR}" || sh_exit "${_LOG_DIR}: Cannot create log directory" 1
|
||||||
|
|
||||||
|
if test "${_ARG_CFG}" = "all"; then
|
||||||
|
"${0}" fe-be fe > "${_LOG_DIR}/README-speed-fe-be"
|
||||||
|
"${0}" sa sa > "${_LOG_DIR}/README-speed-sa"
|
||||||
|
"${0}" cmp cmp > "${_LOG_DIR}/README-speed-cmp"
|
||||||
|
"${0}" ctx ctx > "${_LOG_DIR}/README-speed-ctx"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -z "${_ARG_CFG}" -o -z "${_ARG_DIR}" && sh_exit "${_USAGE_MSG}" 4
|
||||||
|
test -f "run-${_ARG_CFG}.sh" || sh_exit "run-${_ARG_CFG}.sh: No such configuration script" 2
|
||||||
|
test -d "${_ARG_DIR}" || sh_exit "${_ARG_DIR}: No such directory" 3
|
||||||
|
|
||||||
|
test -e "${_ARG_DIR}/haproxy.cfg.in" || cp -af "${_ARG_DIR}/haproxy.cfg" "${_ARG_DIR}/haproxy.cfg.in"
|
||||||
|
test -e "${_ARG_DIR}/ot.cfg.in" || cp -af "${_ARG_DIR}/ot.cfg" "${_ARG_DIR}/ot.cfg.in"
|
||||||
|
if test "${_ARG_DIR}" = "fe"; then
|
||||||
|
test -e "be/haproxy.cfg.in" || cp -af "be/haproxy.cfg" "be/haproxy.cfg.in"
|
||||||
|
test -e "be/ot.cfg.in" || cp -af "be/ot.cfg" "be/ot.cfg.in"
|
||||||
|
fi
|
||||||
|
|
||||||
|
httpd_run
|
||||||
|
|
||||||
|
for _var_ratio in 100.0 50.0 10.0 2.5 0.0 disabled off; do
|
||||||
|
haproxy_run "${_var_ratio}"
|
||||||
|
wrk_run "${_var_ratio}"
|
||||||
|
|
||||||
|
pkill --signal SIGUSR1 haproxy
|
||||||
|
wait
|
||||||
|
done
|
||||||
|
|
||||||
|
httpd_stop
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# Use WURFL_SRC and possibly WURFL_INC and WURFL_LIB to force path
|
|
||||||
# to WURFL headers and libraries if needed.
|
|
||||||
WURFL_INC = $(WURFL_SRC)
|
|
||||||
WURFL_LIB = $(WURFL_SRC)
|
|
||||||
OPTIONS_OBJS += addons/wurfl/wurfl.o
|
|
||||||
WURFL_CFLAGS = $(if $(WURFL_INC),-I$(WURFL_INC))
|
|
||||||
ifneq ($(WURFL_DEBUG),)
|
|
||||||
WURFL_CFLAGS += -DWURFL_DEBUG
|
|
||||||
endif
|
|
||||||
ifneq ($(WURFL_HEADER_WITH_DETAILS),)
|
|
||||||
WURFL_CFLAGS += -DWURFL_HEADER_WITH_DETAILS
|
|
||||||
endif
|
|
||||||
WURFL_LDFLAGS = $(if $(WURFL_LIB),-L$(WURFL_LIB)) -lwurfl
|
|
||||||
|
|
@ -1801,8 +1801,6 @@ void filter_count_ip(const char *source_field, const char *accept_field, const c
|
||||||
*/
|
*/
|
||||||
if (unlikely(!ustat))
|
if (unlikely(!ustat))
|
||||||
ustat = calloc(1, sizeof(*ustat));
|
ustat = calloc(1, sizeof(*ustat));
|
||||||
if (!ustat)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ustat->nb_err = err;
|
ustat->nb_err = err;
|
||||||
ustat->nb_req = 1;
|
ustat->nb_req = 1;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ end
|
||||||
# returns $node filled with the first node of ebroot $arg0
|
# returns $node filled with the first node of ebroot $arg0
|
||||||
define ebtree_first
|
define ebtree_first
|
||||||
# browse ebtree left until encountering leaf
|
# browse ebtree left until encountering leaf
|
||||||
set $node = (struct eb_node *)((struct eb_root*)$arg0)->b[0]
|
set $node = (struct eb_node *)$arg0->b[0]
|
||||||
while 1
|
while 1
|
||||||
_ebtree_set_tag_node $node
|
_ebtree_set_tag_node $node
|
||||||
if $tag == 0
|
if $tag == 0
|
||||||
|
|
@ -41,7 +41,7 @@ end
|
||||||
# finds next ebtree node after $arg0, and returns it in $node
|
# finds next ebtree node after $arg0, and returns it in $node
|
||||||
define ebtree_next
|
define ebtree_next
|
||||||
# get parent
|
# get parent
|
||||||
set $node = (struct eb_root *)((struct eb_node *)$arg0)->leaf_p
|
set $node = (struct eb_root *)$arg0->leaf_p
|
||||||
# Walking up from right branch, so we cannot be below root
|
# Walking up from right branch, so we cannot be below root
|
||||||
# while (eb_gettag(t) != EB_LEFT) // #define EB_LEFT 0
|
# while (eb_gettag(t) != EB_LEFT) // #define EB_LEFT 0
|
||||||
while 1
|
while 1
|
||||||
|
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
# list info about open FD
|
|
||||||
define fd_dump
|
|
||||||
set $f = 0
|
|
||||||
while $f < $g.maxsock
|
|
||||||
if fdtab[$f].owner != 0
|
|
||||||
printf "fd %5d: rm=%#lx tm=%#lx um=%#lx cb=%p ownr=%p st=%#x refc=%#x tkov=%u gen=%u\n", $f, fdtab[$f].running_mask, fdtab[$f].thread_mask, fdtab[$f].update_mask, fdtab[$f].iocb, fdtab[$f].owner, fdtab[$f].state, fdtab[$f].refc_tgid, fdtab[$f].nb_takeover, fdtab[$f].generation
|
|
||||||
end
|
|
||||||
set $f = $f + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# only those attached to a listener
|
|
||||||
define fd_dump_listener
|
|
||||||
set $f = 0
|
|
||||||
while $f < $g.maxsock
|
|
||||||
if fdtab[$f].owner != 0 && fdtab[$f].iocb == &sock_accept_iocb
|
|
||||||
set $c = (struct listener *)fdtab[$f].owner
|
|
||||||
printf "fd %5d: rm=%#lx tm=%#lx um=%#lx st=%#x refc=%#x tkov=%u gen=%u listener=%p(%s): flg=%#x state=%d fe=%p(%s) acc=%p\n", $f, fdtab[$f].running_mask, fdtab[$f].thread_mask, fdtab[$f].update_mask, fdtab[$f].state, fdtab[$f].refc_tgid, fdtab[$f].nb_takeover, fdtab[$f].generation, fdtab[$f].owner, $c->name, $c->flags, $c->state, $c->bind_conf.frontend, $c->bind_conf.frontend.id, $c->bind_conf.accept
|
|
||||||
end
|
|
||||||
set $f = $f + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# only those attached to a connection
|
|
||||||
define fd_dump_conn
|
|
||||||
set $f = 0
|
|
||||||
while $f < $g.maxsock
|
|
||||||
if fdtab[$f].owner != 0 && fdtab[$f].iocb == &sock_conn_iocb
|
|
||||||
set $c = (struct connection *)fdtab[$f].owner
|
|
||||||
printf "fd %5d: rm=%#lx tm=%#lx um=%#lx st=%#x refc=%#x tkov=%u gen=%u conn=%p: flg=%#x err=%#x ctrl=%p xprt=%p mux=%p", $f, fdtab[$f].running_mask, fdtab[$f].thread_mask, fdtab[$f].update_mask, fdtab[$f].state, fdtab[$f].refc_tgid, fdtab[$f].nb_takeover, fdtab[$f].generation, fdtab[$f].owner, $c->flags, $c->err_code, $c->ctrl, $c->xprt, $c->mux
|
|
||||||
if *$c->target == OBJ_TYPE_LISTENER
|
|
||||||
set $s = (struct session *)$c->owner
|
|
||||||
printf " sess=%p: fe=%p id=%s age=%dms", $s, $s->fe, $s->fe->id, (*global_now_ns - $s->accept_ts) / 1000000
|
|
||||||
end
|
|
||||||
printf "\n"
|
|
||||||
end
|
|
||||||
set $f = $f + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
# lists all tasks in the wait queue whose ebroot pointed to by $arg0
|
|
||||||
# e.g.
|
|
||||||
# task_dump_wq &ha_tgroup_ctx[0].timers
|
|
||||||
# task_dump_wq &ha_thread_ctx[0].timers
|
|
||||||
#
|
|
||||||
define task_dump_rq
|
|
||||||
set $tot=0
|
|
||||||
ebtree_first ($arg0)
|
|
||||||
while ($node != 0)
|
|
||||||
set $tot = $tot+1
|
|
||||||
set $p = (struct task *)((void*)$node-(long)&((struct task*)0).rq)
|
|
||||||
printf "task %p ",$p
|
|
||||||
p -pretty off -- /a *$p
|
|
||||||
ebtree_next $node
|
|
||||||
end
|
|
||||||
printf "Total: %d tasks.\n",$tot
|
|
||||||
end
|
|
||||||
|
|
||||||
define task_dump_wq
|
|
||||||
set $tot=0
|
|
||||||
ebtree_first ($arg0)
|
|
||||||
while ($node != 0)
|
|
||||||
set $tot = $tot+1
|
|
||||||
set $p = (struct task *)((void*)$node-(long)&((struct task*)0).wq)
|
|
||||||
printf "task %p ",$p
|
|
||||||
p -pretty off -- /a *$p
|
|
||||||
ebtree_next $node
|
|
||||||
end
|
|
||||||
printf "Total: %d tasks.\n",$tot
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# list info about current threads (ptr, now_ms, queue, current)
|
|
||||||
define thread_dump
|
|
||||||
set $t = 0
|
|
||||||
while $t < $g.nbthread
|
|
||||||
set $i = $ti[$t].pth_id
|
|
||||||
set $h = $tc[$t].current
|
|
||||||
printf "Tid %4d: pth=%p mono=%llu now_ms=%u fl=0x%02x rq=%d cq=%d current=%p\n", $t, $i, $tc[$t].curr_mono_time, (unsigned)(($tc[$t].curr_mono_time + now_offset)/1000000), $tc[$t].flags, $tc[$t].current_queue, $tc[$t].rq_total, $h
|
|
||||||
set $t = $t + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
BEGININPUT
|
|
||||||
BEGINCONTEXT
|
|
||||||
|
|
||||||
HAProxy's development cycle consists in one development branch, and multiple
|
|
||||||
maintenance branches.
|
|
||||||
|
|
||||||
All the development is made into the development branch exclusively. This
|
|
||||||
includes mostly new features, doc updates, cleanups and or course, fixes.
|
|
||||||
|
|
||||||
The maintenance branches, also called stable branches, never see any
|
|
||||||
development, and only receive ultra-safe fixes for bugs that affect them,
|
|
||||||
that are picked from the development branch.
|
|
||||||
|
|
||||||
Branches are numbered in 0.1 increments. Every 6 months, upon a new major
|
|
||||||
release, the development branch enters maintenance and a new development branch
|
|
||||||
is created with a new, higher version. The current development branch is
|
|
||||||
3.5-dev, and maintenance branches are 3.4 and below.
|
|
||||||
|
|
||||||
Fixes created in the development branch for issues that were introduced in an
|
|
||||||
earlier branch are applied in descending order to each and every version till
|
|
||||||
that branch that introduced the issue: 3.4 first, then 3.2, then 3.1, then 3.0
|
|
||||||
and so on. This operation is called "backporting". A fix for an issue is never
|
|
||||||
backported beyond the branch that introduced the issue. An important point is
|
|
||||||
that the project maintainers really aim at zero regression in maintenance
|
|
||||||
branches, so they're never willing to take any risk backporting patches that
|
|
||||||
are not deemed strictly necessary.
|
|
||||||
|
|
||||||
Fixes consist of patches managed using the Git version control tool and are
|
|
||||||
identified by a Git commit ID and a commit message. For this reason we
|
|
||||||
indistinctly talk about backporting fixes, commits, or patches; all mean the
|
|
||||||
same thing. When mentioning commit IDs, developers always use a short form
|
|
||||||
made of the first 8 characters only, and expect the AI assistant to do the
|
|
||||||
same.
|
|
||||||
|
|
||||||
It seldom happens that some fixes depend on changes that were brought by other
|
|
||||||
patches that were not in some branches and that will need to be backported as
|
|
||||||
well for the fix to work. In this case, such information is explicitly provided
|
|
||||||
in the commit message by the patch's author in natural language.
|
|
||||||
|
|
||||||
Developers are serious and always indicate if a patch needs to be backported.
|
|
||||||
Sometimes they omit the exact target branch, or they will say that the patch is
|
|
||||||
"needed" in some older branch, but it means the same. If a commit message
|
|
||||||
doesn't mention any backport instructions, it means that the commit does not
|
|
||||||
have to be backported. And patches that are not strictly bug fixes nor doc
|
|
||||||
improvements are normally not backported. For example, fixes for design
|
|
||||||
limitations, architectural improvements and performance optimizations are
|
|
||||||
considered too risky for a backport. Finally, all bug fixes are tagged as
|
|
||||||
"BUG" at the beginning of their subject line. Patches that are not tagged as
|
|
||||||
such are not bugs, and must never be backported unless their commit message
|
|
||||||
explicitly requests so.
|
|
||||||
|
|
||||||
ENDCONTEXT
|
|
||||||
|
|
||||||
A developer is reviewing the development branch, trying to spot which commits
|
|
||||||
need to be backported to maintenance branches. This person is already expert
|
|
||||||
on HAProxy and everything related to Git, patch management, and the risks
|
|
||||||
associated with backports, so he doesn't want to be told how to proceed nor to
|
|
||||||
review the contents of the patch.
|
|
||||||
|
|
||||||
The goal for this developer is to get some help from the AI assistant to save
|
|
||||||
some precious time on this tedious review work. In order to do a better job, he
|
|
||||||
needs an accurate summary of the information and instructions found in each
|
|
||||||
commit message. Specifically he needs to figure if the patch fixes a problem
|
|
||||||
affecting an older branch or not, if it needs to be backported, if so to which
|
|
||||||
branches, and if other patches need to be backported along with it.
|
|
||||||
|
|
||||||
The indented text block below after an "id" line and starting with a Subject line
|
|
||||||
is a commit message from the HAProxy development branch that describes a patch
|
|
||||||
applied to that branch, starting with its subject line, please read it carefully.
|
|
||||||
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
ENDINPUT
|
|
||||||
BEGININSTRUCTION
|
|
||||||
|
|
||||||
You are an AI assistant that follows instruction extremely well. Help as much
|
|
||||||
as you can, responding to a single question using a single response.
|
|
||||||
|
|
||||||
The developer wants to know if he needs to backport the patch above to fix
|
|
||||||
maintenance branches, for which branches, and what possible dependencies might
|
|
||||||
be mentioned in the commit message. Carefully study the commit message and its
|
|
||||||
backporting instructions if any (otherwise it should probably not be backported),
|
|
||||||
then provide a very concise and short summary that will help the developer decide
|
|
||||||
to backport it, or simply to skip it.
|
|
||||||
|
|
||||||
Start by explaining in one or two sentences what you recommend for this one and why.
|
|
||||||
Finally, based on your analysis, give your general conclusion as "Conclusion: X"
|
|
||||||
where X is a single word among:
|
|
||||||
- "yes", if you recommend to backport the patch right now either because
|
|
||||||
it explicitly states this or because it's a fix for a bug that affects
|
|
||||||
a maintenance branch (3.4 or lower);
|
|
||||||
- "wait", if this patch explicitly mentions that it must be backported, but
|
|
||||||
only after waiting some time.
|
|
||||||
- "no", if nothing clearly indicates a necessity to backport this patch (e.g.
|
|
||||||
lack of explicit backport instructions, or it's just an improvement);
|
|
||||||
- "uncertain" otherwise for cases not covered above
|
|
||||||
|
|
||||||
ENDINSTRUCTION
|
|
||||||
|
|
||||||
Explanation:
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
HAProxy
|
HAProxy
|
||||||
Configuration Manual
|
Configuration Manual
|
||||||
----------------------
|
----------------------
|
||||||
version 3.5
|
version 3.4
|
||||||
2026/06/25
|
2026/05/20
|
||||||
|
|
||||||
|
|
||||||
This document covers the configuration language as implemented in the version
|
This document covers the configuration language as implemented in the version
|
||||||
|
|
@ -3329,7 +3329,7 @@ setenv <name> <value>
|
||||||
the configuration file sees the new value. See also "presetenv", "resetenv",
|
the configuration file sees the new value. See also "presetenv", "resetenv",
|
||||||
and "unsetenv".
|
and "unsetenv".
|
||||||
|
|
||||||
shm-stats-file <name>
|
shm-stats-file <name> [ EXPERIMENTAL ]
|
||||||
When this directive is set, it enables the use of shared memory for storing
|
When this directive is set, it enables the use of shared memory for storing
|
||||||
stats counters. <name> is used as argument to shm_open() to open the shared
|
stats counters. <name> is used as argument to shm_open() to open the shared
|
||||||
memory at a unique location. It also means that the directive is only
|
memory at a unique location. It also means that the directive is only
|
||||||
|
|
@ -3345,7 +3345,7 @@ shm-stats-file <name>
|
||||||
|
|
||||||
See also "guid", "guid-prefix" and "shm-stats-file-max-objects"
|
See also "guid", "guid-prefix" and "shm-stats-file-max-objects"
|
||||||
|
|
||||||
shm-stats-file-max-objects <number>
|
shm-stats-file-max-objects <number> [ EXPERIMENTAL ]
|
||||||
This setting defines the maximum number of objects the shared memory used
|
This setting defines the maximum number of objects the shared memory used
|
||||||
for shared counters will be able to store per thread group. It is directly
|
for shared counters will be able to store per thread group. It is directly
|
||||||
related to the maximum memory size of the shm and is used to "premap" the
|
related to the maximum memory size of the shm and is used to "premap" the
|
||||||
|
|
@ -4940,8 +4940,8 @@ tune.lua.openlibs [all | none | <lib>[,<lib>...]]
|
||||||
tune.lua.openlibs string,math,table,utf8 # safe subset, no I/O or OS
|
tune.lua.openlibs string,math,table,utf8 # safe subset, no I/O or OS
|
||||||
tune.lua.openlibs all # default, load everything
|
tune.lua.openlibs all # default, load everything
|
||||||
|
|
||||||
This setting must be set before any "lua-load", "lua-load-per-thread" or
|
This setting must be set before any "lua-load" or "lua-load-per-thread"
|
||||||
"lua-prepend-path" directive, otherwise a parse error is returned.
|
directive, otherwise a parse error is returned.
|
||||||
|
|
||||||
tune.lua.service-timeout <timeout>
|
tune.lua.service-timeout <timeout>
|
||||||
This is the execution timeout for the Lua services. This is useful for
|
This is the execution timeout for the Lua services. This is useful for
|
||||||
|
|
@ -6160,6 +6160,7 @@ default-server X - X X
|
||||||
default_backend X X X -
|
default_backend X X X -
|
||||||
description - X X X
|
description - X X X
|
||||||
disabled X X X X
|
disabled X X X X
|
||||||
|
dispatch (deprecated) - - X X
|
||||||
email-alert from X X X X
|
email-alert from X X X X
|
||||||
email-alert level X X X X
|
email-alert level X X X X
|
||||||
email-alert mailers X X X X
|
email-alert mailers X X X X
|
||||||
|
|
@ -6268,6 +6269,7 @@ option tcp-smart-accept (*) X X X -
|
||||||
option tcp-smart-connect (*) X - X X
|
option tcp-smart-connect (*) X - X X
|
||||||
option tcpka X X X X
|
option tcpka X X X X
|
||||||
option tcplog X X X -
|
option tcplog X X X -
|
||||||
|
option transparent (deprecated) (*) X - X X
|
||||||
option use-small-buffers (*) X - X X
|
option use-small-buffers (*) X - X X
|
||||||
persist rdp-cookie X - X X
|
persist rdp-cookie X - X X
|
||||||
quic-initial X (!) X X -
|
quic-initial X (!) X X -
|
||||||
|
|
@ -6329,6 +6331,7 @@ timeout server X - X X
|
||||||
timeout server-fin X - X X
|
timeout server-fin X - X X
|
||||||
timeout tarpit X X X X
|
timeout tarpit X X X X
|
||||||
timeout tunnel X - X X
|
timeout tunnel X - X X
|
||||||
|
transparent (deprecated) X - X X
|
||||||
unique-id-format X X X X
|
unique-id-format X X X X
|
||||||
unique-id-header X X X -
|
unique-id-header X X X -
|
||||||
use_backend - X X -
|
use_backend - X X -
|
||||||
|
|
@ -6743,7 +6746,7 @@ balance url_param <param> [check_post]
|
||||||
might be a URL parameter list. This is probably not a concern with SGML
|
might be a URL parameter list. This is probably not a concern with SGML
|
||||||
type message bodies.
|
type message bodies.
|
||||||
|
|
||||||
See also : "cookie", "hash-type".
|
See also : "dispatch", "cookie", "transparent", "hash-type".
|
||||||
|
|
||||||
|
|
||||||
bind [<address>]:<port_range> [, ...] [param*]
|
bind [<address>]:<port_range> [, ...] [param*]
|
||||||
|
|
@ -7524,6 +7527,54 @@ disabled
|
||||||
See also : "enabled", "force-be-switch"
|
See also : "enabled", "force-be-switch"
|
||||||
|
|
||||||
|
|
||||||
|
dispatch <address>:<port> (deprecated)
|
||||||
|
Set a default server address
|
||||||
|
|
||||||
|
May be used in the following contexts: tcp, http
|
||||||
|
|
||||||
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
|
no | no | yes | yes
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
|
||||||
|
<address> is the IPv4 address of the default server. Alternatively, a
|
||||||
|
resolvable hostname is supported, but this name will be resolved
|
||||||
|
during start-up.
|
||||||
|
|
||||||
|
<ports> is a mandatory port specification. All connections will be sent
|
||||||
|
to this port, and it is not permitted to use port offsets as is
|
||||||
|
possible with normal servers.
|
||||||
|
|
||||||
|
The "dispatch" keyword designates a default server for use when no other
|
||||||
|
server can take the connection. In the past it was used to forward non
|
||||||
|
persistent connections to an auxiliary load balancer. Due to its simple
|
||||||
|
syntax, it has also been used for simple TCP relays. It is recommended not to
|
||||||
|
use it for more clarity, and to use the "server" directive instead.
|
||||||
|
|
||||||
|
This keyword has been deprecated in 3.3 and will be removed in 3.5 due to
|
||||||
|
some internal limitations (no support for SSL nor idle connections etc).
|
||||||
|
Using it will emit a warning that may be silenced by enabling directive
|
||||||
|
"expose-deprecated-directives" in the global section.
|
||||||
|
|
||||||
|
The correct way to proceed without this directive is to simply declare a
|
||||||
|
server with the same address and port. If the "dispatch" directive was
|
||||||
|
mixed with other servers, then these servers should be configured with a
|
||||||
|
weight of zero in order never to be elected by the load balancing algorithm.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
backend deprecated_setup
|
||||||
|
dispatch 192.168.100.100:80 # external load balancer's address
|
||||||
|
server s1 192.168.100.1:80 cookie S1 check
|
||||||
|
server s2 192.168.100.2:80 cookie S2 check
|
||||||
|
|
||||||
|
backend modern_setup
|
||||||
|
server external_lb 192.168.100.100:80
|
||||||
|
server s1 192.168.100.1:80 cookie S1 check weight 0
|
||||||
|
server s2 192.168.100.2:80 cookie S2 check weight 0
|
||||||
|
|
||||||
|
See also : "server"
|
||||||
|
|
||||||
|
|
||||||
dynamic-cookie-key <string>
|
dynamic-cookie-key <string>
|
||||||
Set the dynamic cookie secret key for a backend.
|
Set the dynamic cookie secret key for a backend.
|
||||||
|
|
||||||
|
|
@ -9054,9 +9105,7 @@ http-reuse { never | safe | aggressive | always }
|
||||||
- proxy protocol
|
- proxy protocol
|
||||||
- TOS and mark socket options
|
- TOS and mark socket options
|
||||||
- connection name, determined either by the result of the evaluation of the
|
- connection name, determined either by the result of the evaluation of the
|
||||||
"pool-conn-name" expression if present, otherwise by the "sni" expression,
|
"pool-conn-name" expression if present, otherwise by the "sni" expression
|
||||||
which defaults to "req.hdr(host),field(1,:)", i.e. uses the incoming
|
|
||||||
request's "Host" header field without the colon nor the port number.
|
|
||||||
|
|
||||||
In some occasions, connection lookup or reuse is not performed due to extra
|
In some occasions, connection lookup or reuse is not performed due to extra
|
||||||
restrictions. This is determined by the reuse strategy specified via the
|
restrictions. This is determined by the reuse strategy specified via the
|
||||||
|
|
@ -9130,26 +9179,6 @@ http-reuse { never | safe | aggressive | always }
|
||||||
too few connections are kept open. It may be desirable in this case to adjust
|
too few connections are kept open. It may be desirable in this case to adjust
|
||||||
such thresholds or simply to increase the global "maxconn" value.
|
such thresholds or simply to increase the global "maxconn" value.
|
||||||
|
|
||||||
In some rare cases, when the host name is used to distinguish outgoing TLS
|
|
||||||
connections (e.g. forward proxy), where most request target different hosts,
|
|
||||||
the reuse rate will be very low, and the automatic eviction of rarely used
|
|
||||||
connections will kick in before connections have a chance to be reused,
|
|
||||||
because the mechanism continuously measures the average number of connections
|
|
||||||
needed to deliver the service without exhausting resources. In such
|
|
||||||
situations, setting "pool-low-conn" to a value close to the average expected
|
|
||||||
number of idle connections may help preserve more connections by encouraging
|
|
||||||
threads to setup their own instead of trying to pick other threads' and
|
|
||||||
shrinking the pool of available connections.
|
|
||||||
|
|
||||||
If a locally hosted server uses a single certificate (with multiple host
|
|
||||||
names or wildcards) and operates multiple sites, it may be more effective to
|
|
||||||
just use "no-sni-auto" on the "server" line to avoid reserving a connection
|
|
||||||
to a single Host name. This will significantly increase the reuse rate. Some
|
|
||||||
servers might perform excessive checks between Host and SNI though, resulting
|
|
||||||
in rejecting subsequent requests, so this option requires preliminary
|
|
||||||
validation. The default behavior ("sni-auto") is to be safe even with such
|
|
||||||
servers.
|
|
||||||
|
|
||||||
When thread groups are explicitly enabled, it is important to understand that
|
When thread groups are explicitly enabled, it is important to understand that
|
||||||
idle connections are only usable between threads from a same group. As such
|
idle connections are only usable between threads from a same group. As such
|
||||||
it may happen that unfair load between groups leads to more idle connections
|
it may happen that unfair load between groups leads to more idle connections
|
||||||
|
|
@ -9933,7 +9962,7 @@ no option accept-unsafe-violations-in-http-request
|
||||||
When this option is set, the following rules are observed:
|
When this option is set, the following rules are observed:
|
||||||
|
|
||||||
* In H1 only, invalid characters, including NULL character, in header name
|
* In H1 only, invalid characters, including NULL character, in header name
|
||||||
will not be rejected; however the header will be dropped.
|
will be accepted;
|
||||||
|
|
||||||
* In H1 only, NULL character in header value will be accepted;
|
* In H1 only, NULL character in header value will be accepted;
|
||||||
|
|
||||||
|
|
@ -9998,11 +10027,8 @@ no option accept-unsafe-violations-in-http-response
|
||||||
|
|
||||||
When this option is set, the following rules are observed:
|
When this option is set, the following rules are observed:
|
||||||
|
|
||||||
* In H1 only, status codes longer than 3 digits but whose value fits in 16
|
|
||||||
bits are not rejected.
|
|
||||||
|
|
||||||
* In H1 only, invalid characters, including NULL character, in header name
|
* In H1 only, invalid characters, including NULL character, in header name
|
||||||
will not be rejected; however the header will be dropped.
|
will be accepted;
|
||||||
|
|
||||||
* In H1 only, NULL character in header value will be accepted;
|
* In H1 only, NULL character in header value will be accepted;
|
||||||
|
|
||||||
|
|
@ -12086,6 +12112,46 @@ option tcplog [clf]
|
||||||
See also : "option httplog", and section 8 about logging.
|
See also : "option httplog", and section 8 about logging.
|
||||||
|
|
||||||
|
|
||||||
|
option transparent (deprecated)
|
||||||
|
no option transparent (deprecated)
|
||||||
|
Enable client-side transparent proxying
|
||||||
|
|
||||||
|
May be used in the following contexts: tcp, http
|
||||||
|
|
||||||
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
|
yes | no | yes | yes
|
||||||
|
|
||||||
|
Arguments : none
|
||||||
|
|
||||||
|
This option was introduced in order to provide layer 7 persistence to layer 3
|
||||||
|
load balancers. The idea is to use the OS's ability to redirect an incoming
|
||||||
|
connection for a remote address to a local process (here HAProxy), and let
|
||||||
|
this process know what address was initially requested. When this option is
|
||||||
|
used, sessions without cookies will be forwarded to the original destination
|
||||||
|
IP address of the incoming request (which should match that of another
|
||||||
|
equipment), while requests with cookies will still be forwarded to the
|
||||||
|
appropriate server.
|
||||||
|
|
||||||
|
Note that contrary to a common belief, this option does NOT make HAProxy
|
||||||
|
present the client's IP to the server when establishing the connection.
|
||||||
|
|
||||||
|
As of 3.3, this option is now deprecated because it used to suffer from a
|
||||||
|
number of internal technical limitations. Using it will emit a warning, which
|
||||||
|
can be avoided if really needed via the "expose-deprecated-directives" global
|
||||||
|
keyword.
|
||||||
|
|
||||||
|
The correct approach is to declare a server on address 0.0.0.0, which will
|
||||||
|
take care of connecting to the expected destination address. A server will
|
||||||
|
also properly handle idle connections to the target servers.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
# option transparent ## before 3.3
|
||||||
|
server transparent 0.0.0.0
|
||||||
|
|
||||||
|
See also: the "usesrc" argument of the "source" keyword, and the
|
||||||
|
"transparent" option of the "bind" keyword.
|
||||||
|
|
||||||
|
|
||||||
option use-small-buffers [ queue | l7-retries | check ]*
|
option use-small-buffers [ queue | l7-retries | check ]*
|
||||||
|
|
||||||
Enable support for small buffers for the given categories.
|
Enable support for small buffers for the given categories.
|
||||||
|
|
@ -12514,9 +12580,9 @@ server <name> <address>[:[port]] [param*]
|
||||||
address as the one from the client connection. This is useful in
|
address as the one from the client connection. This is useful in
|
||||||
transparent proxy architectures where the client's connection is
|
transparent proxy architectures where the client's connection is
|
||||||
intercepted and HAProxy must forward to the original destination
|
intercepted and HAProxy must forward to the original destination
|
||||||
address. This is more or less what the old "transparent" keyword
|
address. This is more or less what the "transparent" keyword does
|
||||||
did except that servers do not have the keyword's limitations
|
except that with a server it's possible to limit concurrency and
|
||||||
(ssl, queues etc). Optionally, an address family prefix may be
|
to report statistics. Optionally, an address family prefix may be
|
||||||
used before the address to force the family regardless of the
|
used before the address to force the family regardless of the
|
||||||
address format, which can be useful to specify a path to a unix
|
address format, which can be useful to specify a path to a unix
|
||||||
socket with no slash ('/'). Currently supported prefixes are :
|
socket with no slash ('/'). Currently supported prefixes are :
|
||||||
|
|
@ -15071,6 +15137,32 @@ timeout tunnel <timeout>
|
||||||
See also : "timeout client", "timeout client-fin", "timeout server".
|
See also : "timeout client", "timeout client-fin", "timeout server".
|
||||||
|
|
||||||
|
|
||||||
|
transparent (deprecated)
|
||||||
|
Enable client-side transparent proxying
|
||||||
|
|
||||||
|
May be used in the following contexts: tcp, http
|
||||||
|
|
||||||
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
|
yes | no | yes | yes
|
||||||
|
|
||||||
|
Arguments : none
|
||||||
|
|
||||||
|
This keyword was introduced in order to provide layer 7 persistence to layer
|
||||||
|
3 load balancers. The idea is to use the OS's ability to redirect an incoming
|
||||||
|
connection for a remote address to a local process (here HAProxy), and let
|
||||||
|
this process know what address was initially requested. When this option is
|
||||||
|
used, sessions without cookies will be forwarded to the original destination
|
||||||
|
IP address of the incoming request (which should match that of another
|
||||||
|
equipment), while requests with cookies will still be forwarded to the
|
||||||
|
appropriate server.
|
||||||
|
|
||||||
|
The "transparent" keyword is deprecated, use "option transparent" instead.
|
||||||
|
|
||||||
|
Note that contrary to a common belief, this option does NOT make HAProxy
|
||||||
|
present the client's IP to the server when establishing the connection.
|
||||||
|
|
||||||
|
See also: "option transparent"
|
||||||
|
|
||||||
unique-id-format <fmt>
|
unique-id-format <fmt>
|
||||||
Generate a unique ID for each request.
|
Generate a unique ID for each request.
|
||||||
|
|
||||||
|
|
@ -19804,13 +19896,11 @@ sni-auto
|
||||||
May be used in the following contexts: tcp, http, log, peers, ring
|
May be used in the following contexts: tcp, http, log, peers, ring
|
||||||
|
|
||||||
The "sni-auto" parameter enables the automatic SNI selection, if no value was
|
The "sni-auto" parameter enables the automatic SNI selection, if no value was
|
||||||
already set. It sets the "sni" expression to "req.hdr(host),field(1,:)",
|
already set. It is enabled by default but this parameter may be used as
|
||||||
which means that an SNI will be presented with the Host name of the request
|
"server" setting to reset any "no-sni-auto" setting which would have been
|
||||||
that is being sent to the server, but dropping the port number. It is enabled
|
inherited from "default-server" directive as default value. It may also be
|
||||||
by default but this parameter may be used as "server" setting to reset any
|
used as "default-server" setting to reset any previous "default-server"
|
||||||
"no-sni-auto" setting which would have been inherited from "default-server"
|
"no-sni-auto" setting.
|
||||||
directive as default value. It may also be used as "default-server" setting
|
|
||||||
to reset any previous "default-server" "no-sni-auto" setting.
|
|
||||||
|
|
||||||
For HTTPS connections, the selected SNI is based on the request host header
|
For HTTPS connections, the selected SNI is based on the request host header
|
||||||
value, if found. Otherwise it remains unset. For other protocols, the option
|
value, if found. Otherwise it remains unset. For other protocols, the option
|
||||||
|
|
@ -30576,9 +30666,41 @@ See also: "use-fcgi-app", section 9.2 about the compression filter, section 9.4
|
||||||
9.6. OpenTracing
|
9.6. OpenTracing
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The OpenTracing filter was removed in version 3.5. A replacement filter based
|
The OpenTracing filter adds native support for using distributed tracing in
|
||||||
on OpenTelemetry is available since 3.4 with complete build instructions
|
HAProxy. This is enabled by sending an OpenTracing compliant request to one
|
||||||
currently at:
|
of the supported tracers such as Datadog, Jaeger, Lightstep and Zipkin tracers.
|
||||||
|
Please note: tracers are not listed by any preference, but alphabetically.
|
||||||
|
|
||||||
|
This feature is only enabled when HAProxy was built with USE_OT=1.
|
||||||
|
|
||||||
|
The OpenTracing filter activation is done explicitly by specifying it in the
|
||||||
|
HAProxy configuration. If this is not done, the OpenTracing filter in no way
|
||||||
|
participates in the work of HAProxy.
|
||||||
|
|
||||||
|
filter opentracing [id <id>] config <file>
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
|
||||||
|
<id> is the OpenTracing filter id that will be used to find the
|
||||||
|
right scope in the configuration file. If no filter id is
|
||||||
|
specified, 'ot-filter' is used as default. If scope is not
|
||||||
|
specified in the configuration file, it applies to all defined
|
||||||
|
OpenTracing filters.
|
||||||
|
|
||||||
|
<file> is the path of the OpenTracing configuration file. The same
|
||||||
|
file can contain configurations for multiple OpenTracing
|
||||||
|
filters simultaneously. In that case we do not need to define
|
||||||
|
scope so the same configuration applies to all filters or each
|
||||||
|
filter must have its own scope defined.
|
||||||
|
|
||||||
|
More detailed documentation related to the operation, configuration and use
|
||||||
|
of the filter can be found in the addons/ot directory.
|
||||||
|
|
||||||
|
Note: The OpenTracing filter shouldn't be used for new designs as OpenTracing
|
||||||
|
itself is no longer maintained nor supported by its authors. As such
|
||||||
|
OpenTracing will be deprecated in 3.3 and removed in 3.5. A replacement
|
||||||
|
filter based on OpenTelemetry is available since 3.4 with complete build
|
||||||
|
instructions currently at:
|
||||||
|
|
||||||
https://github.com/haproxytech/haproxy-opentelemetry/
|
https://github.com/haproxytech/haproxy-opentelemetry/
|
||||||
|
|
||||||
|
|
@ -32488,9 +32610,9 @@ https://github.com/haproxy/wiki/wiki/ACME:--native-haproxy
|
||||||
Current limitations:
|
Current limitations:
|
||||||
- The feature is limited to the http-01, dns-01 or dns-persist-01 challenges
|
- The feature is limited to the http-01, dns-01 or dns-persist-01 challenges
|
||||||
for now. http-01 is completely handled by HAProxy, but dns-01 and
|
for now. http-01 is completely handled by HAProxy, but dns-01 and
|
||||||
dns-persist-01 needs either the dataplaneAPI, a lua script using event_hdl or
|
dns-persist-01 needs either the dataplaneAPI or another 3rd party
|
||||||
another 3rd party tool to talk to a DNS provider API. dns-persist-01 only
|
tool to talk to a DNS provider API. dns-persist-01 only needs the TXT entry
|
||||||
needs the TXT entry to be set once, so it could be set manually without a tool.
|
to be set once, so it could be set manually without a tool.
|
||||||
- It is possible to start without an existing certificate on the disk. To do
|
- It is possible to start without an existing certificate on the disk. To do
|
||||||
so, the certificate must configured in a crt-store.
|
so, the certificate must configured in a crt-store.
|
||||||
When using the "acme" keyword in a crt-store, a temporary key pair will be
|
When using the "acme" keyword in a crt-store, a temporary key pair will be
|
||||||
|
|
@ -32561,8 +32683,6 @@ challenge-ready <value>[,<value>]*
|
||||||
"acme challenge_ready <crt> domain <domain>" on the master CLI or
|
"acme challenge_ready <crt> domain <domain>" on the master CLI or
|
||||||
the stats socket. This allows an external DNS provisioning tool to
|
the stats socket. This allows an external DNS provisioning tool to
|
||||||
confirm that the TXT record has been set before HAProxy proceeds.
|
confirm that the TXT record has been set before HAProxy proceeds.
|
||||||
It is also possible to signal the "cli" readiness using the
|
|
||||||
ACME.challenge_ready() lua function.
|
|
||||||
|
|
||||||
dns - perform a DNS pre-check by resolving the TXT record for
|
dns - perform a DNS pre-check by resolving the TXT record for
|
||||||
"_acme-challenge.<domain>" using the configured "default" resolvers
|
"_acme-challenge.<domain>" using the configured "default" resolvers
|
||||||
|
|
|
||||||
|
|
@ -526,6 +526,12 @@ In addition, some variables are related to the global runqueue:
|
||||||
unsigned int grq_total; /* total number of entries in the global run queue, atomic */
|
unsigned int grq_total; /* total number of entries in the global run queue, atomic */
|
||||||
static unsigned int global_rqueue_ticks; /* insertion count in the grq, use rq_lock */
|
static unsigned int global_rqueue_ticks; /* insertion count in the grq, use rq_lock */
|
||||||
|
|
||||||
|
And others to the global wait queue:
|
||||||
|
struct eb_root timers; /* sorted timers tree, global, accessed under wq_lock */
|
||||||
|
__decl_aligned_rwlock(wq_lock); /* RW lock related to the wait queue */
|
||||||
|
struct eb_root timers; /* sorted timers tree, global, accessed under wq_lock */
|
||||||
|
|
||||||
|
|
||||||
2022-06-14 - progress on task affinity
|
2022-06-14 - progress on task affinity
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue