Guidelines for logs
The objective of these guidelines is to guarantee uniformity between the logs from all services that run in a single project, regardless of whether they are custom or core.
When configuring a custom service you can select a Log Parser. Each log parser supports a specific logging format, but they all share the same purpose: allowing log collection and processing from your Kubernetes cluster to the ELK Stack.
Mia-Platform Console provides a series of log parsers that can be selected from the Console and will be used to properly parse and process your service logs:
mia-json: processes all logs as JSON, parsing all the keys to store them;
mia-nginx: a custom Nginx parser;
mia-plain: a plain text parser;
- Not Collected: prevents all logs from the Kubernetes Pod to be collected and processed.
JSON Logging format
When a service uses the label with value
mia-json, all of its key/values are collected and stored in Elastic. However, if you want to perform queries on the logs using Kibana, you'll need to create indexes.
A set of preconfigured indexes come with each Console project. These indexes run on a specific set of keys. The following document provides a list of available log keys (following the Elastic Common Schema specifications) that can be used. Some of these log keys are indexed.
Each project has a set of preconfigured indexes. If you need custom indexes, please refer to your Mia-Platform representative.
Here you can find some guidelines, drawn from guidelines and best practices suggested by Elastic, which should be followed when application logs are generated:
- Field names must be in camelCase;
- Field names must not contain special characters;
- Field names should be singular or plural according to the content of the field;
- Whenever it makes sense, prefer nesting your fields in structured objects;
- Avoid using abbreviations in field names.
When creating a new server, consider offload the setup of the logging facilities to Mia-Platform service libraries:
- For Node.js services, you can use lc39 and custom-plugin-lib;
- For Go services, you can use glogger.
Use the appropriate logging level
It is important to always use the correct log level. Each level has a value expressed in tenths: the higher is the number, the higher the severity of the log. To choose which is the appropriate level, you should rely on the following criteria:
|10||Trace the operations flow of the application (do not use in production).|
|20||Report information that may be useful in troubleshooting (do not use in production).|
|30||In cases where the service has to give information about the branch of code in execution.|
|40||In cases of recoverable error, the service can continue to process the request.|
|50||In cases of not recoverable error and error for which the processing of the request (but not the service) must be interrupted.|
|60||In cases of unexpected and not recoverable error, and as a result of which the service must stop its execution.|
It is important to put in logs the right information that can be used to track operations, highlight problems, and allow troubleshooting.
Avoid, under any circumstance, to insert any private or sensitive value that can lead to privacy-related issues or incidents.
In each log, the following fields have to be always present:
|String||Indexed||The text message specific for each log.|
|String||Indexed||Traces the flow of each request. It is taken from the platform headers|
|Number||Indexed||Marks in Unix timestamp the moment when the log was generated.|
|Number||Indexed||Identifies the severity level of the log.|
reqId field is extremely useful to trace operations following a single request, and is considered mandatory since usually services expose APIs.
However, if the concept of request tracing is not applicable, you can ignore it.
Each service exposing APIs must necessarily generate the logs shown in the table below, specifying the following fields in addition to the mandatory field specified above.
If the service is not REST but takes its inputs from another source, the same criteria have to be applied.
trace log when the event processing starts, and a
info log when the event ends.
The final log should contain as much useful information as possible.
ECS Field Definition
The following are examples taken from ECS documentation. None of the fields are mandatory, however it is important to use standard keys, whenever applicable.
If you want to create error logs, we recommend the following structure.
When an error log has been generated, the passed object must necessarily have the key
whose value has to be an object of the form specified by ECS for the Error Fields,
which are shown in the table below:
|Core||Indexed||Error code describing the error.|
|Core||Indexed||Unique identifier for the error.|
|Extended||Indexed||The stack trace of the error in plain text.|
|Extended||Indexed||Multi-fields stack trace of the error in plain text.|
|Extended||Indexed||The type of the error, for example the class name of the exception. Example: |
|Core||Indexed||Hostname of the host. It normally contains what the |
|Core||Indexed||Name of the host. It can contain what |
|Extended||Indexed||Seconds the host has been up. Example: |
|Extended||Indexed||Size in bytes of the request body. Example: |
|Extended||Indexed||Total size in bytes of the request (body and headers). Example: |
|Extended||Indexed||HTTP request method. The field value must be normalized to lowercase for querying. See the documentation section "Implementing ECS". Example: |
|Extended||Indexed||Referrer for this HTTP request. Example: |
|Extended||Not indexed||Name of the device. Example: |
|Extended||Not indexed||Name of the user agent. Example: |
|Extended||Indexed||Unparsed user_agent string. example: |
|Extended||Indexed||Multi-fields unparsed user_agent string.|
|Extended||Not indexed||Version of the user agent. example: |
|Extended||Indexed||Size in bytes of the response body. example: |
|Extended||Indexed||Total size in bytes of the response (body and headers). example: |
|Extended||Indexed||HTTP response status code. example: |
|Extended||Not indexed||HTTP version. example: |
|Extended||Indexed||Domain of the URL, such as www.mia-platform.eu. In some cases a URL may refer to an IP and/or port directly, without a domain name. In this case, the IP address would go to the |
|Extended||Indexed||Portion of the URL after the |
|Extended||Indexed||If full URLs are important to your use case, they should be stored in |
|Extended||Indexed||Multi-fields. Example: |
|Extended||Indexed||Path of the request, such as |
|Extended||Indexed||Port of the request, such as 443. Example: |
|Extended||Indexed||The query field describes the query string of the request, such as "q=elasticsearch". The |
|Extended||Indexed||Scheme of the request, such as "https". Note: The |