Skip to content

Commit dea4888

Browse files
authored
Add Log4j2 JsonTemplateLayout support for JSON log output (#9209)
* Add Log4j2 JsonTemplateLayout support for JSON log output Add the log4j-layout-template-json dependency and a new log4j2-json.xml configuration file that uses JsonTemplateLayout to produce structured JSON logs. Each log event includes @timestamp, level, loggerName, message, and exception fields suitable for ingestion by ELK stack or similar log aggregation tools. The file naming convention (log4j2-json.xml) makes the "JSON" option automatically available in the Admin Settings log level dropdown via the existing LoggingApi regex discovery mechanism. Harvester logs retain their existing PatternLayout as they are consumed separately. * Expand logging documentation with configuration details Document Log4j2 configuration structure (appenders, pattern layout, log rotation), harvester logging via routing appender, all available logger modules, JSON logging sample output, custom log configuration creation, REST API endpoints, and troubleshooting tips. Also fix the log level preset list to match actual configuration files (PROD, INDEX, DEV, TEST, JSON — there is no SEARCH preset).
1 parent 1d00b5a commit dea4888

File tree

4 files changed

+435
-11
lines changed

4 files changed

+435
-11
lines changed

docs/manual/docs/install-guide/logging.md

Lines changed: 225 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This section describes how to use the geonetwork log files to find more details
44

55
## Customising the log file location
66

7-
The default log file location is `logs/geonetwork.log` (with backups created
7+
The default log file location is `logs/geonetwork.log` (with backups created
88
``geonetwork-1.log``, ``geonetwork-2.log``,...).
99

1010
It is possible to change the directory where these log files are generated
@@ -15,33 +15,247 @@ For the example `-Dlog_dir=/var/tomcat/logs` the files will be created in
1515
`/var/tomcat/logs/geonetwork.log`, and will rotate through the filenames
1616
`/var/tomcat/logs/geonetwork-1.log`,`/var/tomcat/logs/geonetwork-2.log`,...
1717

18-
To set the `log_dir` property, you can add it to the `JAVA_OPTS` in the startup
19-
script of your servlet container. For example, if you are using Tomcat, you
20-
can add it to the `setenv.sh` or `setenv.bat` file in the `bin` directory of
18+
To set the `log_dir` property, you can add it to the `JAVA_OPTS` in the startup
19+
script of your servlet container. For example, if you are using Tomcat, you
20+
can add it to the `setenv.sh` or `setenv.bat` file in the `bin` directory of
2121
your Tomcat installation.
2222

23-
Details of some errors, such as XSL transformation errors, are not written to
24-
`geonetwork.log`. They are written to a file called **`catalina.out`** (if
23+
Details of some errors, such as XSL transformation errors, are not written to
24+
`geonetwork.log`. They are written to a file called **`catalina.out`** (if
2525
using Tomcat).
2626

2727
## Setting the Loglevel
2828

29-
GeoNetwork by default has 4 log levels: PROD, INDEX, SEARCH, DEV.
29+
GeoNetwork by default has 5 log levels: PROD, INDEX, DEV, TEST, JSON.
3030

3131
- PROD is the default option, it will only log critical errors.
3232
- INDEX is similar to PROD, but with extended logging around the indexation process.
33-
- Search is similar to PROD, but with extended logging around the search process.
3433
- DEV is the most extended level, all debug messages will be logged.
34+
- TEST is a simplified configuration useful for running tests, with fewer logger categories and a `warn` root level.
35+
- JSON outputs structured JSON logs suitable for log aggregation tools such as Elasticsearch/Kibana (ELK stack).
3536

3637
You can set the log level from the Admin --> Settings page.
3738

3839
![](img/log-setting.png)
3940

4041
## Log4j
4142

42-
GeoNetwork uses [Apache log4j](https://logging.apache.org/log4j) for logging.
43+
GeoNetwork uses [Apache Log4j2](https://logging.apache.org/log4j) for logging.
4344
The log4j configuration files are located in the **`/WEB-INF/classes`** directory of the GeoNetwork web application:
44-
**`/WEB-INF/classes/log4j2.xml`**, **`/WEB-INF/classes/log4j2-dev.xml`** and **`/WEB-INF/classes/log4j2-index.xml`**.
45-
The configuration file configures for each debug level at what severity messages will be logged.
45+
**`log4j2.xml`** (PROD), **`log4j2-dev.xml`** (DEV), **`log4j2-index.xml`** (INDEX), **`log4j2-json.xml`** (JSON) and **`log4j2-test.xml`** (TEST).
46+
Each configuration file defines which log levels apply to each logger module.
4647

4748
The file used is determined by the log level set in the *Admin**Settings* page.
49+
50+
### Configuration structure
51+
52+
Each Log4j2 configuration file defines three appenders:
53+
54+
- **Console** — writes to `SYSTEM_OUT` (stdout).
55+
- **RollingFile** (`File`) — writes to `geonetwork.log` in the log directory.
56+
- **Harvester** — a routing appender that writes to per-harvester log files (see [Harvester logging](#harvester-logging)).
57+
58+
The default `PatternLayout` format used by the Console and RollingFile appenders is:
59+
60+
```
61+
%date{ISO8601} %-5level [%logger] - %message%n
62+
```
63+
64+
Which produces output like:
65+
66+
```
67+
2024-06-15T10:23:45,123 INFO [geonetwork.harvester] - Starting harvester run
68+
```
69+
70+
### Log file rotation
71+
72+
The `RollingFile` appender uses size-based rotation:
73+
74+
- Maximum file size: **10 MB** per log file.
75+
- Up to **3 backup files** are kept, named `geonetwork.log-1.log`, `geonetwork.log-2.log`, `geonetwork.log-3.log`.
76+
- When the current log file exceeds 10 MB, it is rolled over and the oldest backup is deleted.
77+
78+
### Auto-discovery of configuration files
79+
80+
GeoNetwork scans `/WEB-INF/classes` for files matching the regex `log4j2(-(.*?))?.xml`. Any file that matches this pattern is automatically made available in the *Admin**Settings* log level dropdown. The matched group (e.g. `dev` from `log4j2-dev.xml`) is uppercased to form the display name. The base `log4j2.xml` without a suffix is displayed as **PROD**.
81+
82+
## Harvester logging
83+
84+
Harvester logs are written to separate files via a **Routing** appender. Each harvester gets its own log file, dynamically named based on the harvester's thread context (`ctx:logfile` and `ctx:harvester`).
85+
86+
- The log file name is determined at runtime from the harvester context.
87+
- If no specific context is set, logs go to `harvester_default.log` in the log directory.
88+
- Harvester log files use the `PatternLayout` with timezone-aware timestamps:
89+
```
90+
%date{ISO8601}{${ctx:timeZone}} %-5level [%logger] - %message%n
91+
```
92+
- Even when JSON logging is enabled, harvester logs continue to use plain-text `PatternLayout` since they are consumed separately from the main log file.
93+
94+
## Logger modules
95+
96+
The Log4j2 configuration files define logger categories that administrators can adjust. Each log level preset (PROD, INDEX, DEV, etc.) sets these loggers to different levels.
97+
98+
### GeoNetwork loggers
99+
100+
The main GeoNetwork logger `geonetwork` controls the base level for all GeoNetwork modules. Submodule loggers inherit from it unless explicitly configured:
101+
102+
| Logger | Description |
103+
|--------|-------------|
104+
| `geonetwork.accessmanager` | Access control and permissions |
105+
| `geonetwork.atom` | ATOM feed support |
106+
| `geonetwork.csw` | CSW service |
107+
| `geonetwork.csw.search` | CSW search operations |
108+
| `geonetwork.database` | Database operations |
109+
| `geonetwork.databasemigration` | Database schema migration |
110+
| `geonetwork.datamanager` | Metadata data manager |
111+
| `geonetwork.editor` | Metadata editor |
112+
| `geonetwork.editorexpandelement` | Editor element expansion |
113+
| `geonetwork.editorfillelement` | Editor element filling |
114+
| `geonetwork.encryptor` | Encryption services |
115+
| `geonetwork.formatter` | Metadata formatter |
116+
| `geonetwork.geoserver.publisher` | GeoServer layer publishing |
117+
| `geonetwork.geoserver.rest` | GeoServer REST interactions |
118+
| `geonetwork.harvester` | Harvester operations (also writes to harvester log files) |
119+
| `geonetwork.harvest-man` | Harvester manager |
120+
| `geonetwork.index` | Elasticsearch indexing |
121+
| `geonetwork.ldap` | LDAP authentication |
122+
| `geonetwork.mef` | MEF import/export |
123+
| `geonetwork.schemamanager` | Metadata schema management |
124+
| `geonetwork.search` | Search operations |
125+
| `geonetwork.security` | Security framework |
126+
| `geonetwork.thesaurus` | Thesaurus operations |
127+
| `geonetwork.doi` | DOI registration |
128+
| `geonetwork.engine` | Jeeves engine |
129+
| `geonetwork.xlinkprocessor` | XLink resolution |
130+
| `geonetwork.xmlresolver` | XML entity resolution |
131+
132+
### Third-party loggers
133+
134+
| Logger | Description |
135+
|--------|-------------|
136+
| `org.springframework` | Spring Framework (base) |
137+
| `org.springframework.beans` | Spring bean wiring |
138+
| `org.springframework.security` | Spring Security |
139+
| `org.springframework.security.ldap` | Spring Security LDAP |
140+
| `org.hibernate.SQL` | Hibernate SQL statements |
141+
| `org.hibernate.type` | Hibernate type resolution |
142+
| `org.hibernate.tool.hbm2ddl` | Hibernate schema generation |
143+
| `org.jzkit` | JZKIT search toolkit |
144+
| `org.apache.camel` | Apache Camel routing |
145+
146+
### Log levels per preset
147+
148+
Each preset adjusts logger levels differently. As a general guide:
149+
150+
- **PROD** — most GeoNetwork loggers at `error`, third-party at `error`. Minimal output.
151+
- **INDEX** — similar to PROD, but `geonetwork.search` at `warn` and `geonetwork.harvest-man` at `info` for indexation monitoring.
152+
- **DEV** — most GeoNetwork loggers at `debug`, Spring/Hibernate at `debug`. Very verbose.
153+
- **TEST** — simplified configuration with fewer logger categories, root level at `warn`.
154+
- **JSON** — same logger levels as PROD, but output format is JSON (see below).
155+
156+
## JSON logging
157+
158+
The **JSON** log level uses `log4j2-json.xml` which replaces the default `PatternLayout` with Log4j2's `JsonTemplateLayout`. This produces structured JSON output on both the console and the rolling log file, making it suitable for ingestion by log aggregation tools such as the ELK stack (Elasticsearch, Logstash, Kibana).
159+
160+
Each log event is output as a JSON object with the following fields:
161+
162+
- `@timestamp` — event timestamp in ISO 8601 format
163+
- `level` — log level (e.g. ERROR, INFO, DEBUG)
164+
- `loggerName` — the logger that produced the event
165+
- `message` — the log message
166+
- `exception` — stack trace, if present
167+
168+
A sample JSON log line:
169+
170+
```json
171+
{"@timestamp":"2024-06-15T10:23:45.123+0000","level":"ERROR","loggerName":"geonetwork.index","message":"Failed to index record abc-123","exception":null}
172+
```
173+
174+
To activate JSON logging, go to *Admin**Settings* and select **JSON** from the log level dropdown.
175+
176+
The `JsonTemplateLayout` is provided by the `log4j-layout-template-json` library which is included in GeoNetwork's dependencies. The event template is embedded inline in the `log4j2-json.xml` configuration file and can be customized directly to add or modify fields.
177+
178+
Harvester logs continue to use plain-text `PatternLayout` as they are consumed separately.
179+
180+
For log ingestion, you can point **Filebeat** or **Logstash** directly at the `geonetwork.log` file when JSON mode is enabled, since each line is a self-contained JSON object.
181+
182+
## Custom log configurations
183+
184+
You can create your own log level preset by adding a new configuration file to `/WEB-INF/classes/`:
185+
186+
1. Copy an existing configuration (e.g. `log4j2.xml`) as a starting point.
187+
2. Name the new file following the pattern `log4j2-<name>.xml` (e.g. `log4j2-debug-search.xml`).
188+
3. Adjust the logger levels as needed.
189+
4. Restart GeoNetwork (or wait for the configuration to be reloaded).
190+
191+
The new configuration will automatically appear in the *Admin**Settings* log level dropdown as **`<NAME>`** (uppercased from the filename suffix, e.g. `DEBUG-SEARCH`).
192+
193+
## Log REST API
194+
195+
GeoNetwork provides REST endpoints for managing and viewing logs. All endpoints require **Administrator** role.
196+
197+
### List available log configurations
198+
199+
```
200+
GET /{portal}/api/site/logging
201+
```
202+
203+
Returns a JSON array of available log configuration files:
204+
205+
```json
206+
[
207+
{"name": "PROD", "file": "log4j2.xml"},
208+
{"name": "DEV", "file": "log4j2-dev.xml"},
209+
{"name": "INDEX", "file": "log4j2-index.xml"},
210+
{"name": "JSON", "file": "log4j2-json.xml"},
211+
{"name": "TEST", "file": "log4j2-test.xml"}
212+
]
213+
```
214+
215+
### Get recent log activity
216+
217+
```
218+
GET /{portal}/api/site/logging/activity?lines={n}
219+
```
220+
221+
Returns the last *n* lines from the log file as plain text. Default is **2000** lines; maximum is **20000**.
222+
223+
### Download log file as ZIP
224+
225+
```
226+
GET /{portal}/api/site/logging/activity/zip
227+
```
228+
229+
Downloads the current log file as a ZIP archive, named `catalog-log-<timestamp>.zip`.
230+
231+
## Troubleshooting
232+
233+
### Enable Log4j2 internal status logging
234+
235+
If log output is not appearing as expected, enable Log4j2's internal status logger to diagnose configuration problems. Set the `status` attribute on the `<Configuration>` element:
236+
237+
```xml
238+
<Configuration status="trace" dest="out">
239+
```
240+
241+
Alternatively, set the system property at startup:
242+
243+
```
244+
-Dorg.apache.logging.log4j.simplelog.StatusLogger.level=DEBUG
245+
```
246+
247+
This will output Log4j2's internal messages to the console, helping identify issues with appender configuration, missing files, or pattern errors.
248+
249+
### XSL transformation errors
250+
251+
XSL transformation errors are not written to `geonetwork.log`. They are written to **`catalina.out`** (when using Tomcat). Check this file if you suspect issues with metadata formatting or schema processing.
252+
253+
### Temporarily increase logging for a specific module
254+
255+
To debug a specific subsystem without increasing the global log level, edit the active Log4j2 configuration file and change only the target logger. For example, to debug search issues while keeping everything else at `error`:
256+
257+
```xml
258+
<Logger name="geonetwork.search" level="debug"/>
259+
```
260+
261+
Then switch to a different log configuration and back in *Admin**Settings* to reload, or restart GeoNetwork. Remember to revert the change after debugging.

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,11 @@
607607
<artifactId>log4j-jul</artifactId>
608608
<version>${log4j2.version}</version>
609609
</dependency>
610+
<dependency>
611+
<groupId>org.apache.logging.log4j</groupId>
612+
<artifactId>log4j-layout-template-json</artifactId>
613+
<version>${log4j2.version}</version>
614+
</dependency>
610615
<dependency>
611616
<groupId>org.apache.httpcomponents</groupId>
612617
<artifactId>httpclient</artifactId>

web/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@
6969
<groupId>org.apache.logging.log4j</groupId>
7070
<artifactId>log4j-jul</artifactId>
7171
</dependency>
72+
<dependency>
73+
<groupId>org.apache.logging.log4j</groupId>
74+
<artifactId>log4j-layout-template-json</artifactId>
75+
</dependency>
7276
<dependency>
7377
<groupId>org.tuckey</groupId>
7478
<artifactId>urlrewritefilter</artifactId>

0 commit comments

Comments
 (0)