# Logging

### KLog Class Overview

* **Built on Standard Java Logging**\
  Utilizes the built-in java.util.logging framework, part of Java SE. No additional external libraries, such as Apache Log4j, are required.
* **High Performance**\
  Capable of logging over 10,000 lines per second on a MacBook Pro when using the FileHandler and KLogLineFormatter.
* **Simplified Logging**\
  Streamlines logging with straightforward methods for debug, error, and info messages.
* **Static Methods**\
  All methods are static, eliminating the need for instantiation.
* **Flexible Handlers and Formatters**\
  Includes handlers and formatters for generating log output in various formats: tabular text, CSV, XML, JSON, and YAML. Supports sending logs to JDBC-compliant databases or routing error logs to any SMTP server.
* **Enhanced Log Details**\
  Provides precise timestamps and exact code locations in formatted log outputs.
* **Configuration and Runtime Adjustments**\
  Logging is enabled via the *KLog.properties* configuration file, which must be located in the current directory or set thru the startup parameter *KLogPropertyFile*. Logging levels can dynamically be adjusted and log entries may be filtered at runtime.

{% hint style="info" %}
The Java utility package uses KLog internally to assist with problem determination. Setting the log level to *FINEST* in the *KLog.properties* file enables detailed debugging mode, providing comprehensive insights during code execution.
{% endhint %}

### Logging Handlers

In addition to the standard logging handlers for console and file output, KLog provides the additional classes:

* **KLogJDBCHandler**: Write each log entry to any JDBC compliant database
* **KLogSMTPHandler**: Send error log entries (FATAL logging level) to any SMTP server

### Logging Formatters

The log information (timestamp, logging level, code location and message) can be formatted with the additional formatter classes:

* **KLogCSVFormatter**: Format each log entry as a one-line CSV string
* **KLogJSONFormatter**: Format each log entry as a multi-line JSON string
* **KLogLineFormatter**: Format each log entry as a one-line tabular string
* **KLogXMLFormatter**: Format each log entry as a multi-line XML string
* **KLogYAMLFormatter**: Format each log entry as a multi-line YAML string

### Sample Properties Files

The logging properties file enables and configures the logging framework used by all `KLog` methods. Simply download, edit and and place it in the current directory of your application.

{% file src="<https://1523050323-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnLy540wu2J4F0Txdp4tM%2Fuploads%2Fdl67i6mRb00WqZ7FAnbN%2FKLog.properties.minimal.zip?alt=media&token=17b872ad-b70e-48dd-9f29-212ecb15977c>" %}
Recommended minimal logging (errors only)
{% endfile %}

{% file src="<https://1523050323-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnLy540wu2J4F0Txdp4tM%2Fuploads%2F7X4nuuPTM001vNu1GaDj%2FKLog.properties.sample.zip?alt=media&token=ee952677-1468-409f-a0e7-dcdada820e81>" %}
Full logging functionality
{% endfile %}

### Special Properties

<details>

<summary>Startup System Properties</summary>

| Command Line Option | Default                         | Purpose                                                     |
| ------------------- | ------------------------------- | ----------------------------------------------------------- |
| -DKLogPropertyFile  | "KLog.properties"               | Path and file name of KLog properties file                  |
| -DKLogLevel         | Set by the KLog properties file | Override KLog level to Info, Error,  Debug or Off           |
| -DKLogInclude       | Set by the KLog properties file | Limit log entries to specified RegEx match, e.g. “password“ |
| -DKLogExclude       | Set by the KLog properties file | Exclude log entries matching RegEx, e.g. “started\|ended“   |

Examples

```bash
% java -DKLogInclude=“Started|Ended“ YourApp
```

<pre class="language-bash"><code class="lang-bash"><strong>% java -DKLogPropertyFile=/etc/KLog.properties -DKLogLevel=Debug YourApp
</strong></code></pre>

{% hint style="warning" %}
Please note that all command line options are case sensitive.
{% endhint %}

</details>

<details>

<summary>Common KLog Properties</summary>

| Property Key             | Value                     | Notes                                                      |
| ------------------------ | ------------------------- | ---------------------------------------------------------- |
| ch.k43.util.KLog.level   | FINEST, INFO, SEVERE, OFF | Corresponds to KLog logging levels Debug, Info, Error, Off |
| ch.k43.util.KLog.exclude | RegEx Pattern             | Exclude matching log entries, e.g. “password“              |
| ch.k43.util.KLog.include | RexEx Pattern             | Include only matching log entries, e.g. “started\|ended“   |

</details>

<details>

<summary>KLog.properties for KLogJDBCHandler</summary>

| Property Key                              | Value                | Notes                                       |
| ----------------------------------------- | -------------------- | ------------------------------------------- |
| ch.k43.util.KLogJDBCHandler.jdbc.driver   | JDBC Driver Class    | Java class name, e.g. org.h2.Driver         |
| ch.k43.util.KLogJDBCHandler.jdbc.url      | Connection URL       | e.g. jdbc:h2:mem:mydb                       |
| ch.k43.util.KLogJDBCHandler.jdbc.username | Connection user name | e.g. johnsmith                              |
| ch.k43.util.KLogJDBCHandler.jdbc.password | Connection password  | e.g. Pa$$w0rd                               |
| ch.k43.util.KLogJDBCHandler.tablename     | Database table name  | Table name to be used, e.g. KLOGDATA        |
| ch.k43.util.KLogJDBCHandler.retensiondays | Number               | Number of days to keep log entries, e.g. 14 |
| ch.k43.util.KLogJDBCHandler.debug         | true, false          | Send debug data to standard output (stdout) |

