Structured logging dictionary
=============================
This page describes the common entries of the Structured Logging component. Currently these backends are supported:
* The ``default`` text based backend
* The ``systemd-journal`` backend
* The ``json`` backend
The ``default`` backend
-----------------------
The default backend uses a text representation of the key-value pairs.
A line is constructed by appending all key-value pairs as ``key="value"``, separated by spaces.
The output is written by passing the resulting text line to the standard error stream and also to ``syslog`` if ``--disable-syslog`` was not passed on the command-line.
An example line looks like this::
msg="Raised send buffer size" subsystem="setup" level="0" prio="Info" ts="2025-12-29T17:16:17+0100" frontend.address="127.0.0.1:8053" network.send_buffer_size="4194304
- Key names are not quoted.
- Values are quoted with double quotes.
- If a value contains a double quote, it is escaped with a backslash.
- Backslashes in the value are escaped by prepending a backslash.
The following keys are always present:
+-------------+------------------+--------------------------------------+---------------------------------------+
| **Key** | **Type** | **Example** | **Remarks** |
+-------------+------------------+--------------------------------------+---------------------------------------+
|``msg`` |``string`` | ``"Raised send buffer size"`` |Value is the same for all instances of |
| | | |this log entry, together with |
| | | |``subsystem`` it uniquely identifies |
| | | |the log message. |
+-------------+------------------+--------------------------------------+---------------------------------------+
|``subsystem``|``string`` |``"setup"`` |Uniquely identifies the log |
| | | |entry together with the value of |
| | | |``msg``. |
+-------------+------------------+--------------------------------------+---------------------------------------+
| ``level`` |``number`` |``"0"`` |The detail level of the log entry. |
| | | |Not actively used currently. |
+-------------+------------------+--------------------------------------+---------------------------------------+
| ``prio`` |``enum`` |``"Notice"`` |One of ``Alert=1``, ``Critical=2``, |
| | | |``Error=3``, ``Warning=4``, |
| | | |``Notice=5``, ``Info=6``, |
| | | |``Debug=7``. |
+-------------+------------------+--------------------------------------+---------------------------------------+
| ``ts`` |``number`` |``"1697614303.039"`` |Number of seconds since the Unix epoch,|
| | | |including fractional part. |
+-------------+------------------+--------------------------------------+---------------------------------------+
A log entry can also have zero or more additional key-value pairs. We tried to adhere to OpenTelemetry's
`general attributes `_ when possible, or more specific
ones like for example `dns attributes `_ or
`http attributes `_ for DNS over HTTPS.
Common keys are:
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| **Key** | **Type** |**Example** | **Remarks** |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``error`` |``string`` |``"No such file or directory"`` |An error cause. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``address`` |``ip address:port`` |``"[::]:5301"`` |An IP: port combination. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``addresses`` |``list of subnets`` |``"127.0.0.0/8 ::ffff:0:0/96"`` |A list of subnets, space separated. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``client.address`` |``ip address:port`` |``"[2001:db8::1]:1234"`` |Address of the DNS client. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``backend.address`` |``ip address:port`` |``"[2001:db8::2]:53"`` |Address of the downstream backend. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``backend.name`` |``string`` |``"my-backend"`` |Name of the downstream backend, if any. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``backend.protocol`` |``string`` |``"DoT"`` |Protocol used to send DNS queries to the downstream backend. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``destination.address`` |``ip address:port`` |``"192.0.2.42:53"`` |Destination address of a packet (may be more specific than ``frontend.address``, or be the next hop and differ from ``client.address`` when the proxy protocol is being used, for example).|
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.question.class`` |``unsigned integer`` |``1`` |The DNS query class. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.question.id`` |``unsigned integer`` |``42`` |The DNS query ID. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.question.name`` |``DNS name`` |``"example.com"`` |The DNS query name. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.question.real_time_sec`` |``integer`` |``1767095038`` |The time this query was received, as the number of seconds since EPOCH. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.question.real_time_nsec`` |``integer`` |``23`` |Additional nano-seconds for ``dns.question.real_time_sec``, for extra precision. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.question.size`` |``unsigned integer`` |``42`` |Size of the DNS query packet, in bytes. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.question.type`` |``unsigned integer`` |``28`` |The DNS query type. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.response.class`` |``unsigned integer`` |``1`` |The DNS response class. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.response.id`` |``unsigned integer`` |``42`` |The DNS response ID. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.response.latency_us`` |``float`` |``180.63`` |The latency between the query and the response, in microseconds. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.response.name`` |``DNS name`` |``"example.com"`` |The DNS response name. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.response.rcode`` |``DNS Response Code``|``"No Error"`` |DNS response code |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.response.size`` |``unsigned integer`` |``42`` |Size of the DNS response packet, in bytes. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``dns.response.type`` |``unsigned integer`` |``28`` |The DNS response type. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``frontend.address`` |``ip address:port`` |``"[::]:53"`` |Address this frontend is listening on. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``frontend.protocol`` |``string`` |``"DoQ"`` |Protocol this frontend is accepting DNS queries over. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``http.method`` |``string`` |``"GET"`` |HTTP/2 query method for DoH. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``http.path`` |``string`` |``"/dns-query"`` |HTTP/2 query path for DoH. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``http.response.status_code`` |``HTTP status code`` |``"200"`` |HTTP/2 response code for DoH. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``http.stream_id`` |``HTTP stream ID`` |``"4242"`` |HTTP/2 stream identifier for DoH. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``network.local.address`` |``string`` |``"192.0.2.2:53"`` |Local address and port DNSdist is listening on (webserver, console, ...). |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``network.peer.address`` |``string`` |``"192.0.2.2:53"`` |Peer address of the network connection (may differ from ``client.address`` when the proxy protocol is used, for example). |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``path`` |``filesystem path`` |``"tmp/api-dir/apizones"`` | |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``pool`` |``string`` |``"my-pool"`` |Downstream backends pool name. |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|``protocol`` |``string`` |``"udp"`` | |
+--------------------------------+---------------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
The ``systemd-journal`` backend
-------------------------------
The ``systemd-journal`` structured logging backend uses mostly the same keys and values as the default backend, with the exceptions:
- keys are capitalized as required for ``systemd-journal``.
- ``msg`` is translated to ``MESSAGE``.
- ``prio`` is translated to ``PRIORITY``.
- ``ts`` is translated to ``TIMESTAMP``.
- If the original key is in a list of keys special to ``systemd-journal``, it is capitalized and prepended by ``PDNS_``.
The list of special keys is: message, message_id, priority, code_file, code_line, code_func, errno, invocation_id, user_invocation_id, syslog_facility, syslog_identifier, syslog_pid, syslog_timestamp, syslog_raw, documentation, tid, unit, user_unit, object_pid.
To use this logging backend, add the ``--structured-logging-backend systemd-journal`` to the command line in the systemd unit file.
To query the log, use a command similar to::
# journalctl -r -n 1 -o json-pretty -u dnsdist.service
The ``json`` backend
--------------------
The ``json`` structured logging backend uses the same keys and values as the default backend.
An example of a log object::
{"level": "0", "msg": "Adding TCP worker thread to handle TCP connections from clients", "priority": "6", "ts": "2025-12-29T17:20:20+0100"}
All values are represented as strings.
The JSON log objects are written to the standard error stream.