# Global Lua Extensions

We support users to write Lua extensions to perform some custom functions, which can be triggered by cron or events.

For example, we can query the database every minute for nodes with high cpu and report them to the user's own monitoring system via http requests.

Here is an practical example of how to create a Lua extension.

Screenshot

We create a cron extension with the following Lua code:


local sql = [[
select node_id, avg("system_CPU_percent") from monitor where created > now() - INTERVAL '1 hour' group by node_id limit 1
]]
local res = sql_query(sql, 120, 2000, "log_server")

local params = {
    body = res
}
res = http_query('POST', "http://receive-metrics.openresty.com", params)

output(res)

Then we can click the execute button to see the results immediately.

Screenshot

The execution results of the extension can be seen in the history page.

Screenshot Screenshot

Lua extensions can also be triggered by events. When the specified event occurs, it will trigger the extension to run and the event details will be placed in the Lua variable trigger_event.

Here is an example of printing events.

output(trigger_event)

Screenshot

Click the execute button to see the results immediately. A node offline test event is provided here by default.

Screenshot

# Events

We currently support these events:

# nodes_offline

Triggered when nodes go offline.

{
    "type": "nodes_offline",
    "from": "log-server",
    "message": "Gateway nodes [59] offline",
    "level": "ERROR"
}
# nodes_online

Triggered when nodes go online.

{
    "type": "nodes_online",
    "from": "log-server",
    "message": "Gateway nodes [59] online",
    "level": "WARNING"
}
# release

Triggered when the application is released.

{
    "type": "release",
    "uid": 2,
    "http_app_id": 786
}

# Builtin API

Most of the regular Lua code is supported in the extensions, and we also provide a built-in lua api for writing extensions.

# output

syntax: output(msg)

The output messages will be displayed in the Lua extension histories.

# http_query

syntax: res = http_query(method, url, params, retries)

Send the HTTP request.

  • method The HTTP method, like GET, POST, PUT.
  • path The HTTP url string.
  • retries Number of retries after request failed, default retries is 1.

The params table accepts the following fields:

  • timeout Sets the timeout (in millisecond), default value is 300 seconds.
  • headers A table of request headers.
  • body The request body as a string, or an iterator function (see get_client_body_reader).
  • ssl_verify Verify SSL cert matches hostname

When the request is successful, res will contain the following fields:

  • status The status code.
  • headers A table of headers. Multiple headers with the same field name will be presented as a table of values.
  • body The response body.
# sql_query

Query the admin or log-server database.

syntax: res = sql_query(sql, timeout, limit, destination, retries)

  • sql Query SQL, only select statements are supported.
  • timeout Sets the timeout (in second), default value is 120 seconds.
  • limit Sets the limit of query result sets, default value is 20000.
  • destination Query destination: admin and log-server.
  • retries Number of retries after query failed, default retries is 1.

# More Examples

# Add IP data blocked by the WAF to the application's IP list

This extension queries the database for the IP data blocked by the WAF and adds them to the application's IP list.

Here we need to enable WAF and IP list in the application first.

-- In this example we assume that the application id and IP list id are both 1.
local app_id = "1"
local ip_list_id = "1"

local str_fmt = string.format
local api_put = require "Lua.SchemaDB" .update

-- Get the IP addresses blocked by WAF in the last 24 hours
local sql = [[
SELECT DISTINCT remote_addr as ip
FROM waf_request_tsdb
WHERE action='block'
        AND score >= threshold
        AND created >= now() - interval '24 hours'
        AND app_id='%s'
]]

sql = str_fmt(sql, app_id)
local res = sql_query(sql, 120, 2000, "log_server")
local ip_list = { items = res }

local uri = { "applications", app_id, "ip_list", ip_list_id }
res, err = api_put(uri, ip_list)

if res then
    output("updated ip blacklist sucessfully!")
else
    output("failed to update ip blacklist: " .. tostring(err))
end