> For the complete documentation index, see [llms.txt](https://docs.xplatform.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xplatform.com/talon/operating-applications/analysis-and-troubleshooting/trace-logging.md).

# Trace Logging

Configure trace output destinations, handlers, and logging frameworks for Talon microservices.

## Overview

Salient aspects of Talon trace and logging are as follows:

* Talon modules use *Tracer* objects to output trace
* *Tracer* objects are associated with *Logger* objects that do the actual logging of trace messages
* *Logger* objects can be either:
  * Native *Logger* objects
    * Native *Loggers* are bound to one or more *Handler* objects
    * Native *Logger* and *Handler* objects are thin wrappers around *java.util.logging Logger* and *Handler* objects respectively
    * *Handler* objects are responsible for the trace formatting and output and can be daisy chained or forked for sophisticated targeting of trace output
  * SLF4J *Logger* objects
    * SLF4J *Logger* objects are the Logger objects obtained from the concrete logging implementation bound to SLF4J at runtime
* By default, the platform trace uses native logging. The `nv.trace.useslf4j` environment variable/system property tells the Talon trace and logging subsystem to use SLF4J loggers
* When using the native platform logging, platform-specific mechanisms are used to configure trace levels and targets. When using SLF4J, the mechanisms native to the concrete implementation bound to SLF4J are used to specify trace levels and targets

Logger and handler objects are named entities in the X logging system. Each tracer is bound to a logger by name. In the native logging system, the logger is a native logger which is, in turn, bound to one or more handlers by name. When using SLF4J, the logger name refers to an appropriate SLF4J logger.

Each package in the system has a default logger with its name derived from the package name. For example, the `com.neeve.aep` package has a logger named `nv.aep`, the `com.neeve.ods` package has a logger named `nv.ods`, the `com.neeve.sma` package has a logger named `nv.sma`, and so on and so forth. By default, tracers used by different classes in a package use the default logger. However, the classes are free to create tracers that use different loggers. For example, in the AEP package, although the AEP engine uses the default `nv.aep` logger for general trace output, it uses the `nv.aep.msg` logger to control message trace. Refer to the module specific documentation on what special loggers are created by the different modules.

## Native Logging

### Controlling Logger Trace Levels

One controls the trace level for a logger using the **\<logger name>.trace=\<logger level>** environment variable or system property. For example, `nv.sma.trace=debug` sets the trace level of the `nv.sma` logger to debug, i.e. all trace objects in the `com.neeve.sma` package bound to the `nv.sma` logger will inherit this trace level. The trace level for a logger can alternatively be set via the **\<logger name>.logger.level=\<logger level>** environment variable or system property.

The following are the permissible logger levels (case insignificant) listed in increasing order of granularity/verbosity:

* *OFF*
* SEVERE
* WARNING
* INFO
* CONFIG
* DIAGNOSE
* VERBOSE
* DEBUG
* *ALL*

The "ALL" (log everything) and "OFF" (log nothing) levels may only be used to configure trace logger levels. They may not be used with Tracer.log(...) statements in code.

{% hint style="info" %}
**Note**: X supports the use of '.' and '\_' interchangeably in environment variables and system properties. For example, using `nv_aep_trace=debug` can be used wherever `nv.aep.trace=debug` is used and vice versa.
{% endhint %}

### Handler Types

Handlers are classified by type. Broadly speaking, each handler type determines the destination for trace output. X currently supports the following handler types:

#### Standard Out

Handlers of this type direct trace output to standard out.

#### Standard Error

Handlers of this type direct trace output to standard error.

#### File

Handlers of this type direct trace output to a set of rolling files (number and size of files are controllable).

#### Memory

Handlers of this type direct output to memory with a level based trigger that flushes buffered trace to another named handler which could be on any type.

#### Network

Handlers of this type direct output to a network receiver. The IP address and port on which the network receiver is listening is configurable. X comes packaged with a default network listener.

### Handler Descriptors

X supports the ability to describe handlers via string-based handler descriptors. The format of a descriptor is as follows:

```
[handler type]://prop=name&prop=name&...&prop=name
```

The handler type specifies the type of handler to create. The supported handler type, per the above, are '*stdout*', '*stderr*', *'file', 'memory'* and *'network'*. The handler type defines the properties that can be specified in the remaining portion of the descriptor. For example, to specify a file handler that uses a maximum of 5 rolling log files each of a maximum size of 100000 bytes, with names starting with test.log, use the following descriptor:

```
file://filename=test.log&size=10000&count=5
```

#### Type Specific Descriptor Properties

The following are the various properties supported for the different handler types.

**Standard Out**

*Descriptor format:* `stdout://`

* No specific properties

**Standard Error**

*Descriptor format:* `stderr://`

* No specific properties

**Memory**

*Descriptor format:* `memory://.&<properties>`

* `target`
  * Specifies the name of the handler to which messages held by the memory handler will be pushed when a trace message with a level equal to or greater than `pushLevel` is received by the handler. This property has no default and so is mandatory.
* `size`
  * Specifies the maximum number of log records to buffer in memory. Default=1000
* `pushLevel`
  * See `target`. Default=SEVERE

**File**

*Descriptor format:* `file://.&<properties>`

* `filename`
  * Specifies the pattern of the file to which trace messages will be logged. The file handler logs messages cycling through a set of log files named by suffixing the value of this property with the file number - successively older files are named by adding 0, 1, 2 etc to the base file name specified by this property.
* `limit`
  * Specifies, in bytes, the maximum size of a log file. When a log file exceeds this size, messages are rolled onto a new file. Default=100Mb
* `count`
  * Specifies the maximum number of log files to cycle through. Default=10
* `append`
  * Specifies whether the log is to be opened in append mode or not. Default=true.

**Network**

*Descriptor format:* `network://.&<properties>`

* `host`
  * Specifies the name of the host to which the handler will establish a TCP connection. This property does not have a default and is therefore mandatory.
* `port`
  * Specifies the TCP port to which the handler will establish the TCP connection. This property does not have a default and is therefore mandatory.

In addition, the following properties apply to handlers of all types:

* `level`
  * Specifies the level to be associated with the handler. Trace messages with a level less than the handler level are suppressed. Default=FINEST

### Associating Handlers with Loggers

#### The 'default' Handler

One controls the destination of trace output by associating the appropriate handler with the right logger. By default, unless otherwise specified (as we will see below), each logger is associated with the 'default' handler. The default handler is a handler that is created up front by the X logging subsystem and is described as follows:

```
stdout://level=finest
```

To change the default handler, specify the descriptor of the default handler you would like to use via the `nv.logger.defaulthandler` environment variable or system property.

#### Specifying non-default logger handlers

One can name handlers in the X logging system through environment variables/system properties. The following is the format of environment variables/system properties used to created handlers:

```
nv.logger.handler.<handler name>=<handler descriptor>
```

For example, the following environment variable/system property causes a handler named 'filer' to be created that rolls through 2 files with the default maximum size and a base name as 'filer':

```
nv.logger.handler.filer=file://filename=filer&count=2
```

#### Linking Handlers to Loggers

Once defined, this handler can now be linked to any logger by name. The following environment variables/system properties link loggers to handlers.

```
<logger name>.handlers=<comma separated handler names>
```

For example, to associate the above 'filer' handler to the `nv.aep.msg` logger (the one that controls message trace), set the following environment variable/system property.

```
nv.aep.msg.logger.handlers=filer
```

The above will cause the `nv.aep.msg` logger to be linked to the filer handler thus redirecting all message trace output to the 'filer' set of rolling files.

## Configuration Examples

### DDL Trace Configuration

To configure trace levels and handlers in DDL:

```xml
<model xmlns="http://www.neeveresearch.com/schema/x-ddl"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <env>
    <!-- Configuration of the application tracer and logger -->
    <application>
      <trace>debug</trace>
      <logger>
        <handlers>applog,stdout</handlers>
      </logger>
    </application>

    <!-- Handler Configuration -->
    <nv>
      <logger>
        <handler>
          <stdout>stdout://</stdout>
          <applog>file://filename=/tmp/app.log&amp;count=2</applog>
        </handler>
      </logger>
    </nv>
  </env>
</model>
```

### Using System Properties

The same configuration can be specified using system properties:

```bash
-Dapplication.trace=debug
-Dapplication.logger.handlers=applog,stdout
-Dnv.logger.handler.stdout=stdout://
-Dnv.logger.handler.applog=file://filename=/tmp/app.log&count=2
```

## SLF4J Logging

### Logger Configuration

When using SLF4J logging, the platform does not control the configuration of the loggers. Loggers are configured using the mechanisms native to the concrete logging implementation bound to SLF4J at runtime. Refer to the documentation of the concrete logging implementation for details on how loggers are configured.

### Trace Level Mapping

When using SLF4J logging, the platform *Trace* objects inherit their trace levels from the SLF4J logger. In other words, trace levels set via system properties will be overridden by the SLF4J logger trace levels. The following is how the SLF4J trace levels map to the Talon trace levels.

| **SLF4J Trace Level** | **Platform Trace Level** |
| --------------------- | ------------------------ |
| ERROR                 | SEVERE                   |
| WARN                  | WARNING                  |
| INFO                  | CONFIG                   |
| DEBUG                 | VERBOSE                  |
| TRACE                 | DEBUG                    |

### Limitations

The following limitations exist when using SLF4J logging:

1. Talon tracers do not use SLF4J marker objects during logging.
2. Talon tracers inherit their trace levels from the SLF4J loggers at startup. When using concrete logging implementations such as Logback that can dynamically update their log levels at runtime, the updated log levels will not take effect with the platform tracers. Other logger configuration, though, will take effect in real time since they are not snapshotted by the platform tracers.

## Related Topics

* [Logging Trace](/talon/developing-applications/authoring-user-code/trace-logging/logging-trace.md) - Create tracers and emit trace from your application code
* [XVM Heartbeats](/talon/operating-applications/monitoring/xvm-heartbeats.md) - Heartbeat trace output configuration
* [Engine Stats](/talon/operating-applications/monitoring/engine-statistics.md) - Engine statistics tracing

## Next Steps

1. Determine whether to use native logging or SLF4J integration
2. Configure trace levels for relevant loggers
3. Set up appropriate handlers for trace output
4. Test trace configuration with different log levels
