Configuration¶
Access to Icinga Web 2¶
When Tornado is installed, NetEye creates an Icinga Web 2 user
neteye-tornado
and an associated Icinga Web 2 role
neteye_tornado_director_apis
, which only gives access to the module
Director, with limited authorizations on the actions that Tornado can
perform.
Warning
These user and permission are required by the backend, for Tornado to call the Director API–and in particular for the authentication and authorization of the Tornado Director Executor to the APIs of the Icinga Director. Therefore neither the user, nor the associated role must be removed from the system.
In case you need it, for example to reconfigure the Tornado Director
Executor, the password for the user neteye-tornado
is stored in the
file /root/.pwd_icingaweb2_neteye_tornado
.
Tornado Carbon Interface Overview¶
In today’s world, the UX has become a key point in successful IT products and NetEye wants it to become one of its strongest features, providing a continuously improved GUI to support the users’s daily activities.
For this purpose, NetEye provides a totally redesigned, modern looking and attractive GUI for Tornado, based on solid design and usability guidelines defined by the Carbon Design System
While the new GUI is developed to completely replace the current UI, it is currently in preview and only some features are supported such as processing tree visualization, event-driven testing and multi-tenancy.
The Graphical User Interface allows you to explore the current configuration of your Tornado Instance.
The GUI can be divided in 3 logical blocks. At the top of the screen we find the toolbar, in this area it is possible to change the tenant and enable the edit mode.
Immediately below we find the most important part: the Processing Tree. All filters and rulesets of the processing tree are shown in hierarchical order. You can navigate the tree by expanding the child nodes of a filter by clicking on the arrow on the left side of the node. When clicking on a node, its details will be shown. In case of a ruleset, the order of the rules defines the sequence of their execution. For changing the order, you can use drag&drop function focusing on a button to the left of the rule name.
The test event window is a panel that can be opened using the icon in the top right corner, which allows you to send test Events. These Events can be created through a dedicated form and are composed by the following four fields:
Event type: the type of the Event, such as trap, sms, email, etc.
Creation time: the Event timestamp defined as an epoch in milliseconds.
Tenant ID: The tenant ID that will be added to the event. Fill this field if there are filters or conditions related to the tenant ID, otherwise just leave it empty.
Enable execution of actions: whether the actions of matching rules have to be executed or skipped.
Payload: the event payload in JSON format.
When a test is executed by clicking the “Run Test” button, the linked Event is sent to Tornado and the outcome of the operation will be reported in the Processing Tree.
Following the yellow line it is possible to see the path that the event has taken. The nodes that have matched the event are distinguishable by a full yellow lightning bolt while those partially matched have an empty bolt.
At this point, a rule can be in one of the following states:
matched
: If a rule matched the Event.stopped
: If a rule matched the Event and then stopped the. execution flow. This happens if thecontinue
flag of the rule is set to false.partially matched
: If the where condition of the Rule was matched but it was not possible to process the required extracted variables.not matched
: If the Rule did not match the Event.
For each rule in the table, the extracted variables and the generated Action payloads are shown. In addition, all these extracted variables are also shown in the Event Test form.
Two other buttons are visible, one for cleaning all the fields of the form and one for cleaning the outcome of the test.
Tornado Processing Tree Editor¶
The Tornado GUI provides an edit mode that allows to modify the configuration of the Tornado rules’ processing tree directly from NetEye’s web interface. Two important principles have been used for the development of the edit mode and must be understood and taken into account when modifying Tornado’s configuration:
Implicit Lock Mode. Only one user at a time can modify the processing tree configuration. This prevents multiple users from changing the configuration simultaneously, which might lead to unwanted results and possibly to Tornado not working correctly due to incomplete or wrong configuration. When a user is editing the configuration, the actual, running configuration is left untouched: it continues to be operative and accepts incoming data to be processed.
Edit Mode. When starting to modify the configuration, Tornado will continue to work with the existing configuration–thanks to the implicit lock mode, while the new changes are saved in a separate draft configuration. The new configuration then must be deployed to become operative.
This mode has other positive side effects: one does not need to complete the changes in one session, but can stop and then continue at a later point; another user can pick up the draft and complete it; in case of a disaster (like e.g., the abrupt end of the HTTPS connection to the GUI) it is possible to resume the draft from the point where it was left.
Warning
Only one draft at a time is allowed; that is, editing of multiple draft is not supported!
When a user enters the edit mode, a new draft is created on the fly if none is present, which will be an exact copy of the running Tornado configuration. If not present in the draft, a root node of type Filter will be automatically added to the draft.
To check for the correctness of a Draft, without impacting the deployed configuration, it is possible to open the test window also while in Edit Mode. The event will be processed using the Draft and the result will be displayed, while keeping the existing configuration running.
You can add a new node in two ways:
by clicking on the “Add” button in the top right corner and then selecting the parent node to which you want to add the new node.
by clicking on the icon with the three dots on each node that from now on we will call overflow menu.
Note
All nodes at the same level are ordered alphabetically
For each node, it is possible to define a name. For a filter, these three more options are available:
description
whether it is active or not
the filter that should match the event. A specific editor is available for the user to create a valid filter or alternatively it is possible to write it via JSON-based syntax, and examples can be found in the various How-tos present in the tornado section of the User Guide.
Moreover, in Edit mode, each node can be deleted by clicking the delete item available in the overflow menu.
Tornado Rule Editor¶
The rules can be managed from the detailed view of the ruleset nodes. By clicking on a rule or on the “Add rule” button, a form to add or edit a rule opens. It is organized in tabs:
Properties tab contains the following fields:
name
description
switch to enable/disable the rule
switch to make the rule continue or stop the execution in case it matches an event
Where editor allows you to specify the condition where the rule should be matched (read more)
With editor allows you to specify the variable to extract from the event payload (read more)
Actions editor allows you to specify the actions to execute when it matches an event (read more)
Import and Export Configuration¶
The Tornado GUI provides multiple ways to import and export the whole configuration or just a subset of it.
Export Configuration¶
You have three possibilities to export Tornado configuration or part of it:
entire configuration: select the root node from the Processing Tree View and click on the export button to download the entire configuration
a node (either a ruleset or a filter): select the node from the Processing Tree View and click on the export button to download the node and its sub-nodes
a single rule: navigate to the rules table, select a rule, and click on the export button
Hint
You can backup and download Tornado configuration by exporting the entire configuration.
Import Configuration¶
You can use the import feature to upload to NetEye a previously downloaded configuration, new custom rules, or even the configuration from another NetEye instance.
When clicking on the import button a popup will appear with the following fields:
Node File: the file containing the configuration
Note
When importing a single rule the field will be labeled as Rule File.
Replace whole configuration?: If selected, the imported configuration will replace the root node and all of its sub-nodes.
Hint
You can restore a previous Tornado configuration by selecting this option.
Parent Node: The parent node where to add the imported configuration, by default it is set to the currently selected node.
Note
When a node or a rule with the same name of an already existing one is imported, the name of the new node/rule will be suffixed with _imported.
Tornado Engine Configuration¶
Structure and Configuration: The Thread Pool Configuration¶
Even if the default configuration should suit most of the use cases, in some particular situations it could be useful to customise the size of the internal queues used by Tornado. Tornado utilizes these queues to process incoming events and to dispatch triggered actions.
Tornado uses a dedicated thread pool per queue; the size of each queue is by default equal to the number of available logical CPUs. Consequently, in case of an action of type script, for example, Tornado will be able to run in parallel at max as many scripts as the number of CPUs.
This default behaviour can be overridden by providing a custom configuration for the thread pools size. This is achieved through the optional tornado_pool_config entry in the tornado.daemon section of the Tornado.toml configuration file.
Example of Thread Pool’s Dynamical Configuration¶
[tornado.daemon]
thread_pool_config = {type = "CPU", factor = 1.0}
In this case, the size of the thread pool will be equal to
(number of available logical CPUs) multiplied by (factor)
rounded to
the smallest integer greater than or equal to a number. If the resulting
value is less than 1, then 1 will be used be default.
For example, if there are 16 available CPUs, then:
{type: "CPU", factor: 0.5}
=> thread pool size is 8{type: "CPU", factor: 2.0}
=> thread pool size is 32
Example of Thread Pool’s Static Configuration¶
[tornado.daemon]
thread_pool_config = {type = "Fixed", size = 20}
In this case, the size of the thread pool is statically fixed at 20. If the provided size is less than 1, then 1 will be used be default.
Structure and Configuration: Retry Strategy Configuration¶
Tornado allows the configuration of a global retry strategy to be applied when the execution of an Action fails.
A retry strategy is composed by:
retry policy: the policy that defines whether an action execution should be retried after an execution failure;
backoff policy: the policy that defines the sleep time between retries.
Valid values for the retry policy are:
{type = "MaxRetries", retries = 5}
=> A predefined maximum amount of retry attempts. This is the default value with a retries set to 20.{type = "None"}
=> No retries are performed.{type = "Infinite"}
=> The operation will be retried an infinite number of times. This setting must be used with extreme caution as it could fill the entire memory buffer preventing Tornado from processing incoming events.
Valid values for the backoff policy are:
{type = "Exponential", ms = 1000, multiplier = 2 }
: It increases the back off period for each retry attempt in a given set using the exponential function. The period to sleep on the first backoff is thems
; themultiplier
is instead used to calculate the next backoff interval from the last. This is the default configuration.{type = "None"}
: No sleep time between retries. This is the default value.{type = "Fixed", ms = 1000 }
: A fixed amount of milliseconds to sleep between each retry attempt.{type = "Variable", ms = [1000, 5000, 10000]}
: The amount of milliseconds between two consecutive retry attempts.The time to wait after ‘i’ retries is specified in the vector at position ‘i’.
If the number of retries is bigger than the vector length, then the last value in the vector is used. For example:
ms = [111,222,333]
-> It waits 111 ms after the first failure, 222 ms after the second failure and then 333 ms for all following failures.
Example of a complete Retry Strategy configuration¶
[tornado.daemon]
retry_strategy.retry_policy = {type = "Infinite"}
retry_strategy.backoff_policy = {type = "Variable", ms = [1000, 5000, 10000]}
When not provided explicitly, the following default Retry Strategy is used:
[tornado.daemon]
retry_strategy.retry_policy = {type = "MaxRetries", retries = 20}
retry_strategy.backoff_policy = {type = "Exponential", ms = 1000, multiplier = 2 }
Structure and Configuration: Enable the TCP event socket¶
Enabling the TCP event socket server allows Tornado to receive events through a direct TCP connection.
The TCP event socket configuration entries are available in the
tornado.toml
file. Example of the TCP socket section the
tornado.toml
file:
# Whether to enable the TCP listener
event_tcp_socket_enabled = true
# The IP address where we will listen for incoming events.
event_socket_ip = "127.0.0.1"
#The port where we will listen for incoming events.
event_socket_port = 4747
In this case, Tornado will listen for incoming events on the TCP address
127.0.0.1:4747
.
Structure and Configuration: Enable the Nats connection¶
Enabling the Nats connection allows Tornado to receive events published on a Nats cluster.
The Nats configuration entries are available in the tornado.toml
file. Example of the Nats section the tornado.toml
file:
# Whether to connect to the NATS server
nats_enabled = true
# The addresses of the NATS server
nats.client.addresses = ["127.0.0.1:4222"]
# The NATS Subject where tornado will subscribe and listen for incoming events
nats.subject = "tornado.events"
In this case, Tornado will connect to the “test-cluster” and listen for incoming events published on “tornado.events” subject. Also, since nats.client.auth.type is not provided, Tornado will not authenticate to the NATS server.
At the moment, when the nats_enabled
entry is set to true
, it is
required that the Nats server is available at Tornado startup.
Structure of a Filter¶
A Filter contains these properties:
filter name
: A string value representing a unique Filter identifier. It can be composed only of letters, numbers and the “_” (underscore) character; it corresponds to the filename, stripped from its .json extension.description
: A string providing a high-level description of the filter.active
: A boolean value; iffalse
, the Filter’s children will be ignored.filter
: A boolean operator that, when applied to an event, returnstrue
orfalse
. This operator determines whether an Event matches the Filter; consequently, it determines whether an Event will be processed by the Filter’s inner nodes.
Implicit Filters
If a Filter is omitted, Tornado will automatically infer an implicit filter that passes through all Events. This feature allows for less boiler-plate code when a Filter is only required to blindly forward all Events to the internal rule sets.
For example, if filter_one.json is a Filter that allows all Events to pass through, then this processing tree:
root
|- node_0
| |- ...
|- node_1
| |- ...
\- filter_one.json
is equivalent to:
root
|- node_0
| |- ...
\- node_1
|- ...
Note that in the second tree we removed the filter_one.json file. In this case, Tornado will automatically generate an implicit Filter for the root node, and all incoming Events will be dispatched to each child node.
Filters available by default
The Tornado Processing Tree provides some out of the box Filters, which match all, and only, the Events originated by some given tenant. For more information on tenants in NetEye visit the dedicated page.
These Filters are created at the top level of the Processing Tree, in such a way that it is possible to set up tenant-specific Tornado pipelines.
Given for example a tenant named acme
, the matching condition of the
Filter for the acme
tenant will be defined as:
{
"type": "equals",
"first": "${event.metadata.tenant_id}",
"second": "acme"
}
Keep in mind that these Filters must never be deleted nor modified, because they will be automatically re-created.
Note
NetEye generates one Filter for each tenant, including the default master
tenant.
Structure of a Rule¶
A Rule is composed of a set of properties, constraints and actions.
Basic Properties
rule name
: A string value representing a unique rule identifier. It can be composed only of alphabetical characters, numbers and the “_” (underscore) character.description
: A string value providing a high-level description of the rule.continue
: A boolean value indicating whether to proceed with the event matching process if the current rule matches.active
: A boolean value; iffalse
, the rule is ignored.
When the configuration is read from the file system, the rule name is automatically inferred from the filename by removing the extension and everything that precedes the first ‘_’ (underscore) symbol. For example:
0001_rule_one.json -> 0001 determines the execution order, “rule_one” is the rule name
0010_rule_two.json -> 0010 determines the execution order, “rule_two” is the rule name
Constraints
The constraint section contains the tests that determine whether or not an event matches the rule. There are two types of constraints:
WHERE: A set of operators that when applied to an event returns
true
orfalse
WITH: A set of regular expressions that extract values from an Event and associate them with named variables
An event matches a rule if and only if the WHERE clause evaluates to
true
and all regular expressions in the WITH clause return non-empty
values.
The following operators are available in the WHERE clause. Check also the examples in the dedicated section to see how to use them, including example rules.
‘contains’: Evaluates whether the first argument contains the second one. It can be applied to strings, arrays, and maps. The operator can also be called with the alias ‘contain’.
‘containsIgnoreCase’: Evaluates whether the first argument contains, in a case-insensitive way, the string passed as second argument. This operator can also be called with the alias ‘containIgnoreCase’.
‘equals’: Compares any two values (including, but not limited to, arrays, maps) and returns whether or not they are equal. An alias for this operator is ‘equal’.
‘equalsIgnoreCase’: Compares two strings and returns whether or not they are equal in a case-insensitive way. The operator can also be called with the alias ‘equalIgnoreCase’.
‘ge’: Compares two values and returns whether the first value is greater than or equal to the second one. If one or both of the values do not exist, it returns
false
.‘gt’: Compares two values and returns whether the first value is greater than the second one. If one or both of the values do not exist, it returns
false
.‘le’: Compares two values and returns whether the first value is less than or equal to the second one. If one or both of the values do not exist, it returns
false
.‘lt’: Compares two values and returns whether the first value is less than the second one. If one or both of the values do not exist, it returns
false
.‘ne’: This is the negation of the ‘equals’ operator. Compares two values and returns whether or not they are different. It can also be called with the aliases ‘notEquals’ and ‘notEqual’.
‘regex’: Evaluates whether a field of an event matches a given regular expression.
‘AND’: Receives an array of operator clauses and returns
true
if and only if all of them evaluate totrue
.‘OR’: Receives an array of operator clauses and returns
true
if at least one of the operators evaluates totrue
.‘NOT’: Receives one operator clause and returns
true
if the operator clause evaluates tofalse
, while it returnsfalse
if the operator clause evaluates totrue
.
We use the Rust Regex library (see its github project home page ) to evaluate regular expressions provided by the WITH clause and by the regex operator. You can also refer to its dedicated documentation for details about its features and limitations.
Actions
An Action is an operation triggered when an Event matches a Rule.
Reading Event Fields
A Rule can access Event fields through the “${” and “}” delimiters. To do so, the following conventions are defined:
The ‘.’ (dot) char is used to access inner fields.
Keys containing dots are escaped with leading and trailing double quotes.
Double quote chars are not accepted inside a key.
For example, given the incoming event:
{
"type": "trap",
"created_ms": 1554130814854,
"payload":{
"protocol": "UDP",
"oids": {
"key.with.dots": "38:10:38:30.98"
}
}
}
The rule can access the event’s fields as follows:
${event.type}
: Returns trap${event.payload.protocol}
: Returns UDP${event.payload.oids."key.with.dots"}
: Returns 38:10:38:30.98${event.payload}
: Returns the entire payload${event}
: Returns the entire event${event.metadata.key}
: Returns the value of the key key from the metadata. The metadata is a special field of an event created by Tornado to store additional information where needed (e.g. the tenant_id, etc.)
String interpolation
An action payload can also contain text with placeholders that Tornado will replace at runtime. The values to be used for the substitution are extracted from the incoming Events following the conventions mentioned in the previous section; for example, using that Event definition, this string in the action payload:
Received a ${event.type} with protocol ${event.payload.protocol}
produces:
*Received a trap with protocol UDP*
Note
Only values of type String, Number, Boolean and null are valid. Consequently, the interpolation will fail, and the action will not be executed, if the value associated with the placeholder extracted from the Event is an Array, a Map, or undefined.
Example of Filters¶
Using a Filter to Create Independent Pipelines
We can use Filters to organize coherent set of Rules into isolated pipelines.
In this example we will see how to create two independent pipelines, one that receives only events with type ‘email’, and the other that receives only those with type ‘trapd’.
Our configuration directory will look like this::
rules.d
|- email
| |- ruleset
| | |- ... (all rules about emails here)
| \- only_email_filter.json
|- trapd
| |- ruleset
| | |- ... (all rules about trapds here)
| \- only_trapd_filter.json
\- filter_all.json
This processing tree has a root Filter filter_all that matches all events. We have also defined two inner Filters; the first, only_email_filter, only matches events of type ‘email’. The other, only_trapd_filter, matches just events of type ‘trap’.
Therefore, with this configuration, the rules defined in email/ruleset receive only email events, while those in trapd/ruleset receive only trapd events.
This configuration can be further simplified by removing the filter_all.json file:
rules.d
|- email
| |- ruleset
| | |- ... (all rules about emails here)
| \- only_email_filter.json
\- trapd
|- ruleset
| |- ... (all rules about trapds here)
\- only_trapd_filter.json
In this case, in fact, Tornado will generate an implicit Filter for the root node and the runtime behavior will not change.
Below is the content of our JSON Filter files.
Content of filter_all.json (if provided):
{
"description": "This filter allows every event",
"active": true
}
Content of only_email_filter.json:
{
"description": "This filter allows events of type 'email'",
"active": true,
"filter": {
"type": "equals",
"first": "${event.type}",
"second": "email"
}
}
Content of only_trapd_filter.json:
{
"description": "This filter allows events of type 'trapd'",
"active": true,
"filter": {
"type": "equals",
"first": "${event.type}",
"second": "trapd"
}
}
Multi Tenancy Roles Configuration¶
If your NetEye installation is tenant aware, roles associated to each user must be configured to limit their access only the processing trees they are allowed to.
In the NetEye roles (tornadocarbon/tenant_id
restriction.
Hint
You can find the list of available Tenant IDs by reading the directory
names in /etc/neteye-satellites.d/
. You can use this command:
neteye# basename -a $(ls -d /etc/neteye-satellite.d/*/)
Tornado Collectors¶
JMESPath Collector¶
This is a Collector that receives an input in JSON format and allows the creation of Events using the JMESPath JSON query language. It is used only internally by Tornado and should be never called directly.
Email Collector¶
When the Email Collector receives a valid MIME email message as input, it parses it and produces a Tornado Event with the extracted data.
For example, given the following input:
Subject: This is a test email
Content-Type: multipart/alternative; boundary=foobar
Date: Sun, 02 Oct 2016 07:06:22 -0700 (PDT)
--foobar
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
This is the plaintext version, in utf-8. Proof by Euro: =E2=82=AC
--foobar
Content-Type: text/html
Content-Transfer-Encoding: base64
PGh0bWw+PGJvZHk+VGhpcyBpcyB0aGUgPGI+SFRNTDwvYj4gdmVyc2lvbiwgaW4g
dXMtYXNjaWkuIFByb29mIGJ5IEV1cm86ICZldXJvOzwvYm9keT48L2h0bWw+Cg==
--foobar--
it will generate this Event:
{
"type": "email",
"created_ms": 1554130814854,
"payload": {
"date": 1475417182,
"subject": "This is a test email",
"to": "",
"from": "",
"cc": "",
"body": "This is the plaintext version, in utf-8. Proof by Euro: €",
"attachments": []
}
}
If there are attachments, then attachments that are text files will be in plain text, otherwise they will be encoded in base64.
For example, passing this email with attachments:
From: "Francesco" <francesco@example.com>
Subject: Test for Mail Collector - with attachments
To: "Benjamin" <benjamin@example.com>,
francesco <francesco@example.com>
Cc: thomas@example.com, francesco@example.com
Date: Sun, 02 Oct 2016 07:06:22 -0700 (PDT)
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------E5401F4DD68F2F7A872C2A83"
Content-Language: en-US
This is a multi-part message in MIME format.
--------------E5401F4DD68F2F7A872C2A83
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit
<html>Test for Mail Collector with attachments</html>
--------------E5401F4DD68F2F7A872C2A83
Content-Type: application/pdf;
name="sample.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="sample.pdf"
JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KT0YNCg==
--------------E5401F4DD68F2F7A872C2A83
Content-Type: text/plain; charset=UTF-8;
name="sample.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="sample.txt"
dHh0IGZpbGUgY29udGV4dCBmb3IgZW1haWwgY29sbGVjdG9yCjEyMzQ1Njc4OTA5ODc2NTQz
MjEK
--------------E5401F4DD68F2F7A872C2A83--
will generate this Event:
{
"type": "email",
"created_ms": 1554130814854,
"payload": {
"date": 1475417182,
"subject": "Test for Mail Collector - with attachments",
"to": "\"Benjamin\" <benjamin@example.com>, francesco <francesco@example.com>",
"from": "\"Francesco\" <francesco@example.com>",
"cc": "thomas@example.com, francesco@example.com",
"body": "<html>Test for Mail Collector with attachments</html>",
"attachments": [
{
"filename": "sample.pdf",
"mime_type": "application/pdf",
"encoding": "base64",
"content": "JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KT0YNCg=="
},
{
"filename": "sample.txt",
"mime_type": "text/plain",
"encoding": "plaintext",
"content": "txt file context for email Collector\n1234567890987654321\n"
}
]
}
}
Within the Tornado Event, the filename and mime_type properties of each attachment are the values extracted from the incoming email.
Instead, the encoding property refers to the content encoding in the Event itself, which is one of two types:
plaintext: The content is included in plain text
base64: The content is encoded in base64
Tornado Email Collector (Executable)¶
The Email Collector Executable binary, built on actix, is an executable that generates Tornado Events from MIME email inputs.
On startup, it creates a UDS socket where it listens for incoming email messages. Each email published on the socket is processed by the embedded Tornado email Collector to produce Tornado Events which are, finally, forwarded to the Tornado Engine’s TCP address.
The UDS socket is created with the same user and group as the tornado_email_collector process, with permissions set to 770 (read, write and execute for both the user and the group).
Each client that needs to write an email message to the socket should close the connection as soon as it completes its action. In fact, the Email Collector Executable will not even start processing that email until it receives an EOF signal. Only one email per connection is allowed.
Tornado Rsyslog Collector (executable)¶
The rsyslog Collector binary is an executable that generates Tornado Events from rsyslog inputs.
This Collector is meant to be integrated with rsyslog’s own logging through the omprog module. Consequently, it is never started manually, but instead will be started, and managed, directly by rsyslog itself.
Here is an example rsyslog configuration template that pipes logs to
the rsyslog-collector (the parameters are explained in the configuration file
tornado_rsyslog_collector/conf/rsyslog_collector.toml
) only logs with severity higher
than warning:
module(load="omprog")
action(type="omprog"
binary="/usr/lib64/tornado/bin/tornado_rsyslog_collector --logger=warn")
An example of a fully instantiated startup setup is:
module(load="omprog")
action(type="omprog"
binary="/usr/lib64/tornado/bin/tornado_rsyslog_collector --config-dir=/tornado-rsyslog-collector/config --tornado-event-socket-ip=192.168.123.12 --tornado-event-socket-port=4747")
Note that all parameters for the binary option must be on the same line. You will need to place this configuration in a file in your rsyslog directory, for instance:
/etc/rsyslog.d/tornado.conf
In this example the Collector will:
Reads the configuration from the /tornado-rsyslog-collector/config directory
Write outgoing Events to the TCP socket at tornado_server_ip:4747
The Collector will need to be run in parallel with the Tornado Engine before any events will be processed, for example:
/opt/tornado/bin/tornado --tornado-event-socket-ip=tornado_server_ip
Under this configuration, rsyslog is in charge of starting the Collector when needed and piping the incoming logs to it. As the last stage, the Tornado Events generated by the Collector are forwarded to the Tornado Engine’s TCP socket.
This integration strategy is the best option for supporting high performance given massive amounts of log data.
Because the Collector expects the input to be in JSON format, rsyslog should be pre-configured to properly pipe its inputs in this form.
Tornado Webhook Collector (executable)¶
The Webhook Collector is a standalone HTTP server built on actix-web that listens for REST calls from a generic webhook, generates Tornado Events from the webhook JSON body, and sends them to the Tornado Engine.
On startup, it creates a dedicated REST endpoint for each configured webhook. Calls received by an endpoint are processed by the embedded JMESPath Collector that uses them to produce Tornado Events. In the final step, the Events are forwarded to the Tornado Engine through the configured connection type.
For each webhook, you must provide three values in order to successfully create an endpoint:
id: The webhook identifier. This will determine the path of the endpoint; it must be unique per webhook.
token: A security token that the webhook issuer has to include in the URL as part of the query string (see the example at the bottom of this page for details). If the token provided by the issuer is missing or does not match the one owned by the Collector, then the call will be rejected and an HTTP 401 code (UNAUTHORIZED) will be returned.
collector_config: The transformation logic that converts a webhook JSON object into a Tornado Event. It consists of a JMESPath Collector configuration as described in its specific documentation.
Tornado Nats JSON Collector (executable)¶
The Nats JSON Collector is a standalone Collector that listens for JSON messages on Nats topics, generates Tornado Events, and sends them to the Tornado Engine.
The Nats JSON Collector executable is built on actix.
On startup, it connects to a set of topics on a Nats server. Calls received are then processed by the embedded jmespath Collector that uses them to produce Tornado Events. In the final step, the Events are forwarded to the Tornado Engine through the configured connection type.
For each topic, you must provide two values in order to successfully configure them:
nats_topics: A list of Nats topics to which the Collector will subscribe.
collector_config: (Optional) The transformation logic that converts a JSON object received from Nats into a Tornado Event. It consists of a JMESPath Collector configuration as described in its specific documentation.
Tornado Icinga 2 Collector (executable)¶
The Icinga 2 Collector subscribes to the Icinga 2 API event streams, generates Tornado Events from the Icinga 2 Events, and publishes them on the Tornado Engine TCP address.
The Icinga 2 Collector executable is built on actix.
On startup, it connects to an existing Icinga 2 Server API and subscribes to user defined Event Streams. Each Icinga 2 Event published on the stream, is processed by the embedded jmespath Collector that uses them to produce Tornado Events which are, finally, forwarded to the Tornado Engine’s TCP address.
More than one stream subscription can be defined. For each stream, you must provide two values in order to successfully create a subscription:
stream: the stream configuration composed of:
types: An array of Icinga 2 Event types;
queue: A unique queue name used by Icinga 2 to identify the stream;
filter: An optional Event Stream filter. Additional information about the filter can be found in the official documentation.
collector_config: The transformation logic that converts an Icinga 2 Event into a Tornado Event. It consists of a JMESPath Collector configuration as described in its specific documentation.
Note
Based on the Icinga 2 Event Streams documentation, multiple HTTP clients can use the same queue name as long as they use the same event types and filter.
SNMP Trap Daemon Collectors¶
The _snmptrapd_collector_s of this package are embedded Perl trap handlers for Net-SNMP’s snmptrapd. When registered as a subroutine in the Net-SNMP snmptrapd process, they receives snmptrap-specific inputs, transforms them into Tornado Events, and forwards them to the Tornado Engine.
There are two Collector implementations, the first one sends Events directly to the Tornado TCP socket and the second one forwards them to a NATS server.
The implementations rely on the Perl NetSNMP::TrapReceiver package. You can refer to its documentation for generic configuration examples and usage advice.
The _snmptrapd_collector_s receive snmptrapd messages, parse them, generate Tornado Events and, finally, sends them to Tornado using their specific communication channel.
The received messages are kept in an in-memory non-persistent buffer
that makes the application resilient to crashes or temporary
unavailability of the communication channel. When the connection to the
channel is restored, all messages in the buffer will be sent. When the
buffer is full, the Collectors will start discarding old messages. The
buffer max size is set to 10000
messages.
Consider a snmptrapd message that contains the following information:
PDU INFO:
version 1
errorstatus 0
community public
receivedfrom UDP: [127.0.1.1]:41543->[127.0.2.2]:162
transactionid 1
errorindex 0
messageid 0
requestid 414568963
notificationtype TRAP
VARBINDS:
iso.3.6.1.2.1.1.3.0 type=67 value=Timeticks: (1166403) 3:14:24.03
iso.3.6.1.6.3.1.1.4.1.0 type=6 value=OID: iso.3.6.1.4.1.8072.2.3.0.1
iso.3.6.1.4.1.8072.2.3.2.1 type=2 value=INTEGER: 123456
The Collector will produce this Tornado Event:
{
"type":"snmptrapd",
"created_ms":"1553765890000",
"payload":{
"protocol":"UDP",
"src_ip":"127.0.1.1",
"src_port":"41543",
"dest_ip":"127.0.2.2",
"PDUInfo":{
"version":"1",
"errorstatus":"0",
"community":"public",
"receivedfrom":"UDP: [127.0.1.1]:41543->[127.0.2.2]:162",
"transactionid":"1",
"errorindex":"0",
"messageid":"0",
"requestid":"414568963",
"notificationtype":"TRAP"
},
"oids":{
"iso.3.6.1.2.1.1.3.0":"67",
"iso.3.6.1.6.3.1.1.4.1.0":"6",
"iso.3.6.1.4.1.8072.2.3.2.1":"2"
}
}
}
The structure of the generated Event is not configurable.
Tornado Executors¶
Director Executor¶
The Director Executor is an application that extracts data from a Tornado Action and prepares it to be sent to the Icinga Director REST API; it expects a Tornado Action to include the following elements in its payload:
An action_name: The Director action to perform.
An action_payload (optional): The payload of the Director action.
An icinga2_live_creation (optional): Boolean value, which determines whether to create the specified Icinga Object also in Icinga 2.
Valid values for action_name are:
create_host: creates an object of type
host
in the Directorcreate_service: creates an object of type
service
in the Director
The action_payload should contain at least all mandatory parameters expected by the Icinga Director REST API for the type of object you want to create.
An example of a valid Tornado Action is:
{
"id": "director",
"payload": {
"action_name": "create_host",
"action_payload": {
"object_type": "object",
"object_name": "my_host_name",
"address": "127.0.0.1",
"check_command": "hostalive",
"vars": {
"location": "Bolzano"
}
},
"icinga2_live_creation": true
}
}
Logger Executor¶
An Executor that logs received Actions: it simply outputs the whole Action body to the standard log at the info level.
Script Executor¶
An Executor that runs custom shell scripts on a Unix-like system. To be correctly processed by this Executor, an Action should provide two entries in its payload: the path to a script on the local filesystem of the Executor process, and all the arguments to be passed to the script itself.
The script path is identified by the payload key script. It is important to verify that the Executor has both read and execute rights at that path.
The script arguments are identified by the payload key args; if present, they are passed as command line arguments when the script is executed.
An example of a valid Action is:
{
"id": "script",
"payload" : {
"script": "./usr/share/scripts/my_script.sh",
"args": [
"tornado",
"rust"
]
}
}
In this case the Executor will launch the script my_script.sh with the arguments “tornado” and “rust”. Consequently, the resulting command will be:
neteye# ./usr/share/scripts/my_script.sh tornado rust
Other Ways of Passing Arguments
There are different ways to pass the arguments for a script:
Passing arguments as a String:
{ "id": "script", "payload" : { "script": "./usr/share/scripts/my_script.sh", "args": "arg_one arg_two -a --something else" } }
If args is a String, the entire String is appended as a single argument to the script. In this case the resulting command will be:
neteye# ./usr/share/scripts/my_script.sh "arg_one arg_two -a --something else"
Passing arguments in an array:
{ "id": "script", "payload" : { "script": "./usr/share/scripts/my_script.sh", "args": [ "--arg_one tornado", "arg_two", true, 100 ] } }
Here the argument’s array elements are passed as four arguments to the script in the exact order they are declared. In this case the resulting command will be:
neteye# ./usr/share/scripts/my_script.sh "--arg_one tornado" arg_two true 100
Passing arguments in a map:
{ "id": "script", "payload" : { "script": "./usr/share/scripts/my_script.sh", "args": { "arg_one": "tornado", "arg_two": "rust" } } }
When arguments are passed in a map, each entry in the map is considered to be a (option key, option value) pair. Each pair is passed to the script using the default style to pass options to a Unix executable which is –key followed by the value. Consequently, the resulting command will be:
neteye# ./usr/share/scripts/my_script.sh --arg_one tornado --arg_two rust
Please note that ordering is not guaranteed to be preserved in this case, so the resulting command line could also be:
neteye# ./usr/share/scripts/my_script.sh --arg_two rust --arg_one tornado
Thus if the order of the arguments matters, you should pass them using either the string- or the array-based approach.
Passing no arguments:
{ "id": "script", "payload" : { "script": "./usr/share/scripts/my_script.sh" } }
Since arguments are not mandatory, they can be omitted. In this case the resulting command will simply be:
neteye# ./usr/share/scripts/my_script.sh
Monitoring Executor¶
Warning
The monitoring Executor is deprecated, please use the Smart Monitoring Check Result Executor, which is equivalent but it is easier to configure.
The Monitoring Executor permits to perform Icinga
process-check-results
also in the case that the Icinga object for
which you want to perform the process-check-result
does not yet
exist.
This is done by means of executing the action process-check-result
with the Icinga Executor, and by executing the actions create_host
or create_service
with the Director Executor, in case the
underlying Icinga objects do not yet exist in Icinga.
Warning
The Monitoring Executor requires the live-creation feature of the Icinga Director to be exposed in the REST API. If this is not the case, the actions of this Executor will always fail in case the Icinga Objects are not already present in Icinga 2.
This Executor expects a Tornado Action to include the following elements in its payload:
An action_name: The Monitoring action to perform.
A process_check_result_payload: The payload for the Icinga 2
process-check-result
action.A host_creation_payload: The payload which will be sent to the Icinga Director REST API for the host creation.
A service_creation_payload: The payload which will be sent to the Icinga Director REST API for the service creation (mandatory only in case action_name is
create_and_or_process_service_passive_check_result
).
Valid values for action_name are:
create_and_or_process_host_passive_check_result: sets the
passive check result
for ahost
, and, if necessary, it also creates the host.create_and_or_process_service_passive_check_result: sets the
passive check result
for aservice
, and, if necessary, it also creates the service.
The process_check_result_payload should contain at least all
mandatory parameters expected by the Icinga API to perform the action.
The object on which you want to set the passive check result
must be
specified with the field host
in case of action
create_and_or_process_host_passive_check_result, and service
in
case of action create_and_or_process_service_passive_check_result
(e.g. specifying a set of objects on which to apply the
passive check result
with the parameter filter
is not valid)
The host_creation_payload should contain at least all mandatory parameters expected by the Icinga Director REST API to perform the creation of a host.
The servie_creation_payload should contain at least all mandatory parameters expected by the Icinga Director REST API to perform the creation of a service.
An example of a valid Tornado Action is:
{
"id": "monitoring",
"payload": {
"action_name": "create_and_or_process_service_passive_check_result",
"process_check_result_payload": {
"exit_status": "2",
"plugin_output": "Output message",
"service": "myhost!myservice",
"type": "Service"
},
"host_creation_payload": {
"object_type": "Object",
"object_name": "myhost",
"address": "127.0.0.1",
"check_command": "hostalive",
"vars": {
"location": "Rome"
}
},
"service_creation_payload": {
"object_type": "Object",
"host": "myhost",
"object_name": "myservice",
"check_command": "ping"
}
}
}
The flowchart shown in Flowchart of Monitoring Executor. helps to understand the behaviour of the Monitoring Executor in relation to Icinga 2 and Icinga Director REST APIs.
Foreach Executor¶
An Executor that loops through a set of data and executes a list of actions for each entry; it extracts all values from an array of elements and injects each value to a list of action under the item key.
There are two mandatory configuration entries in its payload:
target: the array of elements
actions: the array of action to execute
For example, given this rule definition:
{
"name": "do_something_foreach_value",
"description": "This uses a foreach loop",
"continue": true,
"active": true,
"constraint": {
"WITH": {}
},
"actions": [
{
"id": "foreach",
"payload": {
"target": "${event.payload.values}",
"actions": [
{
"id": "logger",
"payload": {
"source": "${event.payload.source}",
"value": "the value is ${item}"
}
},
{
"id": "archive",
"payload": {
"event": "${event}",
"item_value": "${item}"
}
}
]
}
}
]
}
When an event with this payload is received:
{
"type": "some_event",
"created_ms": 123456,
"payload":{
"values": ["ONE", "TWO", "THREE"],
"source": "host_01"
}
}
Then the target of the foreach action is the array
["ONE", "TWO", "THREE"]
; consequently, each one of the two inner
actions is executed three times; the first time with item = “ONE”,
then with item = “TWO” and, finally, with item = “THREE”.
Archive Executor¶
The Archive Executor writes the Events from the received Actions to a file.
Requirements and Limitations
The archive Executor can only write to locally mounted file systems. In addition, it needs read and write permissions on the folders and files specified in its configuration.
Configuration
The archive Executor has the following configuration options:
file_cache_size: The number of file descriptors to be cached. You can improve overall performance by keeping files from being continuously opened and closed at each write.
file_cache_ttl_secs: The Time To Live of a file descriptor. When this time reaches 0, the descriptor will be removed from the cache.
base_path: A directory on the file system where all logs are written. Based on their type, rule Actions received from the Matcher can be logged in subdirectories of the base_path. However, the archive Executor will only allow files to be written inside this folder.
default_path: A default path where all Actions that do not specify an
archive_type
in the payload are loggedpaths: A set of mappings from an archive_type to an
archive_path
, which is a subpath relative to the base_path. The archive_path can contain variables, specified by the syntax${parameter_name}
, which are replaced at runtime by the values in the Action’s payload.
The archive path serves to decouple the type from the actual subpath, allowing you to write Action rules without worrying about having to modify them if you later change the directory structure or destination paths.
As an example of how an archive_path is computed, suppose we have the following configuration:
base_path = "/tmp"
default_path = "/default/out.log"
file_cache_size = 10
file_cache_ttl_secs = 1
[paths]
"type_one" = "/dir_one/file.log"
"type_two" = "/dir_two/${hostname}/file.log"
and these three incoming actions:
action_one:
{ "id": "archive", "payload": { "archive_type": "type_one", "event": "__the_incoming_event__" } }
action_two:
{ "id": "archive", "payload": { "archive_type": "type_two", "hostname": "net-test", "event": "__the_incoming_event__" } }
action_three:
{ "id": "archive", "payload": { "event": "__the_incoming_event__" } }
then:
action_one will be archived in /tmp/dir_one/file.log
action_two will be archived in /tmp/dir_two/net-test/file.log
action_three will be archived in /tmp/default/out.log
The archive Executor expects an Action to include the following elements in the payload:
An event: The Event to be archived should be included in the payload under the key
event
An archive type (optional): The archive type is specified in the payload under the key
archive_type
When an archive_type is not specified, the default_path is used (as in
action_three). Otherwise, the Executor will use the archive_path in the
paths
configuration corresponding to the archive_type
key
(action_one and action_two).
When an archive_type is specified but there is no corresponding key in
the mappings under the paths
configuration, or it is not possible to
resolve all path parameters, then the Event will not be archived.
Instead, the archiver will return an error.
The Event from the payload is written into the log file in JSON format, one event per line.
Elasticsearch Executor¶
The Elasticsearch Executor is a functionality that extracts data from a Tornado Action and sends it to Elasticsearch.
The Executor expects a Tornado Action that includes the following elements in its payload:
An endpoint : The Elasticsearch endpoint which Tornado will call to create the Elasticsearch document
An index : The name of the Elasticsearch index in which the document will be created
An data: The content of the document that will be sent to Elasticsearch
(optional) An auth: a method of authentication, see below
An example of a valid Tornado Action is a json document like this:
{
"id": "elasticsearch",
"payload": {
"endpoint": "http://localhost:9200",
"index": "tornado-example",
"data": {
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
}
}
The Elasticsearch Executor will create a new document in the specified Elasticsearch index for each action executed; also the specified index will be created if it does not already exist.
In the above json document, no authentication is specified, therefore
the default authentication method created during the Executor creation
is used. This method is saved in a tornado configuration file
(elasticsearch_executor.toml
) and can be overridden for each Tornado
Action, as described in the next section.
Elasticsearch authentication
When the Elasticsearch Executor is created, a default authentication method can be specified and will be used to authenticate to Elasticsearch, if not differently specified by the action. On the contrary, if a default method is not defined at creation time, then each action that does not specify an authentication method will fail.
To use a specific authentication method the action should include the
auth
field with either of the following authentication types:
None or PemCertificatePath, like shown in the following
examples.
None: the client connects to Elasticsearch without authentication
Example:
{ "id": "elasticsearch", "payload": { "index": "tornado-example", "endpoint": "http://localhost:9200", "data": { "user": "myuser" }, "auth": { "type": "None" } } }
PemCertificatePath: the client connects to Elasticsearch using the PEM certificates read from the local file system. When this method is used, the following information must be provided:
certificate_path: path to the public certificate accepted by Elasticsearch
private_key_path: path to the corresponding private key
ca_certificate_path: path to CA certificate needed to verify the identity of the Elasticsearch server
Example:
{ "id": "elasticsearch", "payload": { "index": "tornado-example", "endpoint": "http://localhost:9200", "data": { "user": "myuser" }, "auth": { "type": "PemCertificatePath", "certificate_path": "/path/to/tornado/conf/certs/tornado.crt.pem", "private_key_path": "/path/to/tornado/conf/certs/private/tornado.key.pem", "ca_certificate_path": "/path/to/tornado/conf/certs/root-ca.crt" } } }
Icinga 2 Executor¶
The Icinga 2 Executor extracts data from a Tornado Action and prepares it to be sent to the Icinga 2 API.
In more details, this Executor expects a Tornado Action to include the following elements in its payload:
An icinga2_action_name: The Icinga 2 action to perform
An icinga2_action_payload (optional): The parameters of the Icinga 2 action
The icinga2_action_name should match one of the existing Icinga 2 actions.
The icinga2_action_payload should contain at least all mandatory parameters expected by the specific Icinga 2 action.
An example of a valid Tornado Action is:
{
"id": "icinga2",
"payload": {
"icinga2_action_name": "process-check-result",
"icinga2_action_payload": {
"exit_status": "${event.payload.exit_status}",
"plugin_output": "${event.payload.plugin_output}",
"filter": "host.name==\"example.localdomain\"",
"type": "Host"
}
}
}
Smart Monitoring Check Result Executor¶
The Smart Monitoring Check Result Executor allows to perform an Icinga
process-check-results
in case the Icinga 2 object for which you
want to carry out that action does not exist. Moreover, this Executor also ensures
that no outdated process-check-result
will overwrite newer check results
already present in Icinga 2.
In case the underlying Icinga 2 objects do not exist in Icinga 2,
the actions create_host
or create_service
are
performed via the Director Executor.
Warning
The Smart Monitoring Check Result Executor requires the live-creation feature of the Icinga Director to be exposed in the REST API. If this is not the case, the actions of this Executor will always fail in case the Icinga Objects are not already present in Icinga 2.
Note however, that the Icinga agent cannot be created live using Smart Monitoring Executor because it always requires a defined endpoint in the configuration which is not possible since the Icinga API doesn’t support live-creation of an endpoint.
To ensure that outdated check results are not processed, the action
process-check-result
is carried out by the
Icinga 2 Executor with the parameters execution_start
and execution_end
inherited by the Action definition or set equal
to the value of the created_ms
property of the originating Tornado
Event. Section
Discarded Check Results
explains how the Executor handles these cases.
The Tornado Action sent to this Executor shall include the following elements in its payload:
A check_result: The basic data to build the Icinga 2
process-check-result
action payloadA host: The data to build the payload which will be sent to the Icinga Director REST API for the host creation
A service: The data to build the payload which will be sent to the Icinga Director REST API for the service creation (optional)
The check_result should contain all mandatory parameters expected by the Icinga API except the following ones that are automatically filled by the Executor:
host
service
type
The host and service should contain all mandatory parameters
expected by the Icinga Director REST API to perform the creation of a
host and/or a service, except object_type
.
The service key is optional. When it is included in the action
payload, the Executor will invoke the process-check-results
call to
set the status of a service; otherwise, it will set the one of a host.
An example of a valid Tornado Action is to set the status of the service
myhost|myservice
:
{
"id": "smart_monitoring_check_result",
"payload": {
"check_result": {
"exit_status": "2",
"plugin_output": "Output message"
},
"host": {
"object_name": "myhost",
"address": "127.0.0.1",
"check_command": "hostalive",
"vars": {
"location": "Rome"
}
},
"service": {
"object_name": "myservice",
"check_command": "ping"
}
}
}
By simply removing the service
key, the same action will set the
status of the host myhost
:
{
"id": "smart_monitoring_check_result",
"payload": {
"check_result": {
"exit_status": "2",
"plugin_output": "Output message"
},
"host": {
"object_name": "myhost",
"address": "127.0.0.1",
"check_command": "hostalive",
"vars": {
"location": "Rome"
}
}
}
}
The flowchart shown in Flowchart of Monitoring Executor. helps to understand the behaviour of the Monitoring Executor in relation to Icinga 2 and Icinga Director REST APIs.
Discarded Check Results
Some process-check-results
may be discarded by Icinga 2 if more recent
check results already exist for the target object.
In this situation the Executor does not retry the Action, but
simply logs an error containing the tag DISCARDED_PROCESS_CHECK_RESULT
in the configured Tornado Logger.
The log message showing a discarded process-check-result
will be similar
to the following excerpt, enclosed in an ActionExecutionError
:
SmartMonitoringExecutor - Process check result action failed with error ActionExecutionError {
message: "Icinga2Executor - Icinga2 API returned an unrecoverable error. Response status: 500 Internal Server Error.
Response body: {\"results\":[{\"code\":409.0,\"status\":\"Newer check result already present. Check result for 'my-host!my-service' was discarded.\"}]}",
can_retry: false,
code: None,
data: {
"payload":{"execution_end":1651054222.0,"execution_start":1651054222.0,"exit_status":0,"plugin_output":"Some process check result","service":"my-host!my-service","type":"Service"},
"tags":["DISCARDED_PROCESS_CHECK_RESULT"],
"url":"https://icinga2-master.neteyelocal:5665/v1/actions/process-check-result",
"method":"POST"
}
}.
Common Logger¶
The tornado_common_logger crate contains the logger configuration for the Tornado components.
The configuration is based on three entries:
level: A list of comma separated logger verbosity levels. Valid values for a level are: trace, debug, info, warn, and error. If only one level is provided, this is used as global logger level. Otherwise, a list of per package levels can be used. E.g.:
level=info
: the global logger level is set to infolevel=warn,tornado=debug
: the global logger level is set to warn, the tornado package logger level is set to debug
stdout-output: A boolean value that determines whether the Logger should print to standard output. Valid values are true and false.
file-output-path: An optional string that defines a file path in the file system. If provided, the Logger will append any output to that file.
The configuration subsection logger.tracing_elastic_apm allows to configure the connection to Elastic APM for the tracing functionality. The following entries can be configured:
apm_output: Whether the Logger data should be sent to the Elastic APM Server. Valid values are true and false.
apm_server_url: The URL of the Elastic APM Server.
apm_server_api_credentials.id: (Optional) the ID of the API Key for authenticating to the Elastic APM server.
apm_server_api_credentials.key: (Optional) the key of the API Key for authenticating to the Elastic APM server. If apm_server_api_credentials.id and apm_server_api_credentials.key are not provided, they will be read from the file <config_dir>/apm_server_api_credentials.json
exporter.max_queue_size: (Optional) The maximum queue size of the tracing batch exporter to buffer spans for delayed processing. Defaults to
65536
.exporter.scheduled_delay_ms: The delay interval in milliseconds between two consecutive exports of batches. Defaults to
5000
(5 seconds).exporter.max_export_batch_size: The maximum number of spans to export in a single batch. Defaults to
512
.exporter.max_export_timeout_ms: The time (in milliseconds) for which the export can run before it is cancelled. Defaults to
30000
(30 seconds).
In Tornado executables, the Logger configuration is usually defined with command line parameters managed by structopt. In that case, the default level is set to warn, stdout-output is disabled and the file-output-path is empty.
For example:
./tornado --level=info --stdout-output --file-output-path=/tornado/log