mirror of
https://github.com/haproxy/haproxy.git
synced 2026-07-11 10:07:10 -04:00
Compare commits
149 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d2381c5ee | ||
|
|
46c3edcb16 | ||
|
|
96c7759f3b | ||
|
|
3b2cd5f9fb | ||
|
|
29f5126317 | ||
|
|
4fbc3e36c1 | ||
|
|
9e2809508b | ||
|
|
9ac590b55e | ||
|
|
475a69d224 | ||
|
|
39233e0a67 | ||
|
|
66d5d6a54b | ||
|
|
51377f9dfb | ||
|
|
954614c03a | ||
|
|
6f8c422252 | ||
|
|
25fcee5b0c | ||
|
|
7f3c30d96c | ||
|
|
e1b02eba9b | ||
|
|
77c4de1ec2 | ||
|
|
b089325f0e | ||
|
|
731b71363f | ||
|
|
2a27062f9a | ||
|
|
f4da8e0299 | ||
|
|
bbbd7909bc | ||
|
|
ef73a1f64a | ||
|
|
dc50a814c7 | ||
|
|
912b82d078 | ||
|
|
0386ec2544 | ||
|
|
6750c36adf | ||
|
|
f34517a1aa | ||
|
|
9a8f923b02 | ||
|
|
16d259c5db | ||
|
|
55a1bb9e09 | ||
|
|
0a11d75c1b | ||
|
|
cfe708d049 | ||
|
|
caaacb4fc1 | ||
|
|
3248ba100d | ||
|
|
7f37cf8cc0 | ||
|
|
0792e211e3 | ||
|
|
1d6138909e | ||
|
|
3a3a347c72 | ||
|
|
e4dceb44a3 | ||
|
|
1e36317346 | ||
|
|
aebe561d4d | ||
|
|
da4b7df81d | ||
|
|
788219f905 | ||
|
|
e090316735 | ||
|
|
236bb6d5f9 | ||
|
|
0ed430864e | ||
|
|
5a6ce04810 | ||
|
|
36243965a0 | ||
|
|
a608d2cade | ||
|
|
b71d27e253 | ||
|
|
ba6c518ee2 | ||
|
|
69caa53530 | ||
|
|
e9a4746f58 | ||
|
|
baec1a9c37 | ||
|
|
ac37158a6d | ||
|
|
2b993de2da | ||
|
|
ee5cfaf266 | ||
|
|
e528442847 | ||
|
|
ff95f204ec | ||
|
|
1e1e780b79 | ||
|
|
b81e271567 | ||
|
|
78dfc51c95 | ||
|
|
75e013727c | ||
|
|
d5c6431907 | ||
|
|
96f415006e | ||
|
|
bff33b4e32 | ||
|
|
13d465a61a | ||
|
|
b232b554f2 | ||
|
|
f245b15834 | ||
|
|
09814345d5 | ||
|
|
351c7e6598 | ||
|
|
f583269db9 | ||
|
|
a6906d799f | ||
|
|
0ed6d1f840 | ||
|
|
635d91aad9 | ||
|
|
fcbea9e0d0 | ||
|
|
e4e99282ca | ||
|
|
b39d2afe48 | ||
|
|
3596904a8d | ||
|
|
753aa44416 | ||
|
|
73a4f6bea7 | ||
|
|
bf76275fff | ||
|
|
cc56803799 | ||
|
|
f2014ec474 | ||
|
|
c0c3a325a4 | ||
|
|
7dfe7d240e | ||
|
|
0bf32cee66 | ||
|
|
3939dc0577 | ||
|
|
382a495649 | ||
|
|
d92c997c68 | ||
|
|
1a4be29252 | ||
|
|
75163e93a8 | ||
|
|
5dff525422 | ||
|
|
6ea18e0c74 | ||
|
|
8ac1e3ff5b | ||
|
|
19d48c3d34 | ||
|
|
10166c16ad | ||
|
|
8bb55185f6 | ||
|
|
fa8ca0be4d | ||
|
|
b17a16b3e2 | ||
|
|
7fc3a52aaf | ||
|
|
50c00ee235 | ||
|
|
4fe06d8c83 | ||
|
|
364d16030a | ||
|
|
7f416252b5 | ||
|
|
f3411cb734 | ||
|
|
e237b4ff9f | ||
|
|
9aa081b17e | ||
|
|
80e0004c91 | ||
|
|
c6d71297bc | ||
|
|
e66c2c3acd | ||
|
|
146015e58b | ||
|
|
3ef29b4314 | ||
|
|
330d60020d | ||
|
|
b3ed9c1879 | ||
|
|
617bfe95f2 | ||
|
|
d28f0cb219 | ||
|
|
0ecbf8ffb4 | ||
|
|
6e3ba99ca8 | ||
|
|
477f29bf48 | ||
|
|
01f4e33ead | ||
|
|
f59da779ca | ||
|
|
af9bb8507d | ||
|
|
4949b0a9a7 | ||
|
|
e4bc2d6a83 | ||
|
|
47b20a72e2 | ||
|
|
9475e69920 | ||
|
|
7aec1e6d9a | ||
|
|
ff6bb343f4 | ||
|
|
c4d5b78c57 | ||
|
|
151a75ef7b | ||
|
|
8288e68f44 | ||
|
|
ea54d3fd1b | ||
|
|
b68be6d0a2 | ||
|
|
8bc48dfc1e | ||
|
|
9d64d390c8 | ||
|
|
ce417b2fb9 | ||
|
|
1cb254ad77 | ||
|
|
78639c7cf7 | ||
|
|
09172169bc | ||
|
|
66fe27298f | ||
|
|
d071a736c4 | ||
|
|
7adf94cfe1 | ||
|
|
6864526d05 | ||
|
|
848668c7ac | ||
|
|
be8159248f | ||
|
|
b12ef0aa44 |
259 changed files with 8756 additions and 14456 deletions
2
.github/matrix.py
vendored
2
.github/matrix.py
vendored
|
|
@ -172,7 +172,6 @@ def main(ref_name):
|
|||
"FLAGS": [
|
||||
'DEBUG="-DDEBUG_LIST"',
|
||||
"USE_ZLIB=1",
|
||||
"USE_OT=1",
|
||||
"OT_INC=${HOME}/opt-ot/include",
|
||||
"OT_LIB=${HOME}/opt-ot/lib",
|
||||
"OT_RUNPATH=1",
|
||||
|
|
@ -206,7 +205,6 @@ def main(ref_name):
|
|||
'ARCH_FLAGS="-g -fsanitize=address"',
|
||||
'OPT_CFLAGS="-O1"',
|
||||
"USE_ZLIB=1",
|
||||
"USE_OT=1",
|
||||
"DEBUG=-DDEBUG_STRICT=2",
|
||||
"OT_INC=${HOME}/opt-ot/include",
|
||||
"OT_LIB=${HOME}/opt-ot/lib",
|
||||
|
|
|
|||
2
.github/workflows/freebsd.yml
vendored
2
.github/workflows/freebsd.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
- name: "Build and test on FreeBSD"
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
release: "14.3"
|
||||
release: "14.4"
|
||||
prepare: |
|
||||
pkg update -f && pkg upgrade -y && pkg install -y openssl git gmake lua54 socat pcre2 python3
|
||||
run: |
|
||||
|
|
|
|||
11
.github/workflows/vtest.yml
vendored
11
.github/workflows/vtest.yml
vendored
|
|
@ -65,13 +65,6 @@ jobs:
|
|||
path: '~/opt/'
|
||||
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
|
||||
if: ${{ matrix.CC == 'i686-linux-gnu-gcc' }}
|
||||
run: sudo dpkg --add-architecture i386
|
||||
|
|
@ -99,10 +92,6 @@ jobs:
|
|||
- name: Install SSL ${{ matrix.ssl }}
|
||||
if: ${{ matrix.ssl && matrix.ssl != 'stock' && steps.cache_ssl.outputs.cache-hit != 'true' }}
|
||||
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
|
||||
if: ${{ contains(matrix.FLAGS, 'USE_WURFL=1') }}
|
||||
run: make -C addons/wurfl/dummy
|
||||
|
|
|
|||
116
CHANGELOG
116
CHANGELOG
|
|
@ -1,6 +1,122 @@
|
|||
ChangeLog :
|
||||
===========
|
||||
|
||||
2026/07/08 : 3.5-dev2
|
||||
- MINOR: proxy: permit to report version info for option deprecation
|
||||
- MAJOR: proxy: remove support for "dispatch" and "transparent" proxy keywords
|
||||
- MEDIUM: cli/show-fd: no longer accept filtering for dispatch mode
|
||||
- CLEANUP: connection: remove some checks for objt_proxy(conn->target)
|
||||
- CLEANUP: backend: drop checks for OBJ_TYPE_PROXY in connect() code
|
||||
- CLEANUP: trace: remove backend retrieval attempt from conn->target
|
||||
- MAJOR: ot: remove deprecated OpenTracing support
|
||||
- BUG/MEDIUM: h3: fix trace crash on frontend response headers
|
||||
- CI: github: remove OpenTracing leftovers
|
||||
- BUG/MEDIUM: mux_quic: fix memory leak of rx app_buf on stream free
|
||||
- MINOR: ssl: export ssl_sock_init_srv()
|
||||
- MEDIUM: httpclient: initialize the httpclient with default SSL values
|
||||
- BUG/MINOR: hq-interop: fix transcoding of wrapping response buffer
|
||||
- BUG/MINOR: hq-interop: support transcoding of absolute URI
|
||||
- BUG/MINOR: h3: adjust HTTP headers traces
|
||||
- MINOR: mux_quic: add minimal traces for QUIC MUX init/release
|
||||
- MINOR: hq-interop: add request start-line traces
|
||||
- MINOR: hq-interop: trace transcoding of response status line
|
||||
- MINOR: hq-interop: trace HTX headers
|
||||
- BUG/MEDIUM: server: initialise agent.health in srv_settings_init()
|
||||
- BUG/MINOR: sample: set SMP_F_CONST on srv_name fetch
|
||||
- MINOR: server: distinguish name references with new SRV_F_NAME_REFD flag
|
||||
- MEDIUM: server: add 'set server name' CLI command for runtime server renaming
|
||||
- REGTESTS: server: add test for 'set server name' CLI command
|
||||
- DOC: server: document 'set server name' CLI command
|
||||
- BUG/MEDIUM: servers: Use a refcount for port_range and free it properly
|
||||
- MINOR: hbuf: new lightweight hbuf API
|
||||
- MINOR: init: add no listener mode
|
||||
- MINOR: trace: add definitions for haload streams
|
||||
- MINOR: hldstream: add definition of hldstream struct objects
|
||||
- MINOR: obj_type: add OBJ_TYPE_HALOAD for haload stream objects
|
||||
- MINOR: stconn: add sc_hastream() and __sc_hastream() helpers
|
||||
- MINOR: stconn: export sc_new()
|
||||
- MINOR: server: export functions used during server initialization
|
||||
- MINOR: haload: import source code and documentation
|
||||
- MINOR: log: add app_log_raw() and send_log_raw() for binary-safe logging
|
||||
- BUG/MINOR: init: fix default global settings being overwritten by -G
|
||||
- BUG/MINOR: tools: fix invalid character detection in strl2ic()
|
||||
- BUG/MAJOR: htx: Don't swap buffers for empty HTX message with an error
|
||||
- CLEANUP: applet/http-client: Don't needlessly copy HTX flags after htx_xfer()
|
||||
- BUG/MINOR: mux-quic: Fix handling EOM after in qcs_http_rcv_buf()
|
||||
- BUG/MINOR: http-htx: Don't by-pass HTX API when merging cookie values
|
||||
- BUG/MEDIUM: h3: fix parser desync on error with multiple frames
|
||||
- BUG/MINOR: mux_quic: prevent multiple STOP_SENDING emission per stream
|
||||
- BUILD: quic: workaround a gcc bug saying "maybe used uninitialized" when USE_TRACE=0
|
||||
- CLEANUP: traces: get rid of a few rare empty args in TRACE calls
|
||||
- MINOR: compiler: add a macro to ignore all arguments
|
||||
- MINOR: trace: always pretend to use args when disabled
|
||||
- BUILD: ssl: avoid a wrong null deref warning in ssl_sock_handshake
|
||||
- CLEANUP: haproxy: remove -dt parsing and help when !USE_TRACE
|
||||
- CLEANUP: mux-h2/traces: remove unused trace code when building without USE_TRACE
|
||||
- CLEANUP: debug/trace: remote "debug dev trace" when USE_TRACE is not set
|
||||
- BUG/MINOR: trace/quic_frame: use buf, not trace_buf in chunk_frm_appendf()
|
||||
- CLEANUP: trace/h3: allow to disable traces in H3
|
||||
- CLEANUP: trace/config: do not register section "traces" with USE_TRACE=0
|
||||
- CLEANUP: trace/tree-wide: drop trace decoding/definition when USE_TRACE=0
|
||||
- BUILD: makefile: only build trace.c and ssl_trace.c when USE_TRACE is set
|
||||
- BUILD: makefile: add macros enable_opts and disable_opts
|
||||
- BUILD: makefile: add an option to enable or disable HTTP/2 (USE_H2)
|
||||
- BUILD: makefile: add an option to enable or disable FCGI (USE_FCGI)
|
||||
- BUILD: makefile: add an option to enable or disable SPOE (USE_SPOE)
|
||||
- BUILD: makefile: add a new generic target "tiny"
|
||||
- BUG/MEDIUM: mux_quic: do not free QCS if STOP_SENDING to sent
|
||||
- MINOR: mux_quic: use separate error code for STOP_SENDING
|
||||
- MINOR: mux_quic: adjust shut stream callback
|
||||
- BUG/MEDIUM: mux_quic: complete stream shutdown for read channel
|
||||
- BUG/MINOR: quic: ignore STREAM after MUX closure on BE side
|
||||
- BUG/MEDIUM: fd: Fix a deadlock when closing other tgroups fds
|
||||
- MEDIUM: quic: remove deprecated keywords
|
||||
- DEV: patchbot: keep the review start in sync with the radios on reload
|
||||
- DEV: patchbot: only display the first 8 chars of the commit id
|
||||
- DEV: patchbot: pass the branch version to the generated page
|
||||
- DEV: patchbot: let the page fetch the shared review state
|
||||
- DEV: patchbot: let the page save the review edits to the server
|
||||
- DEV: patchbot: let the page edit and delete whole notes
|
||||
- DEV: patchbot: gray the save button when there is nothing to save
|
||||
- DEV: patchbot: don't pretend a save succeeded when the server ignored it
|
||||
- DEV: patchbot: tolerate polluted save responses and show server warnings
|
||||
- DEV: patchbot: repeat the syncing buttons at the bottom of the page
|
||||
- DEV: patchbot: update: add an awk backend to persist review edits
|
||||
- DEV: patchbot: update: return the stored overlay as JSON on GET
|
||||
- DEV: patchbot: update: support replacing a whole note blob (setnotes)
|
||||
- DEV: patchbot: update: report git commit failures in the save response
|
||||
- DEV: patchbot: update: report the exact git error to the user
|
||||
- DEV: patchbot: update: never write to stderr, thttpd sends it first
|
||||
- DEV: patchbot: update: name the touched commits in the storage messages
|
||||
- DEV: patchbot: document the shared review persistence
|
||||
- BUG/MINOR: haload: fix spurious task wakeup in hld_strm_task()
|
||||
- BUG/MINOR: hbuf: treat unexpected escape sequences as literals
|
||||
- BUG/MEDIUM: tcpcheck: Add proxy used for healthcheck sections in proxies list
|
||||
- BUG/MINOR: sample: Fix a possible underflow on be2hex for large chunk size
|
||||
- MINOR: chunks: Add function to get a large/regular chunk depending on a buffer
|
||||
- BUG/MEDIUM: chunk: Review chunks usage to not retrieve a large buffer by error
|
||||
- MINOR: htx: Add a field to save the headers data size
|
||||
- MEDIUM: htx: Be sure size of headers never exceed regular buffer on update
|
||||
- BUG/MINOR: stream: Fix custom timeouts initialization when setting backend
|
||||
- REGTESTS: Improve script testing the set-timeout action
|
||||
- BUG/MINOR: stream: Fix custom max-retries initialization when setting backend
|
||||
- MINOR: stream: Add be_max_retries/cur_max_retries sample fetch functions
|
||||
- BUG/MINOR: http-conv: Make url-dec failed if no space for trailing null byte
|
||||
- MAJOR: mworker: remove deprecated "master-worker" global keyword
|
||||
- DOC: haterm: add a missing 'haterm' build target on an example
|
||||
- DOC: readme: add a pointer to haterm/haload docs
|
||||
- MINOR: ocsp: Do not see ocsp loading failures as fatal anymore
|
||||
- REGTESTS: Remove unused `add_range_to_test_list` function from `scripts/run-regtests.sh`
|
||||
- REGTESTS: Remove unused `_version` function from `scripts/run-regtests.sh`
|
||||
- REGTESTS: Migrate REQUIRE_OPTION to `haproxy -cc`
|
||||
- REGTESTS: Remove support for `REQUIRE_OPTION` from scripts/run-regtests.sh
|
||||
- REGTESTS: Migrate `REQUIRE_SERVICE=prometheus-exporter` to a `feature(PROMEX)` check
|
||||
- REGTESTS: Remove support for `REQUIRE_SERVICE` from scripts/run-regtests.sh
|
||||
- CI: github: update vmactions/freebsd-vm to 14.4
|
||||
- MINOR: haload: move statistics header printing to mtask_cb
|
||||
- MINOR: haterm: add note about QUIC usage on SSL port
|
||||
- MINOR: haload: allow "0" shortcut for IPv4 bind address
|
||||
|
||||
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
|
||||
|
|
|
|||
15
INSTALL
15
INSTALL
|
|
@ -475,9 +475,9 @@ are the extra libraries that may be referenced at build time :
|
|||
-------------------
|
||||
Some build errors may happen depending on the options combinations or the
|
||||
selected target. When facing build errors, if you know that your system is a
|
||||
bit special or particularly old, start from TARGET=generic, it is easier to
|
||||
start from there and fix the remaining issues than trying to degrade another
|
||||
target. Common issues may include:
|
||||
bit special or particularly old, start from TARGET=generic or TARGET=tiny; it
|
||||
is easier to start from there and fix the remaining issues than trying to
|
||||
degrade another target. Common issues may include:
|
||||
|
||||
- clock_gettime() not found
|
||||
=> your system needs USE_RT=1
|
||||
|
|
@ -579,6 +579,7 @@ and assign it to the TARGET variable :
|
|||
- haiku for Haiku
|
||||
- generic for any other OS or version.
|
||||
- custom to manually adjust every setting
|
||||
- tiny to turn all default options off by default
|
||||
|
||||
Example:
|
||||
$ make -j $(nproc) TARGET=linux-glibc
|
||||
|
|
@ -603,8 +604,14 @@ well use that property to define your own set of options. USE_POLL and USE_SLZ
|
|||
can even be disabled by setting them to an empty string or a zero. For
|
||||
example :
|
||||
|
||||
$ gmake TARGET=tiny USE_POLL="" USE_SLZ=0 TARGET_CFLAGS=-fomit-frame-pointer
|
||||
$ gmake TARGET=small USE_POLL="" USE_SLZ=0 TARGET_CFLAGS=-fomit-frame-pointer
|
||||
|
||||
Note that when seeking the absolute smallest build (e.g. for low-spec embedded
|
||||
devices), the "tiny" target disables everything configurable and generally
|
||||
results in a binary that's 4-5 times smaller than the default one. From this
|
||||
point it then becomes possible to enable only what is desired:
|
||||
|
||||
$ make -j $(nproc) TARGET=tiny USE_EPOLL=1 USE_DL=1 USE_OPENSSL=1
|
||||
|
||||
5.2) Adding extra CFLAGS for compiling
|
||||
--------------------------------------
|
||||
|
|
|
|||
76
Makefile
76
Makefile
|
|
@ -60,12 +60,14 @@
|
|||
# USE_WURFL : enable WURFL detection library from Scientiamobile
|
||||
# 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_OT : enable the OpenTracing filter
|
||||
# USE_MEMORY_PROFILING : enable the memory profiler. Linux-glibc only.
|
||||
# USE_LIBATOMIC : force to link with/without libatomic. Automatic.
|
||||
# USE_PTHREAD_EMULATION : replace pthread's rwlocks with ours
|
||||
# USE_SHM_OPEN : use shm_open() for features that can make use of shared memory
|
||||
# USE_KTLS : use kTLS.(requires at least Linux 4.17).
|
||||
# USE_FCGI : enable the FCGI subsystem. Always on.
|
||||
# USE_H2 : enable HTTP/2 subsystem. Always on.
|
||||
# USE_SPOE : enable the SPOE subsystem. Always on.
|
||||
#
|
||||
# Options can be forced by specifying "USE_xxx=1" or can be disabled by using
|
||||
# "USE_xxx=" (empty string). The list of enabled and disabled options for a
|
||||
|
|
@ -125,11 +127,6 @@
|
|||
# LUA_INC : force the include path to lua
|
||||
# LUA_LIB_NAME : force the lib name (or automatically evaluated, by order of
|
||||
# priority: lua5.5, lua55, 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.
|
||||
# VERSION : force haproxy version reporting.
|
||||
# SUBVERS : add a sub-version (eg: platform, model, ...).
|
||||
|
|
@ -160,7 +157,7 @@ DOCDIR = $(PREFIX)/doc/haproxy
|
|||
# following list (use the default "generic" if uncertain) :
|
||||
# linux-glibc, linux-glibc-legacy, linux-musl, solaris, freebsd, freebsd-glibc,
|
||||
# dragonfly, openbsd, netbsd, cygwin, haiku, aix51, aix52, aix72-gcc, osx, generic,
|
||||
# custom
|
||||
# custom, tiny
|
||||
TARGET =
|
||||
|
||||
#### No longer used
|
||||
|
|
@ -344,12 +341,12 @@ use_opts = USE_EPOLL USE_KQUEUE USE_NETFILTER USE_POLL \
|
|||
USE_TPROXY USE_LINUX_TPROXY USE_LINUX_CAP \
|
||||
USE_LINUX_SPLICE USE_LIBCRYPT USE_CRYPT_H USE_ENGINE \
|
||||
USE_GETADDRINFO USE_OPENSSL USE_OPENSSL_WOLFSSL USE_OPENSSL_AWSLC \
|
||||
USE_ECH USE_TRACE \
|
||||
USE_ECH USE_TRACE USE_FCGI USE_H2 USE_SPOE \
|
||||
USE_SSL USE_LUA USE_ACCEPT4 USE_CLOSEFROM USE_ZLIB USE_SLZ \
|
||||
USE_CPU_AFFINITY USE_TFO USE_NS USE_DL USE_RT USE_LIBATOMIC \
|
||||
USE_MATH USE_DEVICEATLAS USE_51DEGREES \
|
||||
USE_WURFL USE_OBSOLETE_LINKER USE_PRCTL USE_PROCCTL \
|
||||
USE_THREAD_DUMP USE_EVPORTS USE_OT USE_QUIC USE_PROMEX \
|
||||
USE_THREAD_DUMP USE_EVPORTS USE_QUIC USE_PROMEX \
|
||||
USE_MEMORY_PROFILING USE_SHM_OPEN \
|
||||
USE_STATIC_PCRE USE_STATIC_PCRE2 \
|
||||
USE_PCRE USE_PCRE_JIT USE_PCRE2 USE_PCRE2_JIT \
|
||||
|
|
@ -370,6 +367,15 @@ USE_POLL = default
|
|||
# traces are always enabled
|
||||
USE_TRACE = default
|
||||
|
||||
# FCGI is always enabled
|
||||
USE_FCGI = default
|
||||
|
||||
# HTTP/2 is always enabled
|
||||
USE_H2 = default
|
||||
|
||||
# SPOE is always enabled
|
||||
USE_SPOE = default
|
||||
|
||||
# SLZ is always supported unless explicitly disabled by passing USE_SLZ=""
|
||||
# or disabled by enabling ZLIB using USE_ZLIB=1
|
||||
ifeq ($(USE_ZLIB:0=),)
|
||||
|
|
@ -381,6 +387,13 @@ ifeq ($(TARGET),generic)
|
|||
set_target_defaults = $(call default_opts,USE_POLL USE_TPROXY)
|
||||
endif
|
||||
|
||||
# For embedded systems or to be used as a base, tiniest binary with fewest
|
||||
# features. Only poll() is enabled to avoid issues with select().
|
||||
ifeq ($(TARGET),tiny)
|
||||
set_target_defaults = $(call disable_opts,$(use_opts)) $(call enable_opts,USE_POLL)
|
||||
INSTALL = install -v
|
||||
endif
|
||||
|
||||
# Haiku
|
||||
ifeq ($(TARGET),haiku)
|
||||
TARGET_LDFLAGS = -lnetwork
|
||||
|
|
@ -573,6 +586,18 @@ ifneq ($(USE_ZLIB:0=),)
|
|||
ZLIB_LDFLAGS = $(if $(ZLIB_LIB),-L$(ZLIB_LIB)) -lz
|
||||
endif
|
||||
|
||||
ifneq ($(USE_H2:0=),)
|
||||
OPTIONS_OBJS += src/mux_h2.o src/h2.o
|
||||
endif
|
||||
|
||||
ifneq ($(USE_FCGI:0=),)
|
||||
OPTIONS_OBJS += src/mux_fcgi.o src/fcgi-app.o src/fcgi.o
|
||||
endif
|
||||
|
||||
ifneq ($(USE_SPOE:0=),)
|
||||
OPTIONS_OBJS += src/mux_spop.o src/flt_spoe.o
|
||||
endif
|
||||
|
||||
ifneq ($(USE_SLZ:0=),)
|
||||
OPTIONS_OBJS += src/slz.o
|
||||
endif
|
||||
|
|
@ -635,6 +660,7 @@ endif
|
|||
ifneq ($(USE_OPENSSL_AWSLC:0=),)
|
||||
# always automatically set USE_OPENSSL
|
||||
USE_OPENSSL := $(if $(USE_OPENSSL:0=),$(USE_OPENSSL:0=),implicit)
|
||||
OPTIONS_OBJS += src/fips.o
|
||||
endif
|
||||
|
||||
# This is for any variant of the OpenSSL API. By default it uses OpenSSL.
|
||||
|
|
@ -648,7 +674,10 @@ ifneq ($(USE_OPENSSL:0=),)
|
|||
OPTIONS_OBJS += src/ssl_sock.o src/ssl_ckch.o src/ssl_ocsp.o src/ssl_crtlist.o \
|
||||
src/ssl_sample.o src/cfgparse-ssl.o src/ssl_gencert.o \
|
||||
src/ssl_utils.o src/jwt.o src/ssl_clienthello.o src/jws.o src/acme.o \
|
||||
src/acme_resolvers.o src/ssl_trace.o src/jwe.o
|
||||
src/acme_resolvers.o src/jwe.o
|
||||
ifneq ($(USE_TRACE:0=),)
|
||||
OPTIONS_OBJS += src/ssl_trace.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(USE_ENGINE:0=),)
|
||||
|
|
@ -809,11 +838,6 @@ ifneq ($(USE_LINUX_CAP:0=),)
|
|||
OPTIONS_OBJS += src/linuxcap.o
|
||||
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),)
|
||||
include $(addsuffix /Makefile.mk,$(EXTRA_MAKE))
|
||||
endif
|
||||
|
|
@ -913,30 +937,31 @@ endif # TARGET
|
|||
|
||||
OBJS =
|
||||
HATERM_OBJS =
|
||||
HALOAD_OBJS =
|
||||
|
||||
ifneq ($(EXTRA_OBJS),)
|
||||
OBJS += $(EXTRA_OBJS)
|
||||
endif
|
||||
|
||||
OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o \
|
||||
OBJS += src/mux_h1.o src/log.o \
|
||||
src/server.o src/stream.o src/tcpcheck.o src/http_ana.o \
|
||||
src/stick_table.o src/tools.o src/mux_spop.o src/sample.o \
|
||||
src/stick_table.o src/tools.o src/sample.o \
|
||||
src/activity.o src/cfgparse.o src/peers.o src/cli.o \
|
||||
src/backend.o src/connection.o src/resolvers.o src/proxy.o \
|
||||
src/cache.o src/stconn.o src/http_htx.o src/debug.o \
|
||||
src/check.o src/stats-html.o src/haproxy.o src/listener.o \
|
||||
src/applet.o src/pattern.o src/cfgparse-listen.o \
|
||||
src/flt_spoe.o src/cebis_tree.o src/http_ext.o \
|
||||
src/cebis_tree.o src/http_ext.o \
|
||||
src/http_act.o src/http_fetch.o src/cebs_tree.o \
|
||||
src/cebib_tree.o src/http_client.o src/dns.o \
|
||||
src/cebb_tree.o src/vars.o src/event_hdl.o src/tcp_rules.o \
|
||||
src/trace.o src/stats-proxy.o src/pool.o src/stats.o \
|
||||
src/stats-proxy.o src/pool.o src/stats.o \
|
||||
src/cfgparse-global.o src/filters.o src/mux_pt.o \
|
||||
src/flt_http_comp.o src/sock.o src/h1.o src/sink.o \
|
||||
src/ceba_tree.o src/session.o src/payload.o src/htx.o \
|
||||
src/cebl_tree.o src/ceb32_tree.o src/ceb64_tree.o \
|
||||
src/server_state.o src/proto_rhttp.o src/flt_trace.o src/fd.o \
|
||||
src/task.o src/map.o src/fcgi-app.o src/h2.o src/mworker.o \
|
||||
src/task.o src/map.o src/mworker.o \
|
||||
src/tcp_sample.o src/mjson.o src/h1_htx.o src/tcp_act.o \
|
||||
src/ring.o src/flt_bwlim.o src/acl.o src/thread.o src/queue.o \
|
||||
src/http_rules.o src/http.o src/channel.o src/proto_tcp.o \
|
||||
|
|
@ -966,7 +991,13 @@ ifneq ($(TRACE),)
|
|||
OBJS += src/calltrace.o
|
||||
endif
|
||||
|
||||
HATERM_OBJS += $(OBJS) src/haterm_init.o
|
||||
ifneq ($(USE_TRACE:0=),)
|
||||
OBJS += src/trace.o
|
||||
endif
|
||||
|
||||
HATERM_OBJS += $(OBJS) src/haterm_init.o src/hbuf.o
|
||||
|
||||
HALOAD_OBJS += $(OBJS) src/haload_init.o src/haload.o src/hbuf.o
|
||||
|
||||
# Used only for forced dependency checking. May be cleared during development.
|
||||
INCLUDES = $(wildcard include/*/*.h)
|
||||
|
|
@ -1018,6 +1049,9 @@ haproxy: $(OPTIONS_OBJS) $(OBJS)
|
|||
haterm: $(OPTIONS_OBJS) $(HATERM_OBJS)
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
haload: $(OPTIONS_OBJS) $(HALOAD_OBJS)
|
||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||
|
||||
objsize: haproxy
|
||||
$(Q)objdump -t $^|grep ' g '|grep -F '.text'|awk '{print $$5 FS $$6}'|sort
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ Please refer to the following files depending on what you're looking for:
|
|||
- [BRANCHES](BRANCHES) to understand the project's life cycle and what version to use
|
||||
- [LICENSE](LICENSE) for the project's license
|
||||
- [CONTRIBUTING](CONTRIBUTING) for the process to follow to submit contributions
|
||||
- [ doc/haterm.txt ](doc/haterm.txt) and [ doc/haload.txt ](doc/haload.txt) for load generation utilities
|
||||
|
||||
The more detailed documentation is located into the doc/ directory:
|
||||
|
||||
|
|
|
|||
2
VERDATE
2
VERDATE
|
|
@ -1,2 +1,2 @@
|
|||
$Format:%ci$
|
||||
2026/06/25
|
||||
2026/07/08
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
3.5-dev1
|
||||
3.5-dev2
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Miroslav Zagorac <mzagorac@haproxy.com>
|
||||
|
|
@ -1 +0,0 @@
|
|||
Miroslav Zagorac <mzagorac@haproxy.com>
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
# 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
799
addons/ot/README
|
|
@ -1,799 +0,0 @@
|
|||
-----------------------------------------
|
||||
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%).
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
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() {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
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%).
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,397 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,764 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,354 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,312 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,223 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,634 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,815 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,841 +0,0 @@
|
|||
/***
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
--- 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
|
||||
----------------------------------------------------------------------
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
--- 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
|
||||
----------------------------------------------------------------------
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
--- 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
|
||||
----------------------------------------------------------------------
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
--- 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
|
||||
----------------------------------------------------------------------
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"service": "BE",
|
||||
"agent_host": "localhost",
|
||||
"agent_port": 8126
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"service_name": "BE",
|
||||
"collector_host": "localhost"
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
[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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"service": "CMP",
|
||||
"agent_host": "localhost",
|
||||
"agent_port": 8126
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"service_name": "CMP",
|
||||
"collector_host": "localhost"
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
[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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"service": "CTX",
|
||||
"agent_host": "localhost",
|
||||
"agent_port": 8126
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"service_name": "CTX",
|
||||
"collector_host": "localhost"
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
[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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"service": "EMPTY",
|
||||
"agent_host": "localhost",
|
||||
"agent_port": 8126
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"service_name": "EMPTY",
|
||||
"collector_host": "localhost"
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
ot-tracer ot-test-tracer
|
||||
config empty/cfg-jaeger.yml
|
||||
plugin libjaeger_opentracing_plugin-0.5.0.so
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"service": "FE",
|
||||
"agent_host": "localhost",
|
||||
"agent_port": 8126
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"service_name": "FE",
|
||||
"collector_host": "localhost"
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
[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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
test ${#} -lt 1 && exit 1
|
||||
|
||||
awk '/ {$/ { sub(/\(.*/, "", $5); print $5 }' "${@}" | sort | uniq -c
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
#!/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 +0,0 @@
|
|||
<html><body><p>Did I err?</p></body></html>
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"service": "SA",
|
||||
"agent_host": "localhost",
|
||||
"agent_port": 8126
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"service_name": "SA",
|
||||
"collector_host": "localhost"
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
[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
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -259,6 +259,7 @@ listed below. Metrics from extra counters are not listed.
|
|||
| haproxy_frontend_failed_header_rewriting_total |
|
||||
| haproxy_frontend_http_cache_lookups_total |
|
||||
| haproxy_frontend_http_cache_hits_total |
|
||||
| haproxy_frontend_http_cache_hint_hits_total |
|
||||
| haproxy_frontend_internal_errors_total |
|
||||
+-------------------------------------------------+
|
||||
|
||||
|
|
@ -329,6 +330,7 @@ listed below. Metrics from extra counters are not listed.
|
|||
| haproxy_backend_connection_reuses_total |
|
||||
| haproxy_backend_http_cache_lookups_total |
|
||||
| haproxy_backend_http_cache_hits_total |
|
||||
| haproxy_backend_http_cache_hint_hits_total |
|
||||
| haproxy_backend_max_queue_time_seconds |
|
||||
| haproxy_backend_max_connect_time_seconds |
|
||||
| haproxy_backend_max_response_time_seconds |
|
||||
|
|
|
|||
|
|
@ -587,6 +587,7 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
|
|||
case ST_I_PX_INTERCEPTED:
|
||||
case ST_I_PX_CACHE_LOOKUPS:
|
||||
case ST_I_PX_CACHE_HITS:
|
||||
case ST_I_PX_CACHE_HINT_HITS:
|
||||
case ST_I_PX_COMP_IN:
|
||||
case ST_I_PX_COMP_OUT:
|
||||
case ST_I_PX_COMP_BYP:
|
||||
|
|
@ -1065,6 +1066,7 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||
case ST_I_PX_REQ_TOT:
|
||||
case ST_I_PX_CACHE_LOOKUPS:
|
||||
case ST_I_PX_CACHE_HITS:
|
||||
case ST_I_PX_CACHE_HINT_HITS:
|
||||
case ST_I_PX_COMP_IN:
|
||||
case ST_I_PX_COMP_OUT:
|
||||
case ST_I_PX_COMP_BYP:
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ proposed deployment layout is the following:
|
|||
| | +-- patches-3.0 # patches from development branch 3.0
|
||||
| |
|
||||
| +-- out # report directory (HTML)
|
||||
| |
|
||||
| +-- overlay # shared review state (git repo, optional)
|
||||
|
|
||||
+- prog
|
||||
| |
|
||||
|
|
@ -255,6 +257,91 @@ proposed deployment layout is the following:
|
|||
2 instances for 8 cores / 16 threads gives optimal results on dual memory
|
||||
channel systems.
|
||||
|
||||
- optionally, the review page can share the reviewers' edits (adjusted
|
||||
verdicts and short notes) between all users of the same server, thanks to a
|
||||
small CGI script storing them into a dedicated git repository. This part is
|
||||
entirely optional: without it the page keeps working standalone, edits are
|
||||
simply lost on reload as before. Three pieces are needed:
|
||||
|
||||
- the awk script from dev/patchbot/cgi (the server-side program).
|
||||
|
||||
- the storage repository, a plain git working tree which must also stay
|
||||
outside the served directory. The CGI commits every change into it, so a
|
||||
committer identity is required (git is the history: "git log" and "git
|
||||
blame" tell who changed what and when, and the files are plain text, one
|
||||
line per commit id, trivially hand-editable to fix anything):
|
||||
|
||||
mkdir ~/data/overlay
|
||||
cd ~/data/overlay
|
||||
git init
|
||||
git config user.name patchbot
|
||||
git config user.email patchbot@localhost
|
||||
cd ~
|
||||
|
||||
Note that the example above assumes that the web server will be running
|
||||
under the same user as the one owning the whole project, which is not
|
||||
necessarily a great idea. A better approach consists in creating the
|
||||
repository (and only it) under the web server's owner (e.g. "web" or
|
||||
"nobody"). Start with the same actions as above, then:
|
||||
|
||||
sudo chown -R nobody ~/data/overlay
|
||||
|
||||
A group-shared access might also work for server that let the user set a
|
||||
specific group (not tested). It's important to keep in mind that modern Git
|
||||
versions are particularly picky about permissions and will even refuse to
|
||||
read from another user's directory (and the safe.directory trick here
|
||||
cannot work). If required, a trick consists in forcing GIT_DIR to point to
|
||||
the .git dir, and GIT_WORK_TREE to the repo (only partially tested). E.g,
|
||||
for local edition:
|
||||
|
||||
cd ~patchbot/data/overlay/
|
||||
GIT_DIR=$PWD/.git GIT_WORK_TREE=$PWD git commit --amend
|
||||
|
||||
or more simply, when installed as nobody:
|
||||
|
||||
cd ~patchbot/data/overlay/
|
||||
sudo -u git commit --amend
|
||||
|
||||
Also note that the identity really must be set in the repository's local
|
||||
config as shown above and cannot be set globally (git config --global)
|
||||
because CGI processes receive a minimal environment without HOME nor USER,
|
||||
so git will not be able to read ~/.gitconfig and will fail to guess a valid
|
||||
identity ("unable to auto-detect email address"), aborting every commit.
|
||||
|
||||
If only Git stops working, the file will continue to be updated but no
|
||||
change history will be kept (a warning will be reported to the UI however).
|
||||
This might be acceptable in some deployments and might become a deployment
|
||||
option later if deemed useful.
|
||||
|
||||
- the "update.cgi" wrapper, copied from the haproxy tree into a "cgi-bin"
|
||||
sub-directory in the served directory, next to the generated HTML pages
|
||||
(the pages reach it with a relative URL). It's a small shell script holding
|
||||
the local paths, to be adjusted after copying:
|
||||
|
||||
mkdir -p -m 711 ~/data/out/cgi-bin/
|
||||
touch ~/data/out/cgi-bin/index.html
|
||||
cp ~/data/in/haproxy/dev/patchbot/cgi/update.cgi ~/data/out/cgi-bin/
|
||||
vi ~/data/out/cgi-bin/update.cgi # point it to the backend and the repo
|
||||
|
||||
Note that this wrapper also has a subtle role here: awk can easily die on
|
||||
some errors (failure to write to certain files etc) without producing a
|
||||
response. In this case the wrapper will detect it and report the error to
|
||||
the CGI server so that the browser stays informed of server-side issues.
|
||||
|
||||
The web server must be able to execute CGI scripts for this file (e.g.
|
||||
thttpd needs its "**.cgi" or "*/cgi-bin/*.cgi" pattern for it to be
|
||||
executed and not served as text, which would expose the paths it contains).
|
||||
This is the only web-exposed piece; the script and the repository must
|
||||
never be.
|
||||
|
||||
The update-X.Y.sh script deduces the branch from its own file name and
|
||||
passes it to post-ai.sh (-v) at generation time, which enables the syncing UI
|
||||
on the page; a page generated without -v simply doesn't show it.
|
||||
|
||||
Each save is committed with a subject naming the branch and the first touched
|
||||
commit, optionally followed with "+ N more" if more commits are updated, with
|
||||
the full list in the commit body to ease search via git log --grep.
|
||||
|
||||
From this point, executing this update script manually should work and produce
|
||||
the result. Count around 0.5-2 mn per patch on a 8-core machine, so it can be
|
||||
reasonably fast during the early development stages (before -dev1) but
|
||||
|
|
@ -320,9 +407,14 @@ Using the HTML output is a bit rustic but efficient. The interface is split in
|
|||
immediately, only after it has spent some time in the development branch),
|
||||
and "Y" for "Yes" in red (this patch must be backported, let's pick it).
|
||||
The choice is preselected by the scripts above, and since these are radio
|
||||
buttons, the user is free to change this selection. Reloading will lose the
|
||||
user's choices. When changing a selection, the line's background changes to
|
||||
match a similar color tone, allowing to visually spot preselected patches.
|
||||
buttons, the user is free to change this selection. A simple reload done
|
||||
by Ctrl-R will usually preserve user changes because only the document
|
||||
defines them (radio buttons, input boxes). But a full reload (Ctrl-Shift-R)
|
||||
will lose the user's choices that were not saved to the server. In any case
|
||||
the shared states are not retrieved by a full reload, the user has to click
|
||||
on "Get Updates" to retrieve them. When changing a selection, the line's
|
||||
background changes to match a similar color tone, allowing to visually
|
||||
spot preselected patches.
|
||||
|
||||
- fifth column: reason for the choice. The scripts try to provide an
|
||||
explanation for the choice of the preselection, and try to always end with
|
||||
|
|
@ -337,6 +429,52 @@ Using the HTML output is a bit rustic but efficient. The interface is split in
|
|||
backport to, etc. Elements that look like issues numbers and commit IDs are
|
||||
turned to links to ease navigation.
|
||||
|
||||
When the shared review persistence is deployed, two buttons also appear at the
|
||||
top right of the page:
|
||||
|
||||
- "Get updates" retrieves the current shared state from the server. Nothing
|
||||
is ever fetched automatically, not even when the page loads: it's up to
|
||||
the user to click when they want to synchronize. Lines the user has not
|
||||
touched are updated to reflect the shared verdicts; lines the user has
|
||||
already changed locally keep their local value (which will overwrite the
|
||||
shared one on the next save, this is intentional: last opinion wins,
|
||||
ideally with a note explaining why). Shared notes appear in italics below
|
||||
the AI explanation.
|
||||
|
||||
- "Save changes" pushes the local edits to the server: every verdict that
|
||||
differs from the last known shared state, plus the pending notes. It is
|
||||
grayed out whenever there is nothing to save, so a lit button means
|
||||
unsaved local edits (e.g. right after a reload restoring them). After a
|
||||
successful save the page is in sync; if the server is busy or
|
||||
unreachable, the edits simply stay local and a later click retries them.
|
||||
|
||||
Notes are edited via the small links below each explanation:
|
||||
|
||||
- "[add note]" opens an input box whose text will be appended to the
|
||||
commit's shared notes (up to 500 characters per addition). Additions
|
||||
accumulate and cannot conflict, so this is the preferred way to comment.
|
||||
|
||||
- "[edit note]" appears once a commit has shared notes: it presents the
|
||||
whole note in the input box for edition, and saving replaces the note
|
||||
(emptying the box deletes it). Clicking it while an addition is being
|
||||
typed merges both so nothing is lost. Since a replacement could destroy
|
||||
a concurrent update, it is only accepted by the server if the note did
|
||||
not change in between: otherwise the box turns red and stays in edition,
|
||||
and "Get updates" rebases it on the current note so it can be revised
|
||||
(against the refreshed note shown above it) and saved again.
|
||||
|
||||
- "[cancel]" closes the box without sending anything.
|
||||
|
||||
An open box only disappears once its content is synchronized with the
|
||||
server: a successful save, an update proving it redundant (e.g. the same
|
||||
text already pushed from another tab), or an explicit cancel. Boxes
|
||||
opened by mistake and left unmodified are silently closed by the next
|
||||
"Get updates".
|
||||
|
||||
Note that control characters (0x00-0x1F, 0x7F) are automatically removed from
|
||||
notes during updates, except for line feed (0x0A) which is replaced with a
|
||||
space (0x20).
|
||||
|
||||
In addition, in order to improve readability, the top of the table shows 4
|
||||
buttons allowing to show/hide each category. For example, when trying to focus
|
||||
only on "uncertain" and "wait", it can make sense to hide "N" and "Y" and click
|
||||
|
|
|
|||
834
dev/patchbot/cgi/update.awk
Executable file
834
dev/patchbot/cgi/update.awk
Executable file
|
|
@ -0,0 +1,834 @@
|
|||
#!/usr/bin/gawk -bf
|
||||
#
|
||||
# update.awk - storage backend for the patchbot backport review page
|
||||
#
|
||||
# Stores the human review edits (verdict overrides and notes) made on the
|
||||
# patchbot HTML page into a per-branch file kept in a dedicated git
|
||||
# repository, so that they are durable and shared between reviewers.
|
||||
#
|
||||
# This script is exec'd by a tiny "update.cgi" shell wrapper which is the
|
||||
# only web-exposed piece and holds the deployment-specific configuration:
|
||||
#
|
||||
# #!/bin/sh
|
||||
# exec /path/to/update.awk -r /path/to/repo
|
||||
#
|
||||
# The wrapper lives next to the generated HTML pages (thttpd must have the
|
||||
# "**.cgi" pattern enabled so that it is executed, not served). This script,
|
||||
# the repository and its .git must all stay OUTSIDE the HTTP document root.
|
||||
# The repository is a plain git working tree with a configured committer
|
||||
# identity, containing one file per major branch (e.g. "3.5") with one line
|
||||
# per touched commit:
|
||||
#
|
||||
# <commit_id> [state <n|u|w|y>] [notes "<escaped text>"]
|
||||
#
|
||||
# Commit ids are lowercase hex of any length; matching is symmetric-prefix
|
||||
# (two ids designate the same commit iff one is a prefix of the other) and
|
||||
# stops on the first match. Notes are double-quoted with '\' escaping '"'
|
||||
# and '\'; no stored line may ever contain a newline. Malformed fields or
|
||||
# lines are silently ignored, never fatal, and lines that are not being
|
||||
# modified are preserved byte-for-byte (admin hand-edits are legal).
|
||||
#
|
||||
# Requests (regular CGI environment):
|
||||
# - POST update.cgi?branch=3.5 with a line-oriented body:
|
||||
# <cid> state <n|u|w|y|revert>
|
||||
# <cid> notes <text to append>
|
||||
# <cid> setnotes <hash> <replacement text>
|
||||
# "state" overrides the verdict, "revert" (aliases "same", "unchanged")
|
||||
# removes the override so the bot's verdict applies again, "notes"
|
||||
# appends to the commit's notes (capped to 500 chars per push). Broken
|
||||
# directives are dropped, the survivors are applied under the lock and
|
||||
# the result is committed to git. Neither directive carries a base/old
|
||||
# value: state is last-write-wins and notes are append-only, which is
|
||||
# what keeps concurrent edits conflict-free.
|
||||
# "setnotes" replaces the whole note blob (or deletes it when the text
|
||||
# is empty) and is the exception: <hash> is the SDBM hash (8 hex
|
||||
# chars) of the blob the client based its edit on, and the directive is
|
||||
# only applied if it still matches the stored blob. Otherwise it is
|
||||
# dropped and reported as a "conflict <cid>" line in the response, so
|
||||
# that a replacement can never silently destroy a concurrent update.
|
||||
# - GET update.cgi?branch=3.5 returns the current overlay as a JSON array
|
||||
# of {"cid": ..., "state": ..., "notes": ...} objects, with absent
|
||||
# fields omitted and notes fully unescaped (an empty overlay yields
|
||||
# "[]"), directly usable with JSON.parse() on the client.
|
||||
#
|
||||
# Requires GNU awk (PROCINFO, systime); the -b flag in the shebang makes all
|
||||
# string operations byte-based regardless of the locale, which the escaping,
|
||||
# the caps and the hash depend on. A few points deserve attention:
|
||||
# - external commands (git, mkdir, mv, kill) go through /bin/sh, so
|
||||
# everything interpolated into a command is shell-quoted with q();
|
||||
# - NUL bytes in inputs are not reliably preserved by awk; they can only
|
||||
# occur in malformed requests, which are tolerated, not honoured;
|
||||
# - writing through a redirection whose target cannot be opened is a
|
||||
# fatal error in awk, terminating us without even a response, so the
|
||||
# writes into the (stealable) lock dir are arranged to be immune: the
|
||||
# pid goes through the shell and the temp file is opened the instant
|
||||
# the lock is acquired, its descriptor surviving a later theft.
|
||||
#
|
||||
# The script always exits zero once a response has been emitted, including
|
||||
# its own error responses, while a fatal awk error exits non-zero without
|
||||
# any output: a supervising wrapper can thus safely map any non-zero
|
||||
# termination to a generic error response.
|
||||
#
|
||||
# Fully testable from a shell without any HTTP server:
|
||||
#
|
||||
# printf '%s\n' 'deadbeef1234 state y' 'deadbeef1234 notes checked' > body
|
||||
# REQUEST_METHOD=POST QUERY_STRING=branch=3.5 \
|
||||
# CONTENT_LENGTH=$(stat -c %s body) ./update.awk -r /path/to/repo < body
|
||||
|
||||
BEGIN {
|
||||
MAX_CID_LEN = 40 # bound on a commit id (full SHA-1)
|
||||
MAX_NOTE_LEN = 500 # cap on a single pushed note addition
|
||||
MAX_EDIT_LEN = 4000 # cap on a whole-blob replacement (setnotes)
|
||||
MAX_BRANCH_LEN = 15 # bound on the branch name
|
||||
MAX_BODY_LEN = 1048576 # bound on a POST body
|
||||
NOTE_SEP = "; " # separator between coalesced notes
|
||||
LOCK_RETRIES = 100 # lock attempts before reporting busy
|
||||
LOCK_SLEEP = 0.05 # sleep between two attempts (~5s total)
|
||||
LOCK_STALE_AGE = 60 # age backstop when the pid file is unusable
|
||||
|
||||
# byte value of every possible character, for escaping decisions
|
||||
for (i = 0; i < 256; i++)
|
||||
ORD[sprintf("%c", i)] = i
|
||||
|
||||
# Arguments: -r <repo>. Note that when invoked through the shebang,
|
||||
# gawk itself consumes the leading "-r" (its --re-interval flag, a
|
||||
# no-op nowadays), and the repository path then reaches us as the
|
||||
# first bare operand: accept both forms.
|
||||
repo = ""
|
||||
for (i = 1; i < ARGC; i++) {
|
||||
if (ARGV[i] == "-r" && i + 1 < ARGC) {
|
||||
repo = ARGV[i + 1]
|
||||
ARGV[i] = ARGV[i + 1] = ""
|
||||
i++
|
||||
}
|
||||
else if (ARGV[i] != "" && repo == "") {
|
||||
repo = ARGV[i]
|
||||
ARGV[i] = ""
|
||||
}
|
||||
else if (ARGV[i] != "")
|
||||
die("500 Internal Server Error", \
|
||||
"server misconfigured (usage: update.awk -r /path/to/repo)")
|
||||
}
|
||||
|
||||
if (repo == "" || system("test -d " q(repo)) != 0)
|
||||
die("500 Internal Server Error", "server misconfigured")
|
||||
|
||||
lock_path = repo "/lock"
|
||||
lock_pid = lock_path "/pid"
|
||||
lock_tmp = lock_path "/tmp"
|
||||
|
||||
branch = get_branch()
|
||||
|
||||
if (ENVIRON["REQUEST_METHOD"] == "POST")
|
||||
handle_post()
|
||||
else if (ENVIRON["REQUEST_METHOD"] == "GET")
|
||||
handle_get()
|
||||
else
|
||||
die("405 Method Not Allowed", "unsupported method")
|
||||
exit 0
|
||||
}
|
||||
|
||||
# shell-quotes <s> so it can be safely interpolated into a command line:
|
||||
# every external command goes through /bin/sh, this is the only protection.
|
||||
function q(s)
|
||||
{
|
||||
gsub(/'/, "'\\\\''", s)
|
||||
return "'" s "'"
|
||||
}
|
||||
|
||||
# Prints a complete CGI error response and exits, releasing the lock if it
|
||||
# was held. Nothing is ever written to stderr, here nor anywhere else:
|
||||
# thttpd forwards the CGI's stderr to the client *before* its stdout, so
|
||||
# anything written there would land ahead of the response headers and
|
||||
# corrupt them; every diagnostic must be carried by the response itself.
|
||||
function die(status, msg)
|
||||
{
|
||||
if (lock_held)
|
||||
lock_release()
|
||||
printf "Status: %s\r\nContent-Type: text/plain\r\n\r\n%s\n", status, msg
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Extracts and validates the "branch" parameter from QUERY_STRING (used for
|
||||
# both GET and POST). The strict digits-dot-digits pattern is the path
|
||||
# traversal guard: the branch is the only request-controlled component of
|
||||
# the storage file path and nothing else may ever reach the path building.
|
||||
function get_branch( n, i, p, v)
|
||||
{
|
||||
n = split(ENVIRON["QUERY_STRING"], p, "&")
|
||||
v = ""
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (substr(p[i], 1, 7) == "branch=") {
|
||||
v = substr(p[i], 8)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (v == "" || length(v) > MAX_BRANCH_LEN || v !~ /^[0-9]+\.[0-9]+$/)
|
||||
die("400 Bad Request", "missing or invalid branch")
|
||||
return v
|
||||
}
|
||||
|
||||
# SDBM hash of <s> (h = c + h * 65599) as 8 hex chars, the concurrency token
|
||||
# carried by a note blob replacement; must match the page's JS version. The
|
||||
# small multiplier keeps the 32-bit state exactly representable with awk's
|
||||
# double-precision numbers (65599 * 2^32 stays well below 2^53).
|
||||
function sdbm_hex(s, h, i, n)
|
||||
{
|
||||
h = 0
|
||||
n = length(s)
|
||||
for (i = 1; i <= n; i++)
|
||||
h = (ORD[substr(s, i, 1)] + h * 65599) % 4294967296
|
||||
return sprintf("%08x", h)
|
||||
}
|
||||
|
||||
# Symmetric-prefix commit id match: two ids designate the same commit iff
|
||||
# one is a prefix of the other. The caller scans in file order and stops on
|
||||
# the first match; providing enough digits to stay unambiguous is the
|
||||
# writer's responsibility (12 recommended). A too-short collision merely
|
||||
# lands on the wrong line and is admin-fixable by editing the file.
|
||||
function cid_match(a, b)
|
||||
{
|
||||
return index(a, b) == 1 || index(b, a) == 1
|
||||
}
|
||||
|
||||
# returns the leading commit id of a storage line (lowercase hex followed by
|
||||
# a blank or the end of line), or "" if none parses
|
||||
function line_cid(line, c, nxt)
|
||||
{
|
||||
sub(/^[ \t]+/, "", line)
|
||||
if (!match(line, /^[0-9a-f]+/))
|
||||
return ""
|
||||
c = substr(line, 1, RLENGTH)
|
||||
nxt = substr(line, RLENGTH + 1, 1)
|
||||
if (length(c) > MAX_CID_LEN || (nxt != "" && nxt != " " && nxt != "\t"))
|
||||
return ""
|
||||
return c
|
||||
}
|
||||
|
||||
# Parses storage line <line> into P_cid/P_state/P_notes/P_has_notes. Returns
|
||||
# 1 if a valid commit id was found (the entry is usable), 0 otherwise. Any
|
||||
# broken or unknown field is silently dropped, never fatal, so that one bad
|
||||
# hand-edit cannot break the whole file and future format additions don't
|
||||
# trip older code.
|
||||
function parse_line(line, p, v, nxt, out, i, n, c, closed)
|
||||
{
|
||||
P_cid = ""; P_state = ""; P_notes = ""; P_has_notes = 0
|
||||
|
||||
P_cid = line_cid(line)
|
||||
if (P_cid == "")
|
||||
return 0
|
||||
sub(/^[ \t]+/, "", line)
|
||||
p = substr(line, length(P_cid) + 1)
|
||||
|
||||
while (p != "") {
|
||||
sub(/^[ \t]+/, "", p)
|
||||
if (p == "")
|
||||
break
|
||||
|
||||
if (match(p, /^state[ \t]+/)) {
|
||||
v = substr(p, RLENGTH + 1, 1)
|
||||
nxt = substr(p, RLENGTH + 2, 1)
|
||||
if (v ~ /^[nuwy]$/ && (nxt == "" || nxt == " " || nxt == "\t")) {
|
||||
P_state = v
|
||||
p = substr(p, RLENGTH + 2)
|
||||
continue
|
||||
}
|
||||
# unknown state value: drop the field
|
||||
}
|
||||
else if (match(p, /^notes[ \t]+"/)) {
|
||||
out = ""; closed = 0
|
||||
i = RLENGTH + 1
|
||||
n = length(p)
|
||||
while (i <= n) {
|
||||
c = substr(p, i, 1)
|
||||
if (c == "\"") {
|
||||
closed = 1
|
||||
i++
|
||||
break
|
||||
}
|
||||
if (c == "\\" && i < n) {
|
||||
i++
|
||||
c = substr(p, i, 1)
|
||||
}
|
||||
i++
|
||||
if (c == "\r")
|
||||
continue
|
||||
if (ORD[c] < 32 || ORD[c] == 127)
|
||||
c = " "
|
||||
out = out c
|
||||
}
|
||||
if (closed) {
|
||||
P_notes = out
|
||||
P_has_notes = 1
|
||||
p = substr(p, i)
|
||||
continue
|
||||
}
|
||||
# unterminated quote: drop the field and what follows,
|
||||
# it cannot be delimited
|
||||
break
|
||||
}
|
||||
# unknown or broken field: skip one token and try again
|
||||
sub(/^[^ \t]+/, "", p)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
# formats an entry back into a storage line. Notes are quoted with '\'
|
||||
# escaping '"' and '\'; as a hard invariant, no control char (and especially
|
||||
# no newline) may ever be emitted inside a line, or the one-line-per-commit
|
||||
# format breaks, so anything unexpected is defensively turned into a space.
|
||||
function fmt_entry(cid, state, notes, has_notes, line, out, i, n, c)
|
||||
{
|
||||
line = cid
|
||||
if (state != "")
|
||||
line = line " state " state
|
||||
if (has_notes) {
|
||||
out = ""
|
||||
n = length(notes)
|
||||
for (i = 1; i <= n; i++) {
|
||||
c = substr(notes, i, 1)
|
||||
if (c == "\r")
|
||||
continue
|
||||
if (c == "\"" || c == "\\")
|
||||
out = out "\\" c
|
||||
else if (ORD[c] < 32 || ORD[c] == 127)
|
||||
out = out " "
|
||||
else
|
||||
out = out c
|
||||
}
|
||||
line = line " notes \"" out "\""
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
# Sanitises a pushed note: CR is dropped, any other control char becomes a
|
||||
# space (nothing may ever introduce a newline into a stored line), then the
|
||||
# text is trimmed and capped to <cap> bytes on a UTF-8 character boundary.
|
||||
function sanitize_note(s, cap, b)
|
||||
{
|
||||
gsub(/\r/, "", s)
|
||||
gsub(/[\x01-\x1f\x7f]/, " ", s)
|
||||
sub(/^ +/, "", s)
|
||||
sub(/ +$/, "", s)
|
||||
if (length(s) > cap) {
|
||||
# never cut in the middle of a UTF-8 sequence: back off while
|
||||
# the first dropped byte is a continuation byte (0x80-0xBF)
|
||||
b = ORD[substr(s, cap + 1, 1)]
|
||||
while (cap > 0 && b >= 128 && b < 192) {
|
||||
cap--
|
||||
b = ORD[substr(s, cap + 1, 1)]
|
||||
}
|
||||
s = substr(s, 1, cap)
|
||||
sub(/ +$/, "", s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
# reads the POST body from stdin according to CONTENT_LENGTH
|
||||
function read_body( cl, body, line, got)
|
||||
{
|
||||
if (ENVIRON["CONTENT_LENGTH"] !~ /^[0-9]+$/ || \
|
||||
ENVIRON["CONTENT_LENGTH"] + 0 > MAX_BODY_LEN)
|
||||
die("400 Bad Request", "missing or invalid content length")
|
||||
cl = ENVIRON["CONTENT_LENGTH"] + 0
|
||||
|
||||
body = ""; got = 0
|
||||
while (got < cl && (getline line < "/dev/stdin") > 0) {
|
||||
got += length(line) + length(RT)
|
||||
body = body line "\n"
|
||||
}
|
||||
if (got < cl)
|
||||
die("400 Bad Request", "truncated body")
|
||||
return body
|
||||
}
|
||||
|
||||
# Parses the POST body into the d_* directive arrays. Broken directives are
|
||||
# dropped, never fatal: a non-hex or over-long cid, an unknown verb or state
|
||||
# value, or an empty note simply skip that line, and the survivors are still
|
||||
# applied. Returns the number of valid directives.
|
||||
function parse_directives(body, nb, n, i, line, cid, rest, v, txt, h)
|
||||
{
|
||||
nb = 0
|
||||
n = split(body, BL, "\n")
|
||||
for (i = 1; i <= n; i++) {
|
||||
line = BL[i]
|
||||
sub(/\r$/, "", line)
|
||||
sub(/^[ \t]+/, "", line)
|
||||
|
||||
# the commit id is stored verbatim as sent by the client
|
||||
# (whatever length the page carries), only lowercased. The
|
||||
# length bound is the only enforcement.
|
||||
if (!match(line, /^[0-9a-fA-F]+[ \t]/))
|
||||
continue
|
||||
cid = tolower(substr(line, 1, RLENGTH - 1))
|
||||
if (length(cid) > MAX_CID_LEN)
|
||||
continue
|
||||
rest = substr(line, RLENGTH + 1)
|
||||
sub(/^[ \t]+/, "", rest)
|
||||
|
||||
if (match(rest, /^state[ \t]+/)) {
|
||||
v = substr(rest, RLENGTH + 1)
|
||||
sub(/[ \t]+$/, "", v)
|
||||
if (v ~ /^[nuwy]$/) {
|
||||
nb++
|
||||
d_type[nb] = "state"; d_cid[nb] = cid; d_state[nb] = v
|
||||
}
|
||||
else if (v ~ /^(revert|same|unchanged)$/) {
|
||||
nb++
|
||||
d_type[nb] = "revert"; d_cid[nb] = cid
|
||||
}
|
||||
# else: unknown value or trailing junk, drop
|
||||
}
|
||||
else if (match(rest, /^notes[ \t]/)) {
|
||||
txt = sanitize_note(substr(rest, RLENGTH + 1), MAX_NOTE_LEN)
|
||||
if (txt == "")
|
||||
continue
|
||||
nb++
|
||||
d_type[nb] = "notes"; d_cid[nb] = cid; d_note[nb] = txt
|
||||
}
|
||||
else if (match(rest, /^setnotes[ \t]+/)) {
|
||||
v = substr(rest, RLENGTH + 1)
|
||||
if (!match(v, /^[0-9a-fA-F]{8}([ \t]|$)/))
|
||||
continue
|
||||
h = tolower(substr(v, 1, 8))
|
||||
txt = substr(v, 9)
|
||||
sub(/^[ \t]+/, "", txt)
|
||||
# an empty replacement is valid: it deletes the notes
|
||||
nb++
|
||||
d_type[nb] = "setnotes"; d_cid[nb] = cid
|
||||
d_hash[nb] = h
|
||||
d_note[nb] = sanitize_note(txt, MAX_EDIT_LEN)
|
||||
}
|
||||
}
|
||||
return nb
|
||||
}
|
||||
|
||||
# loads the branch file into the L_* line arrays; a missing file is an empty
|
||||
# one (first write will create it). Lines are kept verbatim; only the
|
||||
# leading commit id is parsed here, for matching.
|
||||
function load_file(fname, line)
|
||||
{
|
||||
nb_lines = 0
|
||||
while ((getline line < fname) > 0) {
|
||||
nb_lines++
|
||||
L_raw[nb_lines] = line
|
||||
L_cid[nb_lines] = line_cid(line)
|
||||
L_touched[nb_lines] = 0
|
||||
}
|
||||
close(fname)
|
||||
}
|
||||
|
||||
# Applies directive <di>: the target line is looked up by prefix-match,
|
||||
# first match wins, scanning the file lines then the new entries; a miss
|
||||
# creates a new entry (except for a revert, which then has nothing to
|
||||
# remove). A line reduced to neither state nor notes is dropped at write
|
||||
# time. Returns 0 on success, or 1 when a setnotes base hash doesn't match
|
||||
# the stored blob anymore: the directive is then not applied (a replacement
|
||||
# must never silently destroy a concurrent update) and the caller reports
|
||||
# the conflict.
|
||||
function apply_directive(di, i, li, ni, was_touched, cur)
|
||||
{
|
||||
li = 0; ni = 0; was_touched = 0
|
||||
for (i = 1; i <= nb_lines; i++) {
|
||||
if (L_cid[i] == "" || !cid_match(L_cid[i], d_cid[di]))
|
||||
continue
|
||||
li = i
|
||||
was_touched = L_touched[i]
|
||||
if (!L_touched[i]) {
|
||||
parse_line(L_raw[i])
|
||||
L_state[i] = P_state
|
||||
L_notes[i] = P_notes
|
||||
L_has[i] = P_has_notes
|
||||
L_touched[i] = 1
|
||||
}
|
||||
break
|
||||
}
|
||||
if (!li) {
|
||||
for (i = 1; i <= nb_new; i++) {
|
||||
if (cid_match(N_cid[i], d_cid[di])) {
|
||||
ni = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# The base check happens before any entry creation or modification.
|
||||
# On conflict the line must be left exactly as found, including not
|
||||
# marked as modified if this lookup was what materialised it.
|
||||
if (d_type[di] == "setnotes") {
|
||||
cur = ""
|
||||
if (li && L_has[li])
|
||||
cur = L_notes[li]
|
||||
else if (ni && N_has[ni])
|
||||
cur = N_notes[ni]
|
||||
if (sdbm_hex(cur) != d_hash[di]) {
|
||||
if (li && !was_touched)
|
||||
L_touched[li] = 0
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
if (!li && !ni) {
|
||||
if (d_type[di] == "revert")
|
||||
return 0 # nothing stored for this commit anyway
|
||||
if (d_type[di] == "setnotes" && d_note[di] == "")
|
||||
return 0 # deleting non-existing notes
|
||||
nb_new++
|
||||
N_cid[nb_new] = d_cid[di]
|
||||
N_state[nb_new] = ""; N_notes[nb_new] = ""; N_has[nb_new] = 0
|
||||
ni = nb_new
|
||||
}
|
||||
|
||||
if (d_type[di] == "state") {
|
||||
if (li) L_state[li] = d_state[di]; else N_state[ni] = d_state[di]
|
||||
}
|
||||
else if (d_type[di] == "revert") {
|
||||
if (li) L_state[li] = ""; else N_state[ni] = ""
|
||||
}
|
||||
else if (d_type[di] == "notes") {
|
||||
if (li) {
|
||||
L_notes[li] = L_has[li] ? L_notes[li] NOTE_SEP d_note[di] : d_note[di]
|
||||
L_has[li] = 1
|
||||
}
|
||||
else {
|
||||
N_notes[ni] = N_has[ni] ? N_notes[ni] NOTE_SEP d_note[di] : d_note[di]
|
||||
N_has[ni] = 1
|
||||
}
|
||||
}
|
||||
else if (d_type[di] == "setnotes") {
|
||||
if (li) {
|
||||
L_notes[li] = d_note[di]
|
||||
L_has[li] = (d_note[di] != "")
|
||||
}
|
||||
else {
|
||||
N_notes[ni] = d_note[di]
|
||||
N_has[ni] = (d_note[di] != "")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
# Serialises all writers around the branch files. The lock is a directory
|
||||
# (mkdir is atomic) at an obvious fixed place, <repo>/lock, which also hosts
|
||||
# the temp file so that the final rename stays on one filesystem. The
|
||||
# holder's PID is stored inside; a dead holder is the real staleness signal
|
||||
# (a live but slow one, e.g. during git gc, must never be evicted
|
||||
# mid-commit), with a loose age backstop only for when no PID can be read.
|
||||
#
|
||||
# NOTE: PID-based takeover is a valid liveness signal only because all
|
||||
# writers are local children of the same host (thttpd CGI processes). If
|
||||
# another writer path is ever added (cron job, over-SSH update, push step
|
||||
# touching this repo), the liveness check stops meaning "the holder is
|
||||
# alive" and this takeover silently stops protecting the file.
|
||||
#
|
||||
# Returns 0 on success, -1 when the lock could not be obtained (busy).
|
||||
function lock_acquire( i, pid, stale, mt, priv, cmd, p2)
|
||||
{
|
||||
for (i = 0; i < LOCK_RETRIES; i++) {
|
||||
if (system("mkdir " q(lock_path) " 2>/dev/null") == 0) {
|
||||
# The pid is written via the shell: a takeover based on
|
||||
# a stale decision may steal this fresh lock before the
|
||||
# pid lands, and a plain print into the vanished dir
|
||||
# would be a fatal awk error killing us without even a
|
||||
# response, while a command failure is just a lost
|
||||
# acquisition to retry.
|
||||
if (system("echo " PROCINFO["pid"] " > " q(lock_pid) " 2>/dev/null") != 0)
|
||||
continue
|
||||
lock_held = 1
|
||||
return 0
|
||||
}
|
||||
|
||||
# The lock is held: check whether the holder is still alive.
|
||||
# All writers run under the same UID, so failing to signal it,
|
||||
# even with EPERM, means it is dead and its pid was recycled
|
||||
# by a foreign process; a wrongful eviction would anyway be
|
||||
# absorbed by the takeover verification and the victim's
|
||||
# retry. The pid file must be closed even when
|
||||
# the read fails (e.g. caught empty before the holder flushed
|
||||
# it): gawk keeps input files open and cached by path, and a
|
||||
# cached descriptor would keep returning the content of a
|
||||
# previous lock's deleted pid file, making a live holder look
|
||||
# dead and letting its lock be stolen in the middle of a write.
|
||||
pid = ""; stale = 0
|
||||
getline pid < lock_pid
|
||||
close(lock_pid)
|
||||
if (pid "" == PROCINFO["pid"] "")
|
||||
stale = 1 # our own lock, orphaned by a foiled takeover
|
||||
else if (pid ~ /^[0-9]+$/ && pid + 0 > 0)
|
||||
stale = (system("kill -0 " pid " 2>/dev/null") != 0)
|
||||
else {
|
||||
cmd = "stat -c %Y " q(lock_path) " 2>/dev/null"
|
||||
mt = ""
|
||||
cmd | getline mt
|
||||
close(cmd)
|
||||
stale = (mt ~ /^[0-9]+$/ && systime() - mt > LOCK_STALE_AGE)
|
||||
}
|
||||
|
||||
if (stale) {
|
||||
# Atomic takeover: rename() has exactly one winner
|
||||
# (mv -T refuses an existing target), which owns the
|
||||
# recovery and discards the stale dir under its
|
||||
# private name; a loser re-enters acquisition. Never
|
||||
# rmdir-then-mkdir, that would race two adopters.
|
||||
#
|
||||
# The rename is atomic but the staleness decision was
|
||||
# not: between reading the dead holder's pid and the
|
||||
# rename, the lock may have been released and
|
||||
# re-acquired by a live writer, in which case we just
|
||||
# stole a live lock. So verify: only discard the
|
||||
# stolen dir if it still carries the pid we judged
|
||||
# dead, otherwise put it back untouched (its temp file
|
||||
# is still inside, the victim never notices anything).
|
||||
priv = repo "/lock.stale." PROCINFO["pid"] "." i
|
||||
if (system("mv -T " q(lock_path) " " q(priv) " 2>/dev/null") == 0) {
|
||||
p2 = ""
|
||||
getline p2 < (priv "/pid")
|
||||
close(priv "/pid")
|
||||
if (p2 "" == pid "")
|
||||
system("rm -f " q(priv "/pid") " " q(priv "/tmp") \
|
||||
"; rmdir " q(priv) " 2>/dev/null")
|
||||
else
|
||||
# the give-back may fail if the path was
|
||||
# re-created in between; the private dir is
|
||||
# then left over for the admin, it cannot
|
||||
# be restored safely
|
||||
system("mv -T " q(priv) " " q(lock_path) " 2>/dev/null")
|
||||
}
|
||||
continue
|
||||
}
|
||||
system("sleep " LOCK_SLEEP)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
# Runs "git -C <repo> <args>". Both its stdout and stderr are captured (into
|
||||
# GITMSG, up to 255 bytes, control chars turned into spaces), so that git
|
||||
# can neither corrupt the CGI response nor leak into a server which sends
|
||||
# the CGI's stderr to the client, and above all so that the exact git error
|
||||
# can be reported to the user. Since the command goes through /bin/sh, an
|
||||
# unfindable git yields status 127 and the shell's own message, reworded to
|
||||
# directly point at the typical PATH issue.
|
||||
function run_git(args, cmd, line, out, st)
|
||||
{
|
||||
cmd = "git -C " q(repo) " " args " 2>&1"
|
||||
out = ""
|
||||
while ((cmd | getline line) > 0)
|
||||
out = out (out == "" ? "" : " ") line
|
||||
st = close(cmd)
|
||||
gsub(/[\x01-\x1f\x7f]/, " ", out)
|
||||
if (st == 127)
|
||||
out = "cannot execute git: " out
|
||||
GITMSG = substr(out, 1, 255)
|
||||
sub(/ +$/, "", GITMSG)
|
||||
return st
|
||||
}
|
||||
|
||||
# Releases the lock, but only after checking that it is still ours: after a
|
||||
# takeover interleaving gone wrong, the path may carry someone else's live
|
||||
# lock, which must not be dismantled; ours is then a private stale dir that
|
||||
# the next writers will reclaim. Also called from die().
|
||||
function lock_release( p)
|
||||
{
|
||||
p = ""
|
||||
getline p < lock_pid
|
||||
close(lock_pid)
|
||||
if (p "" == PROCINFO["pid"] "")
|
||||
system("rm -f " q(lock_pid) " " q(lock_tmp) "; rmdir " q(lock_path) " 2>/dev/null")
|
||||
lock_held = 0
|
||||
}
|
||||
|
||||
# The GET handler: returns the current overlay for <branch> as a JSON array
|
||||
# of {"cid","state","notes"} objects with absent fields omitted; a missing
|
||||
# or empty file yields "[]". The raw storage format never travels: notes
|
||||
# are unescaped by the parser and JSON-escaped here, so the client can
|
||||
# JSON.parse() the result and insert notes via textContent directly.
|
||||
# Unparseable content is silently skipped. Reads are lockless: the atomic
|
||||
# rename on the write side guarantees the file is always a complete valid
|
||||
# version.
|
||||
function handle_get( i, first, out)
|
||||
{
|
||||
load_file(repo "/" branch)
|
||||
|
||||
printf "Content-Type: application/json\r\nCache-Control: no-store\r\n\r\n"
|
||||
out = "["
|
||||
first = 1
|
||||
for (i = 1; i <= nb_lines; i++) {
|
||||
if (L_cid[i] == "" || !parse_line(L_raw[i]))
|
||||
continue
|
||||
if (P_state == "" && !P_has_notes)
|
||||
continue # nothing stored for this commit
|
||||
if (!first)
|
||||
out = out ","
|
||||
first = 0
|
||||
out = out "\n{\"cid\":" json_str(P_cid)
|
||||
if (P_state != "")
|
||||
out = out ",\"state\":\"" P_state "\""
|
||||
if (P_has_notes)
|
||||
out = out ",\"notes\":" json_str(P_notes)
|
||||
out = out "}"
|
||||
}
|
||||
printf "%s%s]\n", out, first ? "" : "\n"
|
||||
}
|
||||
|
||||
# emits <s> as a JSON string; control chars are defensively encoded and
|
||||
# UTF-8 sequences pass through verbatim
|
||||
function json_str(s, out, i, n, c)
|
||||
{
|
||||
out = "\""
|
||||
n = length(s)
|
||||
for (i = 1; i <= n; i++) {
|
||||
c = substr(s, i, 1)
|
||||
if (c == "\"" || c == "\\")
|
||||
out = out "\\" c
|
||||
else if (ORD[c] < 32)
|
||||
out = out sprintf("\\u%04x", ORD[c])
|
||||
else
|
||||
out = out c
|
||||
}
|
||||
return out "\""
|
||||
}
|
||||
|
||||
# the POST handler: parse directives, and if any survives, apply them to the
|
||||
# branch file under the lock, atomically replace it and commit it to git.
|
||||
function handle_post( body, i, j, fname, nb_confl, nb_done, msg, git_failed, attempt, renamed)
|
||||
{
|
||||
body = read_body()
|
||||
nb_dirs = parse_directives(body)
|
||||
if (nb_dirs == 0) {
|
||||
# nothing valid remains: complete no-op, no lock taken
|
||||
printf "Content-Type: text/plain\r\n\r\nOK 0 directives applied\n"
|
||||
return
|
||||
}
|
||||
|
||||
# The whole locked cycle may have to be redone: if our lock (and the
|
||||
# temp file inside it) is stolen by a takeover which mistook us for
|
||||
# dead, the final rename fails while nothing was applied to the file
|
||||
# yet, so it is always safe to start over from a fresh read.
|
||||
fname = repo "/" branch
|
||||
renamed = 0
|
||||
for (attempt = 0; attempt < 5 && !renamed; attempt++) {
|
||||
if (lock_acquire() < 0)
|
||||
die("503 Service Unavailable", "busy, retry")
|
||||
|
||||
# Open the temp file right away: from here on its descriptor
|
||||
# keeps working even if the lock gets stolen (the final rename
|
||||
# will fail cleanly and be retried). Opening it later would
|
||||
# widen the window where a theft makes the redirection open
|
||||
# fail, which is a fatal error in awk.
|
||||
printf "" > lock_tmp
|
||||
|
||||
# the file may contain admin hand-edits, possibly not even committed
|
||||
# yet: read it as it is, preserve every line we're not touching, and
|
||||
# commit whatever ends up in the tree.
|
||||
delete L_raw; delete L_cid; delete L_touched
|
||||
delete L_state; delete L_notes; delete L_has
|
||||
delete N_cid; delete N_state; delete N_notes; delete N_has
|
||||
delete CONFL; delete DONE
|
||||
load_file(fname)
|
||||
|
||||
nb_new = 0; nb_confl = 0; nb_done = 0
|
||||
for (i = 1; i <= nb_dirs; i++) {
|
||||
if (apply_directive(i)) {
|
||||
nb_confl++
|
||||
CONFL[nb_confl] = d_cid[i]
|
||||
continue
|
||||
}
|
||||
# remember the touched commits for the git commit message
|
||||
for (j = 1; j <= nb_done; j++)
|
||||
if (DONE[j] == d_cid[i])
|
||||
break
|
||||
if (j > nb_done)
|
||||
DONE[++nb_done] = d_cid[i]
|
||||
}
|
||||
|
||||
git_failed = 0
|
||||
GITMSG = ""
|
||||
renamed = 1
|
||||
if (nb_confl < nb_dirs) {
|
||||
# Complete the temp file (opened right when the lock was
|
||||
# acquired: the open descriptor is immune to a lock theft, the
|
||||
# writes land in the renamed-away file and the rename below
|
||||
# then fails cleanly) and atomically rename() it over the
|
||||
# branch file, so that the latter is always a complete valid
|
||||
# file, even across a crash.
|
||||
for (i = 1; i <= nb_lines; i++) {
|
||||
if (!L_touched[i])
|
||||
print L_raw[i] > lock_tmp
|
||||
else if (L_state[i] != "" || L_has[i])
|
||||
print fmt_entry(L_cid[i], L_state[i], L_notes[i], L_has[i]) > lock_tmp
|
||||
# else: line reduced to nothing, dropped
|
||||
}
|
||||
for (i = 1; i <= nb_new; i++) {
|
||||
if (N_state[i] != "" || N_has[i])
|
||||
print fmt_entry(N_cid[i], N_state[i], N_notes[i], N_has[i]) > lock_tmp
|
||||
}
|
||||
close(lock_tmp)
|
||||
system("sync -d " q(lock_tmp) " 2>/dev/null")
|
||||
if (system("mv -T " q(lock_tmp) " " q(fname) " 2>/dev/null") != 0) {
|
||||
# our lock was stolen and the temp file went with it:
|
||||
# what now sits at the lock path belongs to someone
|
||||
# else, leave it alone and redo the whole cycle from a
|
||||
# fresh read
|
||||
lock_held = 0
|
||||
renamed = 0
|
||||
continue
|
||||
}
|
||||
|
||||
# The commit subject names the branch and the first touched
|
||||
# commit (plus how many others), and the body lists all of
|
||||
# them one per line, which helps a lot when hand-editing the
|
||||
# storage repository (e.g. to locate a change when rebasing).
|
||||
msg = "update " branch ": " DONE[1]
|
||||
if (nb_done > 1)
|
||||
msg = msg " + " (nb_done - 1) " more"
|
||||
msg = msg "\n"
|
||||
for (i = 1; i <= nb_done; i++)
|
||||
msg = msg "\n" DONE[i]
|
||||
|
||||
# Commit failures (e.g. missing committer identity) are not
|
||||
# fatal: the tree stays valid-but-uncommitted and the next
|
||||
# writer folds it into its own commit. But they must not stay
|
||||
# invisible either or the history silently stops being
|
||||
# recorded, so they are reported as a warning line in the
|
||||
# response. A no-op (identical content, e.g. re-pushed
|
||||
# identical states) is not a failure: the commit is simply
|
||||
# skipped when nothing is staged. Never checkout or reset
|
||||
# here, it would eat an admin's uncommitted hand-edit.
|
||||
if (run_git("add -- " q(branch)) != 0)
|
||||
git_failed = 1
|
||||
else if (run_git("diff --cached --quiet") != 0 && \
|
||||
run_git("commit -q -m " q(msg)) != 0)
|
||||
git_failed = 1
|
||||
}
|
||||
# else: everything conflicted, nothing changed, nothing to write
|
||||
|
||||
lock_release()
|
||||
}
|
||||
if (!renamed)
|
||||
die("500 Internal Server Error", "cannot replace branch file")
|
||||
|
||||
# echo the conflicts then the resulting line(s) after the status; the
|
||||
# client relies on the "conflict <cid>" lines, the rest is mostly for
|
||||
# debugging.
|
||||
printf "Content-Type: text/plain\r\n\r\n"
|
||||
printf "OK %d directive%s applied\n", nb_dirs - nb_confl, \
|
||||
nb_dirs - nb_confl == 1 ? "" : "s"
|
||||
for (i = 1; i <= nb_confl; i++)
|
||||
print "conflict " CONFL[i]
|
||||
if (git_failed)
|
||||
print "warning: git commit failed, history not recorded (" \
|
||||
(GITMSG != "" ? GITMSG : \
|
||||
"check the committer identity and permissions in the storage repository") ")"
|
||||
for (i = 1; i <= nb_lines; i++) {
|
||||
if (!L_touched[i])
|
||||
continue
|
||||
if (L_state[i] != "" || L_has[i])
|
||||
print fmt_entry(L_cid[i], L_state[i], L_notes[i], L_has[i])
|
||||
else
|
||||
print L_cid[i] " removed"
|
||||
}
|
||||
for (i = 1; i <= nb_new; i++) {
|
||||
if (N_state[i] != "" || N_has[i])
|
||||
print fmt_entry(N_cid[i], N_state[i], N_notes[i], N_has[i])
|
||||
}
|
||||
}
|
||||
41
dev/patchbot/cgi/update.cgi
Normal file
41
dev/patchbot/cgi/update.cgi
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/sh
|
||||
# Example deployment wrapper for the storage backend of the patchbot review
|
||||
# page. This wrapper is the only web-exposed piece: copy it next to the
|
||||
# generated HTML pages (the page reaches it with a bare relative URL),
|
||||
# adjust the paths below, and make sure the web server has the "**.cgi"
|
||||
# pattern enabled so that this file is executed, not served (or its content,
|
||||
# including the repository path, would leak).
|
||||
#
|
||||
# All deployment-specific settings belong here, as arguments: the backend
|
||||
# itself (update.bin or update.awk, both honour the same interface) and the
|
||||
# overlay git repository (with a configured committer identity) must both
|
||||
# stay outside the document root.
|
||||
#
|
||||
# The wrapper supervises the backend rather than exec'ing it, relying on a
|
||||
# simple contract: the backend always exits zero once it has emitted a
|
||||
# response (including its own error responses), so any other termination
|
||||
# means no response was produced (e.g. a fatal interpreter error) and a
|
||||
# generic error is emitted instead, so that the browser always receives a
|
||||
# response. The backend computes everything before emitting its response in
|
||||
# one final burst, so a death with partial output is not a realistic case
|
||||
# (and would anyway yield an unparsable response that the page treats as a
|
||||
# failed save with the edits kept). The backend's stderr is discarded
|
||||
# because the web server would send it to the client ahead of the response
|
||||
# headers and corrupt them; point it to a file instead of /dev/null when
|
||||
# debugging.
|
||||
|
||||
# The web server usually starts CGIs with a restricted compile-time PATH
|
||||
# (e.g. thttpd's CGI_PATH): make sure it contains git, or adjust it here,
|
||||
# otherwise nothing gets committed in the storage repository.
|
||||
PATH=/usr/local/bin:/usr/bin:/bin
|
||||
export PATH
|
||||
|
||||
# where the backend lives (update.awk or update.bin), and the storage repo
|
||||
SCRIPTS_DIR=/home/patchbot/prog/bin
|
||||
REPO_DIR=/home/patchbot/data/overlay
|
||||
|
||||
if ! "$SCRIPTS_DIR/update.awk" -r "$REPO_DIR" 2>/dev/null; then
|
||||
printf 'Status: 500 Internal Server Error\r\n'
|
||||
printf 'Content-Type: text/plain\r\n\r\n'
|
||||
printf 'backend error, nothing was saved\n'
|
||||
fi
|
||||
|
|
@ -24,20 +24,30 @@ quit() {
|
|||
|
||||
#### Main
|
||||
|
||||
USAGE="Usage: ${0##*/} [ -h ] [ -b 'bkp_list' ] patch..."
|
||||
USAGE="Usage: ${0##*/} [ -h ] [ -b 'bkp_list' ] [ -v version ] patch..."
|
||||
MYSELF="$0"
|
||||
GITURL="http://git.haproxy.org/?p=haproxy.git;a=commitdiff;h="
|
||||
ISSUES="https://github.com/haproxy/haproxy/issues/"
|
||||
BKP=""
|
||||
VERSION=""
|
||||
|
||||
while [ -n "$1" -a -z "${1##-*}" ]; do
|
||||
case "$1" in
|
||||
-h|--help) quit "$USAGE" ;;
|
||||
-b) BKP="$2"; shift 2 ;;
|
||||
-v) VERSION="$2"; shift 2 ;;
|
||||
*) die "$USAGE" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# VERSION is the branch this page covers (eg: 3.5). It is only used by the
|
||||
# in-page JS to sync the review state with the server-side update.cgi, which
|
||||
# strictly validates it, so let's check it here as well. When empty, the
|
||||
# syncing UI is not emitted at all and the page keeps working standalone.
|
||||
if [ -n "$VERSION" ] && ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
|
||||
die "Invalid version '$VERSION', expected <digits>.<digits>"
|
||||
fi
|
||||
|
||||
PATCHES=( "$@" )
|
||||
|
||||
if [ ${#PATCHES[@]} = 0 ]; then
|
||||
|
|
@ -131,14 +141,474 @@ input.y[type="radio"]:checked {
|
|||
border: 2px solid black;
|
||||
background-color: $BT_Y;
|
||||
}
|
||||
|
||||
/* shared reviewers' notes, shown below the AI explanation */
|
||||
div.notes {
|
||||
font-style: italic;
|
||||
margin-top: 2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
|
||||
var cgi_url = "cgi-bin/update.cgi";
|
||||
var nb_patches = 0;
|
||||
var cid = [];
|
||||
var bkp = [];
|
||||
|
||||
// the branch this page covers (eg: "3.5"), used to sync the review state
|
||||
// with the server-side update.cgi; empty when generated without -v, in
|
||||
// which case no syncing is possible and the page works standalone.
|
||||
var branch = '$VERSION';
|
||||
|
||||
// Three states exist per line. The original state (orig[]) is the verdict
|
||||
// the bot chose, captured at load time and constant. The reference state
|
||||
// (ref_state[]/ref_notes[]) is the last known shared state, i.e. what the
|
||||
// server last told us, on top of which the user's edits sit; it starts
|
||||
// equal to the original and is only advanced by "Get updates" and by a
|
||||
// successful save. The local state is the DOM itself (the checked radios),
|
||||
// there is no separate copy. Nothing is fetched automatically: the user
|
||||
// explicitly clicks "Get updates" to retrieve the shared state.
|
||||
var orig = [];
|
||||
var ref_state = [];
|
||||
var ref_notes = [];
|
||||
var cidmap = {};
|
||||
|
||||
// Note edition state per line: mode 0 = closed, 1 = appending (the input
|
||||
// holds text to add to the shared notes), 2 = editing (the input holds the
|
||||
// whole replacement blob, and note_base[] snapshots the reference it was
|
||||
// based on; its hash is sent with the replacement so the server can refuse
|
||||
// it if the blob changed concurrently). An open input only disappears once
|
||||
// its content is synchronized with the reference: a successful save, an
|
||||
// update proving an exact match, or an explicit cancel.
|
||||
var note_mode = [];
|
||||
var note_base = [];
|
||||
|
||||
// SDBM hash (h = c + h * 65599) of a string's UTF-8 bytes, as 8 hex chars;
|
||||
// the concurrency token sent with a note replacement. Must match the
|
||||
// server's C version; the small multiplier keeps the 32-bit state exact
|
||||
// with JS doubles (65599 * 2^32 stays well below 2^53).
|
||||
function sdbm(s) {
|
||||
var b = new TextEncoder().encode(s);
|
||||
var h = 0;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < b.length; i++)
|
||||
h = (b[i] + h * 65599) % 4294967296;
|
||||
return (h + 0x100000000).toString(16).slice(-8);
|
||||
}
|
||||
|
||||
// returns the letter of the checked verdict radio of line <i>, or ""
|
||||
function cur_state(i) {
|
||||
if (document.getElementById("bt_" + i + "_n").checked) return "n";
|
||||
if (document.getElementById("bt_" + i + "_u").checked) return "u";
|
||||
if (document.getElementById("bt_" + i + "_w").checked) return "w";
|
||||
if (document.getElementById("bt_" + i + "_y").checked) return "y";
|
||||
return "";
|
||||
}
|
||||
|
||||
// checks the verdict radio <s> of line <i> (authoritative set, idempotent)
|
||||
function set_state(i, s) {
|
||||
var el = document.getElementById("bt_" + i + "_" + s);
|
||||
if (el)
|
||||
el.checked = true;
|
||||
}
|
||||
|
||||
// Returns the verdict letter emitted in the page for line <i>, i.e. the
|
||||
// bot's verdict. It relies on defaultChecked, which reflects the "checked"
|
||||
// attribute present in the HTML and not the radio's current state: across
|
||||
// a reload, the browser restores the radios to the user's last local
|
||||
// state, so looking at cur_state() at load time would wrongly capture the
|
||||
// user's own edits as being the original state.
|
||||
function gen_state(i) {
|
||||
if (document.getElementById("bt_" + i + "_n").defaultChecked) return "n";
|
||||
if (document.getElementById("bt_" + i + "_u").defaultChecked) return "u";
|
||||
if (document.getElementById("bt_" + i + "_w").defaultChecked) return "w";
|
||||
if (document.getElementById("bt_" + i + "_y").defaultChecked) return "y";
|
||||
return "";
|
||||
}
|
||||
|
||||
// captures the bot's verdicts once the table is fully loaded: they preset
|
||||
// both the original and the reference states. After a reload, the radios
|
||||
// (and thus the local state) may differ from the bot's verdicts since the
|
||||
// browser restores them: this is desired, such differences are unsaved
|
||||
// local edits and must remain detected as such.
|
||||
function init_ref() {
|
||||
var i, el;
|
||||
|
||||
for (i = 1; i < nb_patches; i++) {
|
||||
orig[i] = gen_state(i);
|
||||
ref_state[i] = orig[i];
|
||||
ref_notes[i] = "";
|
||||
cidmap[cid[i]] = i;
|
||||
|
||||
// the browser may also have restored an unsaved note into the hidden
|
||||
// input: reveal it so that it remains visible and editable instead of
|
||||
// being invisible yet silently pushed on the next save. The edition
|
||||
// mode did not survive the reload, so assume a plain addition, which
|
||||
// never destroys anything.
|
||||
el = document.getElementById("in_" + i);
|
||||
if (el && el.value) {
|
||||
note_mode[i] = 1;
|
||||
el.style.display = "";
|
||||
}
|
||||
upd_note_links(i);
|
||||
}
|
||||
updt_save_btn();
|
||||
}
|
||||
|
||||
// the status line and the save button exist twice, at the top and at the
|
||||
// bottom of the page, so both instances are always updated together
|
||||
function sync_msg(m) {
|
||||
var el = document.getElementById("sync_msg");
|
||||
if (el)
|
||||
el.innerText = m;
|
||||
el = document.getElementById("sync_msg2");
|
||||
if (el)
|
||||
el.innerText = m;
|
||||
}
|
||||
|
||||
// renders the reference notes of line <i> by replacing the whole container
|
||||
// (never appending), so that re-applying the same notes is idempotent.
|
||||
function show_notes(i) {
|
||||
var el = document.getElementById("notes_" + i);
|
||||
if (el)
|
||||
el.innerText = ref_notes[i] ? "Notes: " + ref_notes[i] : "";
|
||||
}
|
||||
|
||||
// resolves a commit id received from the server to a line number: exact
|
||||
// match first (the normal case), then symmetric-prefix (one id is a prefix
|
||||
// of the other, which only happens with mixed-length ids), first line wins.
|
||||
// Returns 0 when unknown (eg: a commit which is not on this page).
|
||||
function find_line(ocid) {
|
||||
var i;
|
||||
|
||||
if (cidmap[ocid])
|
||||
return cidmap[ocid];
|
||||
for (i = 1; i < nb_patches; i++)
|
||||
if (cid[i].startsWith(ocid) || ocid.startsWith(cid[i]))
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Applies a freshly fetched overlay (the complete list of shared entries).
|
||||
// The new reference of every line is recomputed as "the server's entry if
|
||||
// any, otherwise the bot's original verdict", so that an entry removed on
|
||||
// the server properly falls back to the original. The reference always
|
||||
// advances, but the displayed state only moves where the user had no local
|
||||
// edit: local edits win and will overwrite the shared state at save time.
|
||||
function apply_ref(list) {
|
||||
var over_state = [], over_notes = [], claimed = [];
|
||||
var i, j, e, el, newref, newnotes, oldnotes;
|
||||
|
||||
for (j = 0; j < list.length; j++) {
|
||||
e = list[j];
|
||||
i = find_line(String(e.cid));
|
||||
if (!i || claimed[i])
|
||||
continue;
|
||||
claimed[i] = 1;
|
||||
if (e.state)
|
||||
over_state[i] = String(e.state);
|
||||
if (e.notes)
|
||||
over_notes[i] = String(e.notes);
|
||||
}
|
||||
|
||||
for (i = 1; i < nb_patches; i++) {
|
||||
newref = over_state[i] ? over_state[i] : orig[i];
|
||||
if (newref != ref_state[i] && ref_state[i] == cur_state(i))
|
||||
set_state(i, newref);
|
||||
ref_state[i] = newref;
|
||||
|
||||
oldnotes = ref_notes[i];
|
||||
newnotes = over_notes[i] ? over_notes[i] : "";
|
||||
if (newnotes != oldnotes) {
|
||||
ref_notes[i] = newnotes;
|
||||
show_notes(i);
|
||||
}
|
||||
|
||||
// Reconcile an open note box with the new reference: a box whose
|
||||
// content is now synchronized disappears (an addition someone already
|
||||
// pushed, or an edition matching the current notes); an edition whose
|
||||
// base moved is re-based on the new reference and marked red so the
|
||||
// user reviews it against the updated notes above before saving.
|
||||
if (note_mode[i]) {
|
||||
el = document.getElementById("in_" + i);
|
||||
if (note_mode[i] == 1 && el.value &&
|
||||
newnotes == (oldnotes ? oldnotes + "; " + el.value : el.value)) {
|
||||
cancel_note(i);
|
||||
}
|
||||
else if (note_mode[i] == 2) {
|
||||
if (el.value == newnotes)
|
||||
cancel_note(i);
|
||||
else if (note_base[i] != newnotes) {
|
||||
note_base[i] = newnotes;
|
||||
mark_conflict(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
upd_note_links(i);
|
||||
}
|
||||
updt_table(0);
|
||||
updt_output();
|
||||
updt_save_btn();
|
||||
}
|
||||
|
||||
// "Get updates" button: fetches the current shared state from the server
|
||||
function fetch_ref() {
|
||||
var i, el;
|
||||
|
||||
if (!branch)
|
||||
return;
|
||||
|
||||
// first silently close the no-op note boxes (opened but nothing changed,
|
||||
// e.g. an "edit" clicked by mistake): they hold nothing worth preserving
|
||||
// and would otherwise ambiguously survive while the notes displayed
|
||||
// above them change.
|
||||
for (i = 1; i < nb_patches; i++) {
|
||||
if (!note_mode[i])
|
||||
continue;
|
||||
el = document.getElementById("in_" + i);
|
||||
if (note_mode[i] == 1 && !el.value.trim())
|
||||
cancel_note(i);
|
||||
else if (note_mode[i] == 2 && el.value == note_base[i])
|
||||
cancel_note(i);
|
||||
}
|
||||
|
||||
sync_msg("fetching...");
|
||||
fetch(cgi_url + "?branch=" + branch)
|
||||
.then(function(r) { if (!r.ok) throw 0; return r.json(); })
|
||||
.then(function(list) { apply_ref(list); sync_msg("reference updated"); })
|
||||
.catch(function() { sync_msg("fetch failed (server unreachable?)"); });
|
||||
}
|
||||
|
||||
// shows/hides the per-line note links according to the edition mode and to
|
||||
// the presence of reference notes ("edit note" needs something to edit, or
|
||||
// a pending addition to merge; "cancel" needs an open input)
|
||||
function upd_note_links(i) {
|
||||
var m = note_mode[i] ? note_mode[i] : 0;
|
||||
var el;
|
||||
|
||||
el = document.getElementById("ln_add_" + i);
|
||||
if (el)
|
||||
el.style.display = m == 0 ? "" : "none";
|
||||
el = document.getElementById("ln_edit_" + i);
|
||||
if (el)
|
||||
el.style.display = (m == 0 && ref_notes[i]) || m == 1 ? "" : "none";
|
||||
el = document.getElementById("ln_cancel_" + i);
|
||||
if (el)
|
||||
el.style.display = m != 0 ? "" : "none";
|
||||
}
|
||||
|
||||
// marks/unmarks the note input of line <i> as conflicting (red): the
|
||||
// reference changed under the edit, the user must review the current notes
|
||||
// above against the input's content before saving again.
|
||||
function mark_conflict(i, on) {
|
||||
var el = document.getElementById("in_" + i);
|
||||
|
||||
if (el)
|
||||
el.style.backgroundColor = on ? "#ffc0c0" : "";
|
||||
}
|
||||
|
||||
// "[add note]" link: reveals the extra-notes input of line <i> in append
|
||||
// mode; the text it holds will be appended to the shared notes on save
|
||||
function add_note(i) {
|
||||
var el = document.getElementById("in_" + i);
|
||||
|
||||
if (!el)
|
||||
return;
|
||||
note_mode[i] = 1;
|
||||
el.maxLength = 500;
|
||||
el.style.display = "";
|
||||
el.focus();
|
||||
upd_note_links(i);
|
||||
updt_save_btn();
|
||||
}
|
||||
|
||||
// "[edit note]" link: switches line <i> to edition of the whole note blob
|
||||
// (which a save sends as a replacement); a pending addition is merged in so
|
||||
// nothing typed so far is lost. The reference blob is snapshotted as the
|
||||
// base of the edit for the conflict detection.
|
||||
function edit_note(i) {
|
||||
var el = document.getElementById("in_" + i);
|
||||
var txt;
|
||||
|
||||
if (!el)
|
||||
return;
|
||||
txt = ref_notes[i];
|
||||
if (note_mode[i] == 1 && el.value)
|
||||
txt = txt ? txt + "; " + el.value : el.value;
|
||||
note_mode[i] = 2;
|
||||
note_base[i] = ref_notes[i];
|
||||
el.value = txt;
|
||||
el.maxLength = 4000;
|
||||
el.style.display = "";
|
||||
el.focus();
|
||||
upd_note_links(i);
|
||||
updt_save_btn();
|
||||
}
|
||||
|
||||
// "[cancel]" link: closes the note input of line <i> without sending
|
||||
// anything; also used internally once an input is known synchronized.
|
||||
function cancel_note(i) {
|
||||
var el = document.getElementById("in_" + i);
|
||||
|
||||
if (el) {
|
||||
el.value = "";
|
||||
el.style.display = "none";
|
||||
}
|
||||
note_mode[i] = 0;
|
||||
note_base[i] = "";
|
||||
mark_conflict(i, 0);
|
||||
upd_note_links(i);
|
||||
updt_save_btn();
|
||||
}
|
||||
|
||||
// Grays the "Save changes" button when nothing differs from the reference
|
||||
// (no verdict change, no pending note addition or edition), so it is
|
||||
// visible at a glance whether anything remains to be saved. Called after
|
||||
// every action which may change that: verdict clicks, note box openings,
|
||||
// closings and typing, updates and saves. Bails out at the first pending
|
||||
// change so the common case stays cheap.
|
||||
function updt_save_btn() {
|
||||
var btn = document.getElementById("save_btn");
|
||||
var btn2 = document.getElementById("save_btn2");
|
||||
var pending = false;
|
||||
var i, s, el;
|
||||
|
||||
if (!btn)
|
||||
return;
|
||||
for (i = 1; i < nb_patches && !pending; i++) {
|
||||
s = cur_state(i);
|
||||
if (s && s != ref_state[i])
|
||||
pending = true;
|
||||
else if (note_mode[i]) {
|
||||
el = document.getElementById("in_" + i);
|
||||
if (note_mode[i] == 1 ? el.value.trim() != "" : el.value != note_base[i])
|
||||
pending = true;
|
||||
}
|
||||
}
|
||||
btn.disabled = !pending;
|
||||
if (btn2)
|
||||
btn2.disabled = !pending;
|
||||
}
|
||||
|
||||
// "Save changes" button: pushes the local edits, i.e. the states differing
|
||||
// from the reference, the non-empty note additions, and the note editions
|
||||
// differing from their base; the reference advances on success (failed
|
||||
// saves keep everything local for a retry). States are last-write-wins and
|
||||
// additions are append-only, so they cannot conflict; an edition carries
|
||||
// the hash of its base blob and the server refuses it if the blob changed
|
||||
// concurrently, reporting "conflict <cid>" lines that turn the concerned
|
||||
// inputs red (still in edition; "Get updates" re-bases them for revision).
|
||||
// Note that a state moved back to the reference by hand is simply not sent.
|
||||
function save_ref() {
|
||||
var st = [], nt = [], rp = [], rp_on = [];
|
||||
var body = "", nsent = 0, i, s, el, txt;
|
||||
|
||||
if (!branch)
|
||||
return;
|
||||
|
||||
for (i = 1; i < nb_patches; i++) {
|
||||
s = cur_state(i);
|
||||
if (s && s != ref_state[i]) {
|
||||
st[i] = s;
|
||||
body += cid[i] + " state " + s + "\n";
|
||||
nsent++;
|
||||
}
|
||||
el = document.getElementById("in_" + i);
|
||||
txt = el ? el.value.replace(/\r/g, "").replace(/[\x00-\x1f\x7f]/g, " ").trim() : "";
|
||||
if (note_mode[i] == 2) {
|
||||
// whole-blob replacement, possibly empty (deletion); only sent when
|
||||
// it differs from the base it was computed from
|
||||
if (txt != note_base[i]) {
|
||||
rp[i] = txt;
|
||||
rp_on[i] = 1;
|
||||
body += cid[i] + " setnotes " + sdbm(note_base[i]) + " " + txt + "\n";
|
||||
nsent++;
|
||||
}
|
||||
}
|
||||
else if (txt) {
|
||||
nt[i] = txt;
|
||||
body += cid[i] + " notes " + txt + "\n";
|
||||
nsent++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!body) {
|
||||
sync_msg("nothing to save");
|
||||
return;
|
||||
}
|
||||
|
||||
sync_msg("saving...");
|
||||
fetch(cgi_url + "?branch=" + branch, { method: "POST", body: body })
|
||||
.then(function(r) { if (!r.ok) throw 0; return r.text(); })
|
||||
.then(function(t) {
|
||||
var confl = {};
|
||||
var resp = t.split("\n");
|
||||
var i, j, ok = null, warn = "", nbc = 0;
|
||||
|
||||
// The lines of interest may be surrounded by unrelated output (some
|
||||
// servers leak the CGI's stderr into the response), so scan for them
|
||||
// anywhere: the count ("OK <n> ..."), the conflicts and the warnings.
|
||||
for (j = 0; j < resp.length; j++) {
|
||||
if (resp[j].indexOf("conflict ") == 0) {
|
||||
i = find_line(resp[j].slice(9).trim());
|
||||
if (i && !confl[i]) {
|
||||
confl[i] = 1;
|
||||
nbc++;
|
||||
}
|
||||
}
|
||||
else if (!ok)
|
||||
ok = resp[j].match(/^OK (\d+) /);
|
||||
if (resp[j].indexOf("warning: ") == 0)
|
||||
warn = "; " + resp[j];
|
||||
}
|
||||
|
||||
// The server states how many directives it applied: anything neither
|
||||
// applied nor reported as a conflict was silently ignored (e.g. an
|
||||
// outdated update.bin not knowing a directive). In that case believe
|
||||
// the server, not ourselves: advance nothing, keep every edit local
|
||||
// for a retry, and say what happened.
|
||||
if (!ok || parseInt(ok[1], 10) != nsent - nbc) {
|
||||
for (i = 1; i < nb_patches; i++) {
|
||||
if (confl[i])
|
||||
mark_conflict(i, 1);
|
||||
}
|
||||
console.log("unexpected update.cgi response: " + t);
|
||||
sync_msg("server applied only " + (ok ? ok[1] : "?") + " of " + nsent +
|
||||
" changes (outdated update.cgi/update.bin?), edits kept" + warn);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 1; i < nb_patches; i++) {
|
||||
if (st[i])
|
||||
ref_state[i] = st[i];
|
||||
if (nt[i]) {
|
||||
// mirror the server-side coalescing so the display is right
|
||||
// without refetching; the next fetch trues it up anyway
|
||||
ref_notes[i] = ref_notes[i] ? ref_notes[i] + "; " + nt[i] : nt[i];
|
||||
show_notes(i);
|
||||
cancel_note(i);
|
||||
}
|
||||
else if (rp_on[i]) {
|
||||
if (confl[i]) {
|
||||
// replacement refused, the blob changed server-side: stay in
|
||||
// edition and flag it, "Get updates" re-bases it for revision
|
||||
mark_conflict(i, 1);
|
||||
}
|
||||
else {
|
||||
ref_notes[i] = rp[i];
|
||||
show_notes(i);
|
||||
cancel_note(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
sync_msg((nbc ? "saved, but " + nbc + " note conflict(s): use Get updates and revise the red one(s)" : "saved") + warn);
|
||||
updt_save_btn();
|
||||
})
|
||||
.catch(function() { sync_msg("save failed (busy?), edits kept"); });
|
||||
}
|
||||
|
||||
// first line to review
|
||||
var review = 0;
|
||||
|
||||
|
|
@ -255,6 +725,7 @@ function updt(line,value) {
|
|||
}
|
||||
updt_table(line);
|
||||
updt_output();
|
||||
updt_save_btn();
|
||||
}
|
||||
|
||||
function show_only(b,n,u,w,y) {
|
||||
|
|
@ -267,12 +738,42 @@ function show_only(b,n,u,w,y) {
|
|||
updt(0,"r");
|
||||
}
|
||||
|
||||
// Resynchronizes the review variable with the checked review radio: across
|
||||
// a reload, the browser restores the radios to the user's last selection
|
||||
// (e.g. "All") while the variable is regenerated to the default first line
|
||||
// to review, and the listing would not match the checked radio anymore.
|
||||
function init_review() {
|
||||
var i, el;
|
||||
|
||||
if (document.getElementById("show_all").checked) {
|
||||
review = 0;
|
||||
return;
|
||||
}
|
||||
for (i = 1; i <= nb_patches; i++) {
|
||||
el = document.getElementById("rv_" + i);
|
||||
if (el && el.checked) {
|
||||
review = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -->
|
||||
</script>
|
||||
</HEAD>
|
||||
EOF
|
||||
|
||||
echo "<BODY>"
|
||||
|
||||
# the syncing UI is only emitted when the branch is known; the page reaches
|
||||
# update.cgi with a bare relative URL so it must sit in the same directory.
|
||||
if [ -n "$VERSION" ]; then
|
||||
echo -n "<div style='float: right; text-align: right;'>"
|
||||
echo -n "<button onclick='fetch_ref();' title='Retrieve the latest shared review state'>Get updates</button> "
|
||||
echo -n "<button id='save_btn' disabled onclick='save_ref();' title='Push your local edits to the shared state'>Save changes</button>"
|
||||
echo "<br/><small id='sync_msg'></small></div>"
|
||||
fi
|
||||
|
||||
echo -n "<table cellpadding=3 cellspacing=5 style='font-size: 150%;'><tr><th align=left>Backported</th>"
|
||||
echo -n "<td style='background-color:$BG_N'><a href='#' onclick='show_only(1,1,0,0,0);'> N: <span id='cnt_bn'>0</span> </a></td>"
|
||||
echo -n "<td style='background-color:$BG_U'><a href='#' onclick='show_only(1,0,1,0,0);'> U: <span id='cnt_bu'>0</span> </a></td>"
|
||||
|
|
@ -383,8 +884,11 @@ for patch in "${PATCHES[@]}"; do
|
|||
resp=$(echo "$resp" | sed -e "s|\([0-9a-f]\{7,40\}\)|<a href='${GITURL}\1'>\1</a>|g")
|
||||
|
||||
echo -n "<TD nowrap align=center ${bkp[$cid]:+style='background-color:${BG_B}'}>$seq_num<BR/>"
|
||||
echo -n "<input type='radio' name='review' onclick='updt($seq_num,\"r\");' ${do_check:+checked} title='Start review here'/></TD>"
|
||||
echo -n "<TD nowrap ${bkp[$cid]:+style='background-color:${BG_B}'}><tt><a href='${GITURL}${cid}'>$cid</a></tt>${date:+<br/><small style='font-weight:normal'>$date</small>}</TD>"
|
||||
echo -n "<input type='radio' name='review' id='rv_$seq_num' onclick='updt($seq_num,\"r\");' ${do_check:+checked} title='Start review here'/></TD>"
|
||||
# only the first 8 chars of the commit id are displayed (enough to be
|
||||
# unambiguous on one page); everything keyed (href, name=, cid[])
|
||||
# carries the full id produced by the pipeline, whatever its length.
|
||||
echo -n "<TD nowrap ${bkp[$cid]:+style='background-color:${BG_B}'}><tt><a href='${GITURL}${cid}'>${cid:0:8}</a></tt>${date:+<br/><small style='font-weight:normal'>$date</small>}</TD>"
|
||||
echo -n "<TD nowrap><a href='${GITURL}${cid}'>${pnum:+$pnum }$subj</a>${author:+<br/><div align=right><small style='font-weight:normal'>$author</small></div>}</TD>"
|
||||
echo -n "<TD nowrap align=center>"
|
||||
echo -n "<input type='radio' onclick='updt($seq_num,\"n\");' id='bt_${seq_num}_n' class='n' name='$cid' value='n' title='Drop' $( [ "$verdict" != no ] || echo -n checked) />"
|
||||
|
|
@ -392,7 +896,18 @@ for patch in "${PATCHES[@]}"; do
|
|||
echo -n "<input type='radio' onclick='updt($seq_num,\"w\");' id='bt_${seq_num}_w' class='w' name='$cid' value='w' title='wait in -next' $([ "$verdict" != wait ] || echo -n checked) />"
|
||||
echo -n "<input type='radio' onclick='updt($seq_num,\"y\");' id='bt_${seq_num}_y' class='y' name='$cid' value='y' title='Pick' $( [ "$verdict" != yes ] || echo -n checked) />"
|
||||
echo -n "</TD>"
|
||||
echo -n "<TD>$resp</TD>"
|
||||
|
||||
# the div is the dedicated container for the shared reviewers' notes,
|
||||
# filled by full replacement (never appended to) by the JS; the
|
||||
# hidden input receives the user's own note to be pushed on save
|
||||
echo -n "<TD>$resp<div class='notes' id='notes_$seq_num'></div>"
|
||||
if [ -n "$VERSION" ]; then
|
||||
echo -n "<a href='#' onclick='add_note($seq_num); return false;' id='ln_add_$seq_num' title='Add a shared note to this commit'><small>[add note]</small></a>"
|
||||
echo -n " <a href='#' onclick='edit_note($seq_num); return false;' id='ln_edit_$seq_num' style='display:none' title='Edit or delete the whole note'><small>[edit note]</small></a>"
|
||||
echo -n " <a href='#' onclick='cancel_note($seq_num); return false;' id='ln_cancel_$seq_num' style='display:none' title='Abort this note edition'><small>[cancel]</small></a>"
|
||||
echo -n " <input type='text' id='in_$seq_num' maxlength='500' size='80' style='display:none' oninput='updt_save_btn();' />"
|
||||
fi
|
||||
echo -n "</TD>"
|
||||
echo "</TR>"
|
||||
echo
|
||||
((seq_num++))
|
||||
|
|
@ -406,12 +921,23 @@ for patch in "${PATCHES[@]}"; do
|
|||
fi
|
||||
done
|
||||
|
||||
echo "<TR><TH>New<br/><input type='radio' name='review' onclick='updt($seq_num,\"r\");' ${do_check:+checked} title='Nothing to backport'/></TH><TH>CID</TH><TH>Subject</TH><TH>Verdict<BR>N U W Y</BR></TH><TH>Reason</TH></TR>"
|
||||
echo "<TR><TH>New<br/><input type='radio' name='review' id='rv_$seq_num' onclick='updt($seq_num,\"r\");' ${do_check:+checked} title='Nothing to backport'/></TH><TH>CID</TH><TH>Subject</TH><TH>Verdict<BR>N U W Y</BR></TH><TH>Reason</TH></TR>"
|
||||
|
||||
echo "</TABLE>"
|
||||
|
||||
# a copy of the syncing buttons at the bottom right: that's where the user
|
||||
# ends up after a review, far from the top ones, and forgetting to save the
|
||||
# work is too easy when no button remains in sight
|
||||
if [ -n "$VERSION" ]; then
|
||||
echo -n "<div style='float: right; text-align: right;'>"
|
||||
echo -n "<button onclick='fetch_ref();' title='Retrieve the latest shared review state'>Get updates</button> "
|
||||
echo -n "<button id='save_btn2' disabled onclick='save_ref();' title='Push your local edits to the shared state'>Save changes</button>"
|
||||
echo "<br/><small id='sync_msg2'></small></div>"
|
||||
fi
|
||||
|
||||
echo "<P/>"
|
||||
echo "<H3>Output:</H3>"
|
||||
echo "<textarea cols=120 rows=10 id='output'></textarea>"
|
||||
echo "<P/>"
|
||||
echo "<script type='text/javascript'>nb_patches=$seq_num; review=$review; updt_table(0); updt_output();</script>"
|
||||
echo "<script type='text/javascript'>nb_patches=$seq_num; review=$review; init_review(); init_ref(); updt_table(0); updt_output();</script>"
|
||||
echo "</BODY></HTML>"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ if [ -z "$BRANCH" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# The version is deduced from this script's name (update-3.0.sh -> 3.0), so
|
||||
# that a symlink with another version continues to work as-is. It's passed
|
||||
# to post-ai.sh for the page to know which branch to sync with update.cgi;
|
||||
# if the name doesn't match, no version is passed and the page simply won't
|
||||
# offer syncing.
|
||||
VERSION="${0##*/}"; VERSION="${VERSION#update-}"; VERSION="${VERSION%.sh}"
|
||||
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]] || VERSION=""
|
||||
|
||||
# eg: for v3.0-dev0^ we should get v2.9.0 hence "2.9"
|
||||
STABLE=$(cd "$HAPROXY_DIR" && git describe --tags "v${BRANCH}-dev0^" |cut -f1,2 -d.|cut -f2- -dv)
|
||||
|
||||
|
|
@ -64,4 +72,4 @@ fi
|
|||
time EXT=m7bv02.txt MODEL=${MODELS_DIR}/mistral-7b-instruct-v0.2.Q5_K_M.gguf CACHE=${PROMPTS_DIR}/prompt-${BRANCH}-m7bv02.cache PROMPT_PFX=${PROMPTS_DIR}/prompt15-${BRANCH}-mist7bv2-pfx.txt PROMPT_SFX=${PROMPTS_DIR}/prompt15-${BRANCH}-mist7bv2-sfx.txt MAINPROG=$MAINPROG PROGRAM="$SCRIPTS_DIR"/process-patch-v15.sh "$SCRIPTS_DIR"/submit-ai.sh -s ${PARALLEL_RUNS} ${PATCHES_DIR}/*.patch
|
||||
|
||||
# generate the output, takes 3-5 seconds
|
||||
"$SCRIPTS_DIR"/post-ai.sh -b "${BKP[*]}" ${PATCHES_DIR}/*.m7bv02.txt > ${VERDICT_DIR}/verdict-${BRANCH}-m7bv02.html
|
||||
"$SCRIPTS_DIR"/post-ai.sh ${VERSION:+-v "$VERSION"} -b "${BKP[*]}" ${PATCHES_DIR}/*.m7bv02.txt > ${VERDICT_DIR}/verdict-${BRANCH}-m7bv02.html
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Configuration Manual
|
||||
----------------------
|
||||
version 3.5
|
||||
2026/06/25
|
||||
2026/07/08
|
||||
|
||||
|
||||
This document covers the configuration language as implemented in the version
|
||||
|
|
@ -970,9 +970,9 @@ HAProxy is launched in master-worker mode.
|
|||
and it may as well condition some worker process parameters (see examples
|
||||
from section 2.4 "Conditional blocks").
|
||||
|
||||
In standalone mode (without "-W" option nor the "master-worker" keyword) the
|
||||
process behaves like a worker, except for variables "HAPROXY_MASTER_CLI" and
|
||||
"HAPROXY_MWORKER" which are not defined.
|
||||
In standalone mode (without "-W" option) the process behaves like a worker,
|
||||
except for variables "HAPROXY_MASTER_CLI" and "HAPROXY_MWORKER" which are not
|
||||
defined.
|
||||
|
||||
Some variables are marked as not usable and not modifiable:
|
||||
|
||||
|
|
@ -1255,8 +1255,6 @@ Example:
|
|||
# 2.3. Environment variables). Its presence enables an additional listener.
|
||||
|
||||
global
|
||||
master-worker
|
||||
|
||||
.if defined(HAPROXY_MWORKER)
|
||||
listen mwcli_px
|
||||
bind :1111
|
||||
|
|
@ -1269,8 +1267,6 @@ Example:
|
|||
# mworker-max-reloads parameter.
|
||||
|
||||
global
|
||||
master-worker
|
||||
|
||||
.if streq("$HAPROXY_BRANCH",3.1)
|
||||
mworker-max-reloads 5
|
||||
.endif
|
||||
|
|
@ -1955,10 +1951,6 @@ The following keywords are supported in the "global" section :
|
|||
- tune.quic.be.stream.rxbuf
|
||||
- tune.quic.be.tx.pacing
|
||||
- tune.quic.be.tx.udp-gso
|
||||
- tune.quic.cc.cubic.min-losses (deprecated)
|
||||
- tune.quic.cc-hystart (deprecated)
|
||||
- tune.quic.disable-tx-pacing (deprecated)
|
||||
- tune.quic.disable-udp-gso (deprecated)
|
||||
- tune.quic.fe.cc.cubic-min-losses
|
||||
- tune.quic.fe.cc.hystart
|
||||
- tune.quic.fe.cc.max-frame-loss
|
||||
|
|
@ -1974,18 +1966,8 @@ The following keywords are supported in the "global" section :
|
|||
- tune.quic.fe.stream.rxbuf
|
||||
- tune.quic.fe.tx.pacing
|
||||
- tune.quic.fe.tx.udp-gso
|
||||
- tune.quic.frontend.max-data-size (deprecated)
|
||||
- tune.quic.frontend.max-idle-timeout (deprecated)
|
||||
- tune.quic.frontend.max-streams-bidi (deprecated)
|
||||
- tune.quic.frontend.max-tx-mem (deprecated)
|
||||
- tune.quic.frontend.stream-data-ratio (deprecated)
|
||||
- tune.quic.frontend.default-max-window-size (deprecated)
|
||||
- tune.quic.listen
|
||||
- tune.quic.max-frame-loss (deprecated)
|
||||
- tune.quic.mem.tx-max
|
||||
- tune.quic.reorder-ratio (deprecated)
|
||||
- tune.quic.retry-threshold (deprecated)
|
||||
- tune.quic.socket-owner (deprecated)
|
||||
- tune.quic.zero-copy-fwd-send
|
||||
- tune.renice.runtime
|
||||
- tune.renice.startup
|
||||
|
|
@ -3050,32 +3032,6 @@ lua-prepend-path <string> [<type>]
|
|||
See https://www.lua.org/pil/8.1.html for the details within the Lua
|
||||
documentation.
|
||||
|
||||
master-worker (deprecated)
|
||||
Master-worker mode. It is equivalent to the command line "-W" argument.
|
||||
|
||||
This keyword is deprecated, please start in master-worker mode using "-W" or
|
||||
"-Ws".
|
||||
|
||||
This mode will launch a "master" which will fork a "worker" after reading the
|
||||
configuration to process the traffic. The master is used as a process manager
|
||||
which will monitor the "workers".
|
||||
|
||||
Using this mode, you can reload HAProxy directly by sending a SIGUSR2 signal
|
||||
to the master. Reloading will ask the master to read the configuration again
|
||||
and fork a new worker. The previous worker will be kept until the end of its
|
||||
jobs.
|
||||
|
||||
The master-worker mode is compatible either with the foreground or daemon
|
||||
mode.
|
||||
|
||||
By default, if a worker exits with a bad return code, in the case of a
|
||||
segfault for example, all workers will be killed, and the master will leave.
|
||||
It is convenient to combine this behavior with Restart=on-failure in a
|
||||
systemd unit file in order to relaunch the whole process. If you don't want
|
||||
this behavior, you must use the keyword "no-exit-on-failure".
|
||||
|
||||
See also "-W" in the management guide.
|
||||
|
||||
master-worker no-exit-on-failure
|
||||
In master-worker mode, by default, if a worker exits with a bad return code,
|
||||
in the case of a segfault for example, all workers will be killed, and the
|
||||
|
|
@ -3171,7 +3127,7 @@ pidfile <pidfile>
|
|||
Writes PIDs of all daemons into file <pidfile> when daemon mode or writes PID
|
||||
of master process into file <pidfile> when master-worker mode. This option is
|
||||
equivalent to the "-p" command line argument. The file must be accessible to
|
||||
the user starting the process. See also "daemon" and "master-worker".
|
||||
the user starting the process. See also "daemon".
|
||||
|
||||
pp2-never-send-local
|
||||
A bug in the PROXY protocol v2 implementation was present in HAProxy up to
|
||||
|
|
@ -5142,22 +5098,12 @@ tune.quic.fe.cc.cubic-min-losses <number>
|
|||
compare some metrics. Never go beyond 2 without an expert's prior analysis of
|
||||
the situation. The default and minimum value is 1. Always use 1.
|
||||
|
||||
tune.quic.cc.cubic.min-losses <number> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.cc.hystart { on | off }
|
||||
tune.quic.fe.cc.hystart { on | off }
|
||||
Enables ('on') or disabled ('off') the HyStart++ (RFC 9406) algorithm for
|
||||
QUIC connections used as a replacement for the slow start phase of congestion
|
||||
control algorithms which may cause high packet loss. It is disabled by default.
|
||||
|
||||
tune.quic.cc-hystart { on | off } (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.cc.max-frame-loss <number>
|
||||
tune.quic.fe.cc.max-frame-loss <number>
|
||||
Sets the limit for which a single QUIC frame can be marked as lost. If
|
||||
|
|
@ -5165,11 +5111,6 @@ tune.quic.fe.cc.max-frame-loss <number>
|
|||
|
||||
The default value is 10.
|
||||
|
||||
tune.quic.max-frame-loss <number> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.cc.max-win-size <size>
|
||||
tune.quic.fe.cc.max-win-size <size>
|
||||
Sets the default maximum window size for the congestion controller of a
|
||||
|
|
@ -5185,11 +5126,6 @@ tune.quic.fe.cc.max-win-size <size>
|
|||
|
||||
See also the "quic-cc-algo" bind and server options.
|
||||
|
||||
tune.quic.frontend.default-max-window-size <size> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.cc.reorder-ratio <0..100, in percent>
|
||||
tune.quic.fe.cc.reorder-ratio <0..100, in percent>
|
||||
The ratio applied to the packet reordering threshold calculated. It may
|
||||
|
|
@ -5197,11 +5133,6 @@ tune.quic.fe.cc.reorder-ratio <0..100, in percent>
|
|||
|
||||
The default value is 50.
|
||||
|
||||
tune.quic.reorder-ratio <0..100, in percent> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.max-idle-timeout <timeout>
|
||||
tune.quic.fe.max-idle-timeout <timeout>
|
||||
Sets the QUIC max_idle_timeout transport parameters on either frontend or
|
||||
|
|
@ -5215,11 +5146,6 @@ tune.quic.fe.max-idle-timeout <timeout>
|
|||
|
||||
The default value is 30s.
|
||||
|
||||
tune.quic.frontend.max-idle-timeout <timeout> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.sec.glitches-threshold <number>
|
||||
tune.quic.fe.sec.glitches-threshold <number>
|
||||
Sets the threshold for the number of glitches per connection either on
|
||||
|
|
@ -5235,11 +5161,6 @@ tune.quic.fe.sec.glitches-threshold <number>
|
|||
|
||||
See also: fc_glitches, tune.glitches.kill.cpu-usage
|
||||
|
||||
tune.quic.frontend.glitches-threshold <number> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.fe.sec.retry-threshold <number>
|
||||
Dynamically enables the Retry feature for all the configured QUIC listeners
|
||||
as soon as this number of half open connections is reached. A half open
|
||||
|
|
@ -5254,11 +5175,6 @@ tune.quic.fe.sec.retry-threshold <number>
|
|||
See https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 for more
|
||||
information about QUIC retry.
|
||||
|
||||
tune.quic.retry-threshold <number> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.fe.sock-per-conn { default-on | force-off }
|
||||
Specifies globally how QUIC frontend connections will use socket for
|
||||
receive/send operations. Connections can share listener socket or each
|
||||
|
|
@ -5288,12 +5204,6 @@ tune.quic.fe.sock-per-conn { default-on | force-off }
|
|||
"force-off" is used globally, it will be applied on every listener instance,
|
||||
regardless of their individual configuration.
|
||||
|
||||
tune.quic.socket-owner { connection | listener } (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. The newer
|
||||
option is named "tune.quic.fe.sock-per-conn", with legacy value "connection"
|
||||
corresponding to "default-on" and "listener" to "force-off".
|
||||
|
||||
tune.quic.be.stream.data-ratio <0..100, in percent>
|
||||
tune.quic.fe.stream.data-ratio <0..100, in percent>
|
||||
This setting allows to configure the hard limit of the number of data bytes
|
||||
|
|
@ -5314,11 +5224,6 @@ tune.quic.fe.stream.data-ratio <0..100, in percent>
|
|||
"tune.quic.be.stream.max-concurrent",
|
||||
"tune.quic.fe.stream.max-concurrent"
|
||||
|
||||
tune.quic.frontend.stream-data-ratio <0..100, in percent> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.stream.max-concurrent <number>
|
||||
tune.quic.fe.stream.max-concurrent <number>
|
||||
On frontend side, this is used as the value for the advertised
|
||||
|
|
@ -5362,11 +5267,6 @@ tune.quic.fe.stream.max-total <number>
|
|||
The default value is 0 which implies no specific limit outside of the QUIC
|
||||
protocol encoding limitation (2^60, more than a billion billion).
|
||||
|
||||
tune.quic.frontend.max-streams-bidi <number> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.stream.rxbuf <size>
|
||||
tune.quic.fe.stream.rxbuf <size>
|
||||
This setting is the hard limit for the number of data bytes in flight over a
|
||||
|
|
@ -5384,11 +5284,6 @@ tune.quic.fe.stream.rxbuf <size>
|
|||
"tune.quic.fe.stream.max-concurrent",
|
||||
"tune.quic.be.stream.data-ratio", "tune.quic.fe.stream.data-ratio"
|
||||
|
||||
tune.quic.frontend.max-data-size <size> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.tx.pacing { on | off }
|
||||
tune.quic.fe.tx.pacing { on | off }
|
||||
Enables ('on') or disables ('off') pacing support for QUIC emission. By
|
||||
|
|
@ -5400,11 +5295,6 @@ tune.quic.fe.tx.pacing { on | off }
|
|||
|
||||
See also the "quic-cc-algo" bind and server options.
|
||||
|
||||
tune.quic.disable-tx-pacing (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.be.tx.udp-gso { on | off }
|
||||
tune.quic.fe.tx.udp-gso { on | off }
|
||||
Enables ('on') or disables ('off') UDP GSO support for QUIC emission. By
|
||||
|
|
@ -5413,11 +5303,6 @@ tune.quic.fe.tx.udp-gso { on | off }
|
|||
be useful to disable it on developers suggestion when suspecting an issue on
|
||||
emission.
|
||||
|
||||
tune.quic.disable-udp-gso (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.listen { on | off }
|
||||
Disable QUIC transport protocol on the frontend side. All the QUIC listeners
|
||||
will still be created, but they won't listen for incoming datagrams. Hence,
|
||||
|
|
@ -5437,11 +5322,6 @@ tune.quic.mem.tx-max <size>
|
|||
connection will always be able to use a window of at least 2 datagrams, so a
|
||||
proper maxconn should be used in conjunction.
|
||||
|
||||
tune.quic.frontend.max-tx-mem <size> (deprecated)
|
||||
This keyword has been deprecated in 3.3 and will be removed in 3.5. It is
|
||||
part of the streamlining process apply on QUIC configuration. If used, this
|
||||
setting will only be applied on frontend connections.
|
||||
|
||||
tune.quic.zero-copy-fwd-send { on | off }
|
||||
Enables ('on') of disabled ('off') the zero-copy sends of data for the QUIC
|
||||
multiplexer. It is enabled by default.
|
||||
|
|
@ -6160,7 +6040,6 @@ default-server X - X X
|
|||
default_backend X X X -
|
||||
description - X X X
|
||||
disabled X X X X
|
||||
dispatch (deprecated) - - X X
|
||||
email-alert from X X X X
|
||||
email-alert level X X X X
|
||||
email-alert mailers X X X X
|
||||
|
|
@ -6269,7 +6148,6 @@ option tcp-smart-accept (*) X X X -
|
|||
option tcp-smart-connect (*) X - X X
|
||||
option tcpka X X X X
|
||||
option tcplog X X X -
|
||||
option transparent (deprecated) (*) X - X X
|
||||
option use-small-buffers (*) X - X X
|
||||
persist rdp-cookie X - X X
|
||||
quic-initial X (!) X X -
|
||||
|
|
@ -6331,7 +6209,6 @@ timeout server X - X X
|
|||
timeout server-fin X - X X
|
||||
timeout tarpit X X X X
|
||||
timeout tunnel X - X X
|
||||
transparent (deprecated) X - X X
|
||||
unique-id-format X X X X
|
||||
unique-id-header X X X -
|
||||
use_backend - X X -
|
||||
|
|
@ -6746,7 +6623,7 @@ balance url_param <param> [check_post]
|
|||
might be a URL parameter list. This is probably not a concern with SGML
|
||||
type message bodies.
|
||||
|
||||
See also : "dispatch", "cookie", "transparent", "hash-type".
|
||||
See also : "cookie", "hash-type".
|
||||
|
||||
|
||||
bind [<address>]:<port_range> [, ...] [param*]
|
||||
|
|
@ -7527,54 +7404,6 @@ disabled
|
|||
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>
|
||||
Set the dynamic cookie secret key for a backend.
|
||||
|
||||
|
|
@ -12137,46 +11966,6 @@ option tcplog [clf]
|
|||
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 ]*
|
||||
|
||||
Enable support for small buffers for the given categories.
|
||||
|
|
@ -12605,9 +12394,9 @@ server <name> <address>[:[port]] [param*]
|
|||
address as the one from the client connection. This is useful in
|
||||
transparent proxy architectures where the client's connection is
|
||||
intercepted and HAProxy must forward to the original destination
|
||||
address. This is more or less what the "transparent" keyword does
|
||||
except that with a server it's possible to limit concurrency and
|
||||
to report statistics. Optionally, an address family prefix may be
|
||||
address. This is more or less what the old "transparent" keyword
|
||||
did except that servers do not have the keyword's limitations
|
||||
(ssl, queues etc). Optionally, an address family prefix may be
|
||||
used before the address to force the family regardless of the
|
||||
address format, which can be useful to specify a path to a unix
|
||||
socket with no slash ('/'). Currently supported prefixes are :
|
||||
|
|
@ -12969,7 +12758,9 @@ stats admin { if | unless } <cond>
|
|||
matched.
|
||||
|
||||
The admin level allows to enable/disable servers from the web interface. By
|
||||
default, statistics page is read-only for security reasons.
|
||||
default, statistics page is read-only for security reasons. If "stats scope"
|
||||
directives are set in the section, then only proxies designated by these
|
||||
directives will accept state changes; access to other ones will be denied.
|
||||
|
||||
Currently, the POST request is limited to the buffer size minus the reserved
|
||||
buffer space, which means that if the list of servers is too long, the
|
||||
|
|
@ -13004,8 +12795,8 @@ stats admin { if | unless } <cond>
|
|||
stats http-request auth unless AUTH
|
||||
stats admin if AUTH_ADMIN
|
||||
|
||||
See also : "stats enable", "stats auth", "stats http-request", section 12.2
|
||||
about userlists and section 7 about ACL usage.
|
||||
See also : "stats enable", "stats auth", "stats http-request", "stats scope",
|
||||
section 12.2 about userlists and section 7 about ACL usage.
|
||||
|
||||
ssl-f-use [<sslbindconf> ...]*
|
||||
Assignate a certificate to the current frontend.
|
||||
|
|
@ -13333,11 +13124,11 @@ stats scope { <name> | "." }
|
|||
section in which the statement appears.
|
||||
|
||||
When this statement is specified, only the sections enumerated with this
|
||||
statement will appear in the report. All other ones will be hidden. This
|
||||
statement may appear as many times as needed if multiple sections need to be
|
||||
reported. Please note that the name checking is performed as simple string
|
||||
comparisons, and that it is never checked that a give section name really
|
||||
exists.
|
||||
statement will appear in the report. All other ones will be hidden, and
|
||||
attempts to change their state in admin mode will be rejected. This statement
|
||||
may appear as many times as needed if multiple sections need to be reported.
|
||||
Please note that the name checking is performed as simple string comparisons,
|
||||
and that it is never checked that a give section name really exists.
|
||||
|
||||
Though this statement alone is enough to enable statistics reporting, it is
|
||||
recommended to set all other settings in order to avoid relying on default
|
||||
|
|
@ -13361,7 +13152,8 @@ stats scope { <name> | "." }
|
|||
stats uri /admin?stats
|
||||
stats refresh 5s
|
||||
|
||||
See also : "stats auth", "stats enable", "stats realm", "stats uri"
|
||||
See also : "stats auth", "stats enable", "stats realm", "stats uri" and
|
||||
"stats admin"
|
||||
|
||||
|
||||
stats show-desc [ <desc> ]
|
||||
|
|
@ -15162,32 +14954,6 @@ timeout tunnel <timeout>
|
|||
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>
|
||||
Generate a unique ID for each request.
|
||||
|
||||
|
|
@ -15652,7 +15418,7 @@ cache-store <name>
|
|||
See section 6.2 about cache setup.
|
||||
|
||||
|
||||
cache-use <name>
|
||||
cache-use <name> [no-early-hints]
|
||||
Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft
|
||||
- | - | - | - | - | X | - | -
|
||||
|
||||
|
|
@ -15661,6 +15427,12 @@ cache-use <name>
|
|||
use a condition for both storage and delivering that's a good idea to put it
|
||||
after this one.
|
||||
|
||||
When the named cache has "early-hints" enabled, lookups handled by this
|
||||
rule may emit a 103 Early Hints response if the requested URL has known
|
||||
"Link" hints in the cache. The optional "no-early-hints" keyword
|
||||
suppresses 103 emission for requests handled by this rule, regardless of
|
||||
the cache-level setting.
|
||||
|
||||
See section 6.2 about cache setup.
|
||||
|
||||
|
||||
|
|
@ -16798,7 +16570,11 @@ set-retries <int> | <epxr>
|
|||
|
||||
Note that this action is only relevant on the backend side and thus this rule
|
||||
is only available for the proxies with backend capability. It is also not
|
||||
allowed in "defaults" sections.
|
||||
allowed in "defaults" sections. When the action is used for a listener, it is
|
||||
evaluated in the frontend context. So retries value is conserved only if
|
||||
stream is not routed to a different backend, via a use-backend rule for
|
||||
instance. Otherwise the default retries value of the selected backend will be
|
||||
preset.
|
||||
|
||||
Example:
|
||||
tcp-request content set-retries 3
|
||||
|
|
@ -16886,7 +16662,11 @@ set-timeout { client | connect | queue | server | tarpit | tunnel } { <timeout>
|
|||
the backend side and thus this rule is only available for the proxies with
|
||||
backend capabilities. Likewise, client timeout is only relevant for frontend
|
||||
side. Tarpit timeout is available to both sides. The timeout value must be
|
||||
non-null to obtain the expected results.
|
||||
non-null to obtain the expected results. When the action is used for a
|
||||
listener, it is evaluated in the frontend context. So custom values for
|
||||
backend-side timeouts are conserved only if stream is not routed to a
|
||||
different backend, via a use-backend rule for instance. Otherwise the default
|
||||
values of the selected backend will be preset.
|
||||
|
||||
Example:
|
||||
http-request set-timeout tunnel 5s
|
||||
|
|
@ -20469,6 +20249,33 @@ cache <name>
|
|||
Declare a cache section, allocate a shared cache memory named <name>, the
|
||||
size of cache is mandatory (see keyword "total-max-size" below).
|
||||
|
||||
early-hints <on/off/only> [ratio <integer>]
|
||||
Enable or disable support for HTTP 103 Early Hints responses (see RFC 8297).
|
||||
When enabled, the cache remembers relevant "Link" response headers (with a
|
||||
"rel" parameter of preload, preconnect, dns-prefetch, modulepreload or
|
||||
prefetch) seen on cached responses. When a subsequent "cache-use" lookup
|
||||
cannot serve the full response from the cache but the URL's "Link" hints
|
||||
are still known, the cache emits a 103 Early Hints response carrying those
|
||||
hints before forwarding the request to the backend, giving the client a
|
||||
head start on fetching subresources while the backend produces the body.
|
||||
Individual "cache-use" rules may opt out of this behavior with the
|
||||
"no-early-hints" keyword. The default value is off (disabled).
|
||||
|
||||
When "early-hints" is set to "only", no responses are stored in the cache.
|
||||
Instead, if a backend response contains relevant "Link" headers as defined
|
||||
above, the cache stores those in order to emit a 103 Early Hints response if
|
||||
that same URL is accessed later. Since the response body is never stored in
|
||||
this mode, the "max-object-size" limit does not apply: hints are extracted
|
||||
and stored regardless of the response's size.
|
||||
|
||||
The optional "ratio" argument sets the percentage of total cache blocks
|
||||
that may be reserved for hints-only entries (1 to 99, default 25). Higher
|
||||
values keep hints alive longer at the cost of less space for full responses;
|
||||
lower values prioritize full responses. This argument only makes sense when
|
||||
"early-hints" is set to on, and is ignored otherwise. In "only" mode every
|
||||
stored entry is a hints entry, so the whole cache is available to them and
|
||||
this ratio has no practical effect.
|
||||
|
||||
max-age <seconds>
|
||||
Define the maximum expiration duration. The expiration is set as the lowest
|
||||
value between the s-maxage or max-age (in this order) directive in the
|
||||
|
|
@ -24524,6 +24331,7 @@ bc_srv_queue integer
|
|||
be_id integer
|
||||
be_name string
|
||||
be_connect_timeout integer
|
||||
be_max_retries integer
|
||||
be_queue_timeout integer
|
||||
be_server_timeout integer
|
||||
be_tarpit_timeout integer
|
||||
|
|
@ -24532,6 +24340,7 @@ bytes_in integer
|
|||
bytes_out integer
|
||||
cur_connect_timeout integer
|
||||
cur_client_timeout integer
|
||||
cur_max_retries integer
|
||||
cur_queue_timeout integer
|
||||
cur_server_timeout integer
|
||||
cur_tarpit_timeout integer
|
||||
|
|
@ -24868,6 +24677,11 @@ be_connect_timeout : integer
|
|||
current backend. This timeout can be overwritten by a "set-timeout" rule. See
|
||||
also the "cur_connect_timeout".
|
||||
|
||||
be_max_retries : integer
|
||||
Returns the configuration value for the connection retries of the current
|
||||
backend. This value can be overwritten by a "set-retries" rule. See also the
|
||||
"cur_max_retries".
|
||||
|
||||
be_name : string
|
||||
Returns a string containing the current backend's name. It can be used in
|
||||
frontends with responses to check which backend processed the request. If
|
||||
|
|
@ -24911,6 +24725,11 @@ cur_client_timeout : integer
|
|||
In the default case, this will be equal to fe_client_timeout unless a
|
||||
"set-timeout" rule has been applied. See also "fe_client_timeout".
|
||||
|
||||
cur_max_retries : integer
|
||||
Returns the currently applied connect retries for the stream.
|
||||
In the default case, this will be equal to be_max_retries unless a
|
||||
"set-retries" rule has been applied. See also "be_max_retries".
|
||||
|
||||
cur_queue_timeout : integer
|
||||
Returns the currently applied queue timeout in millisecond for the stream.
|
||||
In the default case, this will be equal to be_queue_timeout unless a
|
||||
|
|
@ -30693,41 +30512,9 @@ See also: "use-fcgi-app", section 9.2 about the compression filter, section 9.4
|
|||
9.6. OpenTracing
|
||||
----------------
|
||||
|
||||
The OpenTracing filter adds native support for using distributed tracing in
|
||||
HAProxy. This is enabled by sending an OpenTracing compliant request to one
|
||||
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:
|
||||
The OpenTracing filter was removed in version 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/
|
||||
|
||||
|
|
|
|||
146
doc/haload.txt
Normal file
146
doc/haload.txt
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
------
|
||||
HALoad
|
||||
------
|
||||
HAProxy's dummy HTTP
|
||||
client for benchmarks
|
||||
|
||||
1. Background
|
||||
-------------
|
||||
|
||||
HALoad is a lightweight, multi-threaded traffic generator designed to benchmark
|
||||
HTTP infrastructures under heavy loads. Built directly onto HAProxy's highly
|
||||
scalable core architecture, it shares its parent engine's efficient handling of
|
||||
connections. This framework allows the tool to generate high-volume traffic
|
||||
across all standard application layers, including HTTP/1, HTTP/2, and HTTP/3
|
||||
(QUIC), over either cleartext or secured TLS connections.
|
||||
|
||||
The primary design goal is to provide a modernized alternative to legacy tools
|
||||
like h1load, extending benchmarking capabilities to newer protocols. Notably,
|
||||
HALoad introduces the concept of users (-u), a feature completely absent
|
||||
from h1load. Here, a "user" strictly represents an independent, concurrent
|
||||
HTTP client task. Under this architecture, each simulated client will
|
||||
instantiate as many backend server connections as there are target URLs
|
||||
specified on the command line.
|
||||
|
||||
HALoad does not require any configuration file. Instead, the configuration is
|
||||
dynamically derived from basic command line inputs. This ensures immediate
|
||||
usability for test operators while retaining the ability to test complex,
|
||||
multi-protocol setups.
|
||||
|
||||
|
||||
2. Compilation
|
||||
--------------
|
||||
|
||||
The compilation process mirrors standard HAProxy builds, specifying "haload"
|
||||
as the compilation target via the command line:
|
||||
|
||||
$ make -j $(nproc) TARGET=linux-glibc haload
|
||||
|
||||
To enable encrypted communication layers (TLS/SSL):
|
||||
|
||||
$ make TARGET=linux-glibc USE_OPENSSL=1 haload
|
||||
|
||||
For advanced HTTP/3 over QUIC load testing:
|
||||
|
||||
$ make -j $(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_QUIC=1 haload
|
||||
|
||||
Because HALoad shares the code of the main HAProxy binary, it natively
|
||||
inherits all standard HAProxy compiler flags, optimizations, and build
|
||||
targets.
|
||||
|
||||
|
||||
3. Execution
|
||||
------------
|
||||
|
||||
HALoad displays its usage when run without argument or wrong arguments:
|
||||
|
||||
Usage : haload [opts] [URL]
|
||||
where <opts> may be any combination of:
|
||||
-d <time> test duration in seconds (0)
|
||||
-e stop upon first connection error
|
||||
-h(0|1|2|2c|3) use h0 (hq-interop for QUIC), h1, h2, h2c or h3
|
||||
(QUIC/TCP) protocols (*)
|
||||
-(0|1|2|2c|3) same as above (*)
|
||||
-l enable long output format; double for raw values
|
||||
-m <streams> maximum concurrent streams (1)
|
||||
-n <reqs> maximum total requests (-1)
|
||||
-r <reqs> number of requests per connection (-1)
|
||||
-s <time> soft start: time in sec to reach 100% load
|
||||
-t <threads> number of threads
|
||||
-u <users> number of users (1)
|
||||
-w <time> I/O timeout in milliseconds (10000)
|
||||
-C dump the configuration and exit
|
||||
-H "foo:bar" add this header name and value
|
||||
-I use HEAD instead of GET
|
||||
-v shows version
|
||||
--defaults <str> add a string to default section
|
||||
--global <str> add a string to global section
|
||||
--server <opts> set server <opt> options as defined for "server"
|
||||
haproxy keyword
|
||||
--show-status-codes show HTTP status codes distribution
|
||||
--traces enable the traces for all the HTTP protocols
|
||||
SSL options:
|
||||
--tls-ciphers <ciphers> for TLS1.2 and below (*)
|
||||
--tls-ciphersuites <ciphers> for TLS1.3 and above (*)
|
||||
--tls-curves <curves> (*)
|
||||
URL format:
|
||||
(http://|https://|quic://)<addr>:<port>/<path>
|
||||
Note: Options marked with an asterisk (*) are positional and MUST be placed
|
||||
BEFORE the URLs they are intended to affect.
|
||||
|
||||
|
||||
At startup, HALoad dynamically generates an HAProxy configuration in memory.
|
||||
Options like --global and --defaults allow raw configuration lines to be added
|
||||
directly to the "global" and "defaults" sections, while --server appends
|
||||
options to the backend server. These parameters support standard escaped
|
||||
notation (e.g., '\n' or '\t') to insert multi-line statements in a single
|
||||
argument en ligne de commande.
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
# 30-second test using 4 threads simulating 10 distinct users
|
||||
$ ./haload -t 4 -u 10 -d 30 http://127.0.0.1:8888/
|
||||
|
||||
# HTTP/3 test limiting concurrent streams to 3 per connection (-m3)
|
||||
$ ./haload -m3 quic://127.0.0.1:8889/
|
||||
|
||||
# Dump the generated memory configuration and exit (-C)
|
||||
$ ./haload https://127.0.0.1:4443 -C
|
||||
global
|
||||
tune.memory.hot-size 3145728
|
||||
ssl-server-verify none
|
||||
tune.h2.be.max-concurrent-streams 1
|
||||
tune.quic.be.stream.max-concurrent 1
|
||||
|
||||
# Dump the configuration and exit (-C) to check -m3 effect
|
||||
$ ./haload https://127.0.0.1:4443 -m3 -C
|
||||
global
|
||||
tune.memory.hot-size 3145728
|
||||
ssl-server-verify none
|
||||
tune.h2.be.max-concurrent-streams 3
|
||||
tune.quic.be.stream.max-concurrent 3
|
||||
|
||||
# Add a custom directive into defaults, dump the configuration and exit (-C)
|
||||
$ ./haload https://127.0.0.1:4443 --defaults "timeout connect 5s" -C
|
||||
global
|
||||
tune.memory.hot-size 3145728
|
||||
ssl-server-verify none
|
||||
tune.h2.be.max-concurrent-streams 1
|
||||
tune.quic.be.stream.max-concurrent 1
|
||||
defaults
|
||||
timeout connect 5s
|
||||
|
||||
|
||||
4. Limitations
|
||||
--------------
|
||||
|
||||
When using HTTP/3 (QUIC or QMUX) protocols with the maximum concurrent streams
|
||||
option (-m) enabled, HAProxy's connection layer currently does not enforce or
|
||||
respect the strict limit on the number of open connections usually dictated by
|
||||
the concurrent users option (-u).
|
||||
|
||||
For example, when targeting a single URL, specifying "-u 10 -m 5" might lead
|
||||
to opening more than 10 concurrent connections to the target server under
|
||||
heavy load, instead of strictly capping the total connections to the requested
|
||||
number of users.
|
||||
|
|
@ -33,7 +33,7 @@ target to provide on the "make" command line as follows:
|
|||
|
||||
HATerm supports HTTPS/SSL/TCP:
|
||||
|
||||
$ make TARGET=linux-glibc USE_OPENSSL=1
|
||||
$ make TARGET=linux-glibc USE_OPENSSL=1 haterm
|
||||
|
||||
It also supports QUIC:
|
||||
|
||||
|
|
|
|||
|
|
@ -1367,6 +1367,16 @@ Here is the list of static fields using the proxy statistics domain:
|
|||
since the worker process started
|
||||
112. proto [L...]: protocol
|
||||
113. priv_idle_cur [...S]: current number of private idle connections
|
||||
114. reqbin [LFBS]: total number of request bytes received since the worker
|
||||
process started
|
||||
115. reqbout [LFBS]: total number of request bytes sent since the worker
|
||||
process started
|
||||
116. resbin [LFBS]: total number of response bytes received since the worker
|
||||
process started
|
||||
117. resbout [LFBS]: total number of response bytes sent since the worker
|
||||
process started
|
||||
118. cache_hint_hits [.FB.]: cumulative number of cache hits having served
|
||||
early hints
|
||||
|
||||
For all other statistics domains, the presence or the order of the fields are
|
||||
not guaranteed. In this case, the header line should always be used to parse
|
||||
|
|
@ -2148,8 +2158,7 @@ del backend <name>
|
|||
There is additional restrictions which prevent backend removal. First, a
|
||||
backend cannot be removed if it is explicitly referenced by config elements,
|
||||
for example via a use_backend rule or in sample expressions. Some proxies
|
||||
options are also incompatible with runtime deletion. Currently, this is the
|
||||
case when deprecated dispatch or option transparent are used. Also, a backend
|
||||
options are also incompatible with runtime deletion. Currently, a backend
|
||||
cannot be removed if there is a stick-table declared in it. Finally, it is
|
||||
impossible for now to remove a backend if QUIC servers were present in it.
|
||||
|
||||
|
|
@ -2701,6 +2710,46 @@ set server <backend>/<server> ssl [ on | off ] (deprecated)
|
|||
This command is deprecated, create a new server dynamically with or without
|
||||
SSL instead, using the "add server" command.
|
||||
|
||||
set server <backend>/<server> name <newname>
|
||||
Change the name of a server at runtime.
|
||||
|
||||
Two preconditions are enforced:
|
||||
- the server must be administratively in maintenance mode (set first
|
||||
via "set server <b>/<s> state maint" or "disable server <b>/<s>");
|
||||
- the server's name must not be statically referenced by a
|
||||
"use-server" rule, a "track" directive, or a sample-fetch argument
|
||||
of type ARGT_SRV. Such references are recorded at configuration
|
||||
load time and renaming the target would leave the running state
|
||||
inconsistent with the configuration text.
|
||||
|
||||
Like "add server" and "del server", this command is not gated by a
|
||||
per-backend opt-in directive: availability is determined entirely by
|
||||
the server's runtime properties.
|
||||
|
||||
The new name must be syntactically valid (non-empty, must pass
|
||||
invalid_char(), i.e. only [A-Za-z0-9_:.-]) and must be unique among
|
||||
all servers in the backend. The change is effective immediately for
|
||||
all runtime operations, stats, and logs, but is not persisted to the
|
||||
configuration file and will be lost on reload. Some features that
|
||||
rely on static server names (such as stick-tables or external
|
||||
monitoring) may not recognize the new name until restart.
|
||||
|
||||
A successful rename publishes an EVENT_HDL_SUB_SERVER_NAME event
|
||||
carrying the old and new names, which Lua scripts and other event
|
||||
consumers can subscribe to.
|
||||
|
||||
There is no strict requirement that no sessions are active before
|
||||
renaming. However, if there are active sessions, log entries for
|
||||
those sessions may use either the old or new name, depending on when
|
||||
the rename occurs relative to logging. This may result in split or
|
||||
inconsistent logs for in-flight requests. If strict log consistency
|
||||
is required, it is the user's responsibility to ensure all sessions
|
||||
have finished before renaming (e.g. by draining via maintenance mode
|
||||
and waiting for all connections to close).
|
||||
|
||||
Example:
|
||||
set server myapp/s1 name blue
|
||||
|
||||
set severity-output [ none | number | string ]
|
||||
Change the severity output format of the stats socket connected to for the
|
||||
duration of the current session.
|
||||
|
|
@ -3108,7 +3157,7 @@ show events [<sink>] [-w] [-n] [-0]
|
|||
delimited by a line feed character ('\n' or 10 or 0x0A). It is possible to
|
||||
change this to the NUL character ('\0' or 0) by passing the "-0" argument.
|
||||
|
||||
show fd [-!plcfbsd]* [[<tgid>]/[<fd>] | <fd>]
|
||||
show fd [-!plcfbs]* [[<tgid>]/[<fd>] | <fd>]
|
||||
Dump the list of either all open file descriptors or just the one number <fd>
|
||||
if specified. The form "<tgid>/<fd>" is also accepted, where either side may
|
||||
be empty as a wildcard ("/<fd>" for fd <fd> across thread groups, "<tgid>/"
|
||||
|
|
@ -3118,30 +3167,28 @@ show fd [-!plcfbsd]* [[<tgid>]/[<fd>] | <fd>]
|
|||
types. When '-' or '!' are encountered, the selection is inverted for the
|
||||
following characters in the same argument. The inversion is reset before each
|
||||
argument word delimited by white spaces. Selectable FD types include 'p' for
|
||||
pipes, 'l' for listeners, 'c' for connections (any type), 'f' for frontend
|
||||
connections, 'b' for backend connections (any type), 's' for connections to
|
||||
servers, 'd' for connections to the "dispatch" address or the backend's
|
||||
transparent address. With this, 'b' is a shortcut for 'sd' and 'c' for 'fb' or
|
||||
'fsd'. 'c!f' is equivalent to 'b' ("any connections except frontend
|
||||
connections" are indeed backend connections). This is only aimed at developers
|
||||
who need to observe internal states in order to debug complex issues such as
|
||||
abnormal CPU usages. One fd is reported per lines, and for each of them, its
|
||||
state in the poller using upper case letters for enabled flags and lower case
|
||||
for disabled flags, using "P" for "polled", "R" for "ready", "A" for "active",
|
||||
the events status using "H" for "hangup", "E" for "error", "O" for "output",
|
||||
"P" for "priority" and "I" for "input", a few other flags like "N" for "new"
|
||||
(just added into the fd cache), "U" for "updated" (received an update in the
|
||||
fd cache), "L" for "linger_risk", "C" for "cloned", then the cached entry
|
||||
pipes, 'l' for listeners, 'c' for connections (any type, shortcut for 'fb'),
|
||||
'f' for frontend connections, 'b' or 's' for backend connections to servers.
|
||||
'c!f' is equivalent to 'b' ("any connections except frontend connections" are
|
||||
indeed backend connections). This is only aimed at developers who need to
|
||||
observe internal states in order to debug complex issues such as abnormal CPU
|
||||
usages. One fd is reported per lines, and for each of them, its state in the
|
||||
poller using upper case letters for enabled flags and lower case for disabled
|
||||
flags, using "P" for "polled", "R" for "ready", "A" for "active", the events
|
||||
status using "H" for "hangup", "E" for "error", "O" for "output", "P" for
|
||||
"priority" and "I" for "input", a few other flags like "N" for "new" (just
|
||||
added into the fd cache), "U" for "updated" (received an update in the fd
|
||||
cache), "L" for "linger_risk", "C" for "cloned", then the cached entry
|
||||
position, the pointer to the internal owner, the pointer to the I/O callback
|
||||
and its name when known. When the owner is a connection, the connection flags,
|
||||
and the target are reported (frontend, proxy or server). When the owner is a
|
||||
listener, the listener's state and its frontend are reported. There is no
|
||||
point in using this command without a good knowledge of the internals. It's
|
||||
worth noting that the output format may evolve over time so this output must
|
||||
not be parsed by tools designed to be durable. Some internal structure states
|
||||
may look suspicious to the function listing them, in this case the output line
|
||||
will be suffixed with an exclamation mark ('!'). This may help find a starting
|
||||
point when trying to diagnose an incident.
|
||||
its name when known. When the owner is a connection, the connection and
|
||||
flags, and the target are reported (frontend, proxy or server). When the
|
||||
owner is a listener, the listener's state and its frontend are reported.
|
||||
There is no point in using this command without a good knowledge of the
|
||||
internals. It's worth noting that the output format may evolve over time so
|
||||
this output must not be parsed by tools designed to be durable. Some internal
|
||||
structure states may look suspicious to the function listing them, in this
|
||||
case the output line will be suffixed with an exclamation mark ('!'). This
|
||||
may help find a starting point when trying to diagnose an incident.
|
||||
|
||||
show info [typed|json] [desc] [float]
|
||||
Dump info about haproxy status on current process. If "typed" is passed as an
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ enum {
|
|||
ARGC_UBK, /* use_backend message */
|
||||
ARGC_USRV, /* use-server message */
|
||||
ARGC_HERR, /* http-error */
|
||||
ARGC_OT, /* opentracing scope args */
|
||||
ARGC_OPT, /* option directive */
|
||||
ARGC_TCO, /* tcp-request connection expression */
|
||||
ARGC_TSE, /* tcp-request session expression */
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ struct buffer *get_trash_chunk(void);
|
|||
struct buffer *get_large_trash_chunk(void);
|
||||
struct buffer *get_small_trash_chunk(void);
|
||||
struct buffer *get_trash_chunk_sz(size_t size);
|
||||
struct buffer *get_best_trash_chunk(const struct buffer *buf, size_t size);
|
||||
struct buffer *get_larger_trash_chunk(struct buffer *chunk);
|
||||
int init_trash_buffers(int first);
|
||||
|
||||
|
|
@ -172,6 +173,21 @@ static forceinline struct buffer *alloc_trash_chunk_sz(size_t size)
|
|||
else
|
||||
return NULL;
|
||||
}
|
||||
/* Returns a trash chunk accordingly to the requested size and never larger
|
||||
* that the buffer <buf>. So if <buf> is a large buffer,
|
||||
* alloc_trash_chunk_sz() function is called. Otherwise, if the size is
|
||||
* smaller enough, a regular buffer is allocated. If <size> is too big and
|
||||
* <buf> is not a large buffer, NULL is returned.
|
||||
*/
|
||||
static forceinline struct buffer *alloc_best_trash_chunk(const struct buffer *buf, size_t size)
|
||||
{
|
||||
if (pool_head_large_trash && buf->size == pool_head_large_trash->size)
|
||||
return alloc_trash_chunk_sz(size);
|
||||
else if (size <= pool_head_trash->size)
|
||||
return alloc_trash_chunk();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* free a trash chunk allocated by alloc_trash_chunk(). NOP on NULL.
|
||||
|
|
|
|||
|
|
@ -591,4 +591,15 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* Eats all arguments ignoring their types and contents. This is useful
|
||||
* to avoid "foo declared but not used" warnings. A first non-empty arg
|
||||
* is required by the function, but it's inserted by the macro.
|
||||
*/
|
||||
#define __eat_all_args(...) ___eat_all_args(0, __VA_ARGS__)
|
||||
static inline __attribute__((always_inline)) void ___eat_all_args(int ignore, ...)
|
||||
{
|
||||
(void)ignore;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _HAPROXY_COMPILER_H */
|
||||
|
|
|
|||
|
|
@ -734,7 +734,7 @@ static inline struct proxy *conn_get_proxy(const struct connection *conn)
|
|||
if (s)
|
||||
return s->proxy;
|
||||
|
||||
return objt_proxy(conn->target);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* unconditionally retrieves the ssl_sock_ctx for this connection. Prefer using
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue