Lua: Useful scripts and examples

list of scripts:

  • print_r: a debug tool running like the foumous PHP's print_r.
  • stats: HAProxy statistics collector and aggregator.

The following script are not perfect, all the suggestion or patches are welcome, even for the (nonexistent) documentation.

print_r

print_r.lua

This file tries to copy the famous PHP's "print_r" function. It displays recursively the content of a structur. It is useful for debug. this script is universal, it not requires HAProxy for running. You can find below, an example of the displayed result.

You can embed this tool with the Lua line require("print_r"). For displaying a variable, you can write print_r(my_var). The variable will be displayed on stdout with ANSI colors.

The prototype is:

print_r(<var> [, <color (boolean)> [, <display (function)>]])
<var> is the displayed variable
<color> if true, use ANSi color. if false, displays flat text.
<display> The prototype of this function is function(msg). this function is called each time that we want

A call example:

require("print_r")
print_r(core, false, function(msg) io.stdout:write(msg) end)

stats

stats.lua

This script get the CSV stats of all the declared HAProxy instances, aggregates it, and redistributes it. The redistribution can be internal or external with HTTP and the CSV format.

The stats are checked and aggregated each second.

Configuration example:

require("stats")
stats.add("me1",  "socket:///var/lib/haproxy/stats_1")
stats.add("me2",  "socket:///var/lib/haproxy/stats_2")
stats.add("me3",  "socket:///var/lib/haproxy/stats_3")
stats.add("you1", "http:///my-peer:8101/stats;csv")
stats.add("you2", "http:///my-peer:8102/stats;csv")
stats.add("you3", "http:///my-peer:8103/stats;csv")

The location of other HAProxy with you want to aggregate data are defined with an url. The url can design an http access or a socket access. The HTTP access supports basic authentication, and must embed the ";csv" extension. stats.add url format:

http://[<login>:<password>@]<ip>[:<port>]/<path>
socket://<path>

The stats aggregation can be redistributed using http protocol. The output format is the same than te original CSV format, except an added column called "agg" which contains the list of aggregated instances.

The aggregation engine uses 4 aggregation method:

  • first: Only the first value of the first is returned. Its used with names and types.
  • add: The sum of the values of each HAProxy stats is returned. It is used with "max", "limits", "counters" and "rates".
  • cat: Concatenate values od each HAProxy stats and separes values by a "/". It is used with "status", "pid", ...
  • avg: Returns the averages of the value. It is used with mean response time.

These aggregation methods are defined in an array called "stats.values". This array can be modified in the init Lua file. The index of tha array is the value nameand the aggregation method is the column 6. For example:

stats.values["ereq"][6] = "add"

You can enable this HTTP.CSV reditribution service with a frontend using the service "lua.stats" like this:

listen applet_stats
   bind *:10001
   mode http
   http-request use-service lua.stats

You can use the aggregation results for internal process using the sample fetch called lua.stats. It takes as parameter a string describing the required counter. the composition of this parameter is explained below:

["f" | "b"] ":" <fe/be name> ":" <metrix>
["f" | "b"] ":" <fe/be name> ":" [ <server> | <listener> ] ":" <metrix>

If you want to use the "bytes in" for making a deny decision, you can write this configuration:

tcp-request connection reject if { lua.stats(f:applet_tcp:bin) gt 10000 }