Core concepts

Converters

A converter is a built-in function that transforms the value returned by a fetch method.

Using converters Jump to heading

One of the available converters is the lower converter which you can use to make a string lowercase.

In the example below, we get the HTTP request method (e.g. GET or POST) via the method fetch and then use the lower converter to make it lowercase. For example, GET would become get. The http-request capture directive stores this data in the access logs:

haproxy
frontend www
bind :80
http-request capture method,lower len 10
haproxy
frontend www
bind :80
http-request capture method,lower len 10

You can also chain converters one after another. In the next example, the rand fetch returns a random number between 0 and 100. We pass the result to the mul converter to multiply it by 2; Then the sub converter subtracts 5, the add converter adds 3, and the div converter divides it by 2:

haproxy
frontend www
bind :80
http-request add-header X-Random rand(1:100),mul(2),sub(5),add(3),div(2)
haproxy
frontend www
bind :80
http-request add-header X-Random rand(1:100),mul(2),sub(5),add(3),div(2)

when() converter Jump to heading

Available since

  • HAProxy 3.1
  • HAProxy Enterprise 3.1
  • HAProxy ALOHA 17.0

The when() converter enables you to pass data from an input sample preceding the converter, such as debugging information, only when a condition is met, such as an error condition. The when() converter is flexible in terms of the conditions you are able to provide to it, and you can prefix a condition with ! to negate it. You can also specify an ACL to evaluate. The available conditions are:

Condition Description
error Returns true when an error was encountered during stream processing.
forwarded Returns true when the request was forwarded to a backend.
normal Returns true when no error occurred.
processed Returns true when the request was either forwarded to a backend server or processed by an applet.
stopping Returns true if the process is currently stopping.
acl Returns true when the ACL condition evaluates to true. Use this condition like so, specifying the ACL condition and ACL name separated by a comma: when(acl,<acl_name>).

Use when() to log data condtionally Jump to heading

You can provide the when() converter with a condition that tells the load balancer to log debugging information only when there is an error. You can access this debugging information by using the sample fetch fs.debug_str, which returns data from the lower layers of the frontend stream and connection, and by using the sample fetch bs.debug_str for the backend data. Note that using these sample fetches on their own, that is, to log the information on every request, even those without error, may be too verbose. To prevent flooding the logs, it is best to use them with the when() converter so that the debug information will only appear in the logs when there is an error.

Example #1: Conditionally log debug_str Jump to heading

To append extra debugging information to a log message upon error in a frontend, add a log format statement like this to your frontend, using the condition normal and prefix it with ! to negate the condition:

haproxy
log-format "$HAPROXY_HTTP_LOG_FMT dbg={%[fs.debug_str,when(!normal)]}"
haproxy
log-format "$HAPROXY_HTTP_LOG_FMT dbg={%[fs.debug_str,when(!normal)]}"

This says: append the frontend debug to the log message only when the results of the expression are not normal. “Normal” in this case refers to the scenario where no error occurs in processing. When this condition is met, that is, an error occurred, the load balancer will append the contents of the debug string to the log message, for example:

output
text
172.18.0.1:49698 [05/Dec/2024:18:45:41.631] myfrontend webservers/s1 0/0/1/39/40 200 206 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1" dbg={ h1s=0x791735bcf080 h1s.flg=0x14010 .sd.flg=0x50404601 .req.state=MSG_DONE .res.state=MSG_DONE .meth=GET status=200 .sd.flg=0x50404601 .sc.flg=0x00034482 .sc.app=0x791735ae6400 .subs=0 h1c.flg=0x0 .sub=0 .ibuf=0@0+0/0 .obuf=0@0+0/0 .task=0x791735bbe400 .exp=<NEVER> conn.flg=0x80000300}
output
text
172.18.0.1:49698 [05/Dec/2024:18:45:41.631] myfrontend webservers/s1 0/0/1/39/40 200 206 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1" dbg={ h1s=0x791735bcf080 h1s.flg=0x14010 .sd.flg=0x50404601 .req.state=MSG_DONE .res.state=MSG_DONE .meth=GET status=200 .sd.flg=0x50404601 .sc.flg=0x00034482 .sc.app=0x791735ae6400 .subs=0 h1c.flg=0x0 .sub=0 .ibuf=0@0+0/0 .obuf=0@0+0/0 .task=0x791735bbe400 .exp=<NEVER> conn.flg=0x80000300}

If the condition for logging is not met, that is, no error occurred, the load balancer logs a dash (-) in the log message instead.

Example #2: Conditionally log last_entity Jump to heading

You can also identify the entity, that is, the rule or filter, that was either the last evaluated during the stream analysis before an error occurred or that was stuck waiting to continue its processing when an error occured. For this, use the sample fetches last_entity to retrieve the ID of the entity that completed its processing and waiting_entity to retrieve the ID of the entity that was left waiting. Used with the when() converter, this looks like:

haproxy
log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[last_entity,when(error)]
haproxy
log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[last_entity,when(error)]

In this example with the condition for when() set to error, the load balancer will log the entity ID for the entity that was the last to complete its processing.

See also Jump to heading

Do you have any suggestions on how we can improve the content of this page?