</details>

<details>

<summary>KLog.properties for KLogSMTPHandler</summary>

| Property Key                              | Value                                   | Notes                                       |
| ----------------------------------------- | --------------------------------------- | ------------------------------------------- |
| ch.k43.util.KLogSMTPHandler.mail.from     | Sender Address                          | e.g. <johnsmith@acme.com>                   |
| ch.k43.util.KLogSMTPHandler.mail.to       | Recipient Address                       | e.g. <fred@hotmail.com>                     |
| h.k43.util.KLogSMTPHandler.mail.subject   | Email subject                           | e.g. "Application Error"                    |
| ch.k43.util.KLogSMTPHandler.smtp.hostname | SMTP hostname                           | e.g. mail.acme.com                          |
| ch.k43.util.KLogSMTPHandler.smtp.hostport | SMTP port number                        | e.g. 25                                     |
| ch.k43.util.KLogSMTPHandler.smtp.username | SMTP authentication user name (or none) | e.g. <johnsmith@acme.com>                   |
| ch.k43.util.KLogSMTPHandler.smtp.password | SMTP authentication password (or none)  | e.g. Pa$$w0rd                               |
| ch.k43.util.KLogSMTPHandler.smtp.tls      | true, false                             | Use TLS or Non-TLS connection               |
| ch.k43.util.KLogSMTPHandler.threshold     | Number                                  | Maximum number of email sent per minute     |
| ch.k43.util.KLogSMTPHandler.debug         | true, false                             | Send debug data to standard output (stdout) |

</details>

<details>

<summary>KLog.properties for KLogCSVFormatter</summary>

| Property Key                             | Value       | Notes                              |
| ---------------------------------------- | ----------- | ---------------------------------- |
| ch.k43.util.KLogCSVFormatter.writeheader | true, false | Add header lines with column names |

</details>

### Examples

<details>

<summary>Code and Output</summary>

<pre class="language-java"><code class="lang-java"><strong>KLog.info("Program started");
</strong>		
int rc = -1;
KLog.error(rc != 0, "Return code is {}", rc);
	
KLog.debug("Just a debug message");
		
Exception e = new Exception("Program error");
KLog.error(e);
		
KLog.info("Program ended");
</code></pre>

```
2024-08-29T15:49:27.867 D main[1]:ch.k43.util.KLog:open:462                            ===== Application started 2024-08-29T15:49:27.850 =====
2024-08-29T15:49:27.867 D main[1]:ch.k43.util.KLog:open:464                            Java Utility Package (Freeware) ch.k43.util Version 2024.08.29
2024-08-29T15:49:27.868 D main[1]:ch.k43.util.KLog:open:467                            Homepage java-util.k43.ch - Please send any feedback to andy.brunner@k43.ch
2024-08-29T15:49:27.889 D main[1]:ch.k43.util.KLog:open:469                            Host ab-macbook-pro (10.0.0.105)
2024-08-29T15:49:27.889 D main[1]:ch.k43.util.KLog:open:470                            OS platform Mac OS X (Version 14.6.1/aarch64)
2024-08-29T15:49:27.889 D main[1]:ch.k43.util.KLog:open:471                            Java version 17 (OpenJDK 64-Bit Server VM - Eclipse Adoptium)
2024-08-29T15:49:27.891 D main[1]:ch.k43.util.KLog:open:475                            Java heap maximum 16.00 GB, current 1.00 GB, used 4.80 MB, free 1019.20 MB
2024-08-29T15:49:27.891 D main[1]:ch.k43.util.KLog:open:479                            Java locale de/CH, local time UTC +02:00
2024-08-29T15:49:27.891 D main[1]:ch.k43.util.KLog:open:482                            Java classpath ../bin/:../lib/org.json.20230618.jar:../lib/jakarta-mail-1.6.7.jar
2024-08-29T15:49:27.891 I main[1]:Test:main:10                                         Program started
2024-08-29T15:49:27.892 E main[1]:Test:main:13                                         ===> Return code is -1
2024-08-29T15:49:27.892 D main[1]:Test:main:15                                         Just a debug message
2024-08-29T15:49:27.892 E main[1]:Test:main:18                                         ===> java.lang.Exception: Program error
2024-08-29T15:49:27.892 E main[1]:Test:main:18                                         ===> Stack[1]: Test.main(Test.java:17)
2024-08-29T15:49:27.892 I main[1]:Test:main:20                                         Program ended
```

</details>

<details>

<summary>Log Exception</summary>

```java
try {
   ...
} catch (Exception e) {
   KLog.error(e);
}
```

</details>

<details>

<summary>Log and Throw RuntimeException</summary>

```java
try {
  ...
} catch (Exception e) {
  KLog.abort(e.toString());
}
```

</details>

<details>

<summary>Log and Throw IllegalArgumentException</summary>

```java
public divide(double arg1, double arg2) {
  // Check arguments
  KLog.argException(arg2 == 0.0, "Divisor 0 not allowed");
  ...
}
```

</details>
