| ----------------------------------------- |
| 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. |
| |
| The OT filter was primarily tested with the Jaeger tracer, while configurations |
| for both Datadog and Zipkin tracers were also set in the test directory. |
| |
| 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%). |