Logging using Log4j¶
FunctionGraph service supports Java function logging using Log4j and Slf4j.
Note
As all FunctionGraph instances write to the same log, it can be difficult to distinguish logs of different requests.
Writing to stdout or stderr will need to log the requestId of the request obtained from the Context.
The provided RunTimeLogger will add the requestId to the log output (see: see: Logging using RunTimeLogger).
Using a logging framework the user is responsible for adding the requestId to the log output.
This can be achieved by using ThreadContext object.
This section describes how to use functions and log4j to implement log printing.
/*
* Copyright (c) 2025 T-Systems International GmbH.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.opentelekomcloud.samples;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.util.LoaderUtil;
import com.google.gson.JsonObject;
import com.opentelekomcloud.services.runtime.Context;
import com.opentelekomcloud.services.runtime.RuntimeLogger;
import lombok.extern.slf4j.Slf4j;
/*
*
* Sample on how to use Slf4j logging
*
* FunctionGraph configuration:
* Handler name: com.opentelekomcloud.samples.FGLoggingSLF4j.handleRequest
*
* Initialization: ON
* Function Initializer: com.opentelekomcloud.samples.FGLoggingSLF4j.initializer
*
* Class Isolation: ON
*
* Environment Variables
* - LOG_LEVEL = DEBUG
*
*/
@Slf4j
public class FGLoggingSLF4j {
/**
* Setup logging in initializer
*/
public void initializer(Context context) {
RuntimeLogger rlog = context.getLogger();
rlog.log("Start initializing...");
try {
// put requestId into ThreadContext
ThreadContext.put("requestid", context.getRequestID());
// Initialize Log4J
try {
Configurator.reconfigure(
Objects.requireNonNull(LoaderUtil.getThreadContextClassLoader().getResource("log4j2.xml")).toURI());
} catch (URISyntaxException e) {
rlog.error("An error occurred while configuring Log4J:" + e.getMessage());
throw new RuntimeException(e);
}
// set log level
String log_level = context.getUserData("LOG_LEVEL");
List<String> allowed = Arrays.asList("DEBUG", "INFO", "WARN", "ERROR");
if (!allowed.contains(log_level)) {
log_level = "DEBUG";
}
Level level = Level.getLevel(log_level);
Configurator.setRootLevel(level);
} finally {
// remove requestId from ThreadContext
ThreadContext.remove("requestid");
}
rlog.log("Finished initializing...");
}
/**
* FunctionGraph Handler
*/
public String handleRequest(final JsonObject event, final Context context) {
try {
// put requestId into ThreadContext
ThreadContext.put("requestid", context.getRequestID());
log.debug("debug log");
log.info("info log");
log.warn("warn log");
log.error("error log");
} finally {
// remove requestId from ThreadContext
ThreadContext.remove("requestid");
}
return "ok";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Properties>
<!-- requestid will be taken from ThreadContext -->
<Property name="LOG_PATTERN">%d{yyyy-MM-dd'T'HH:mm:ss.SSS'Z'}{UTC}|%X{requestid}|%p|%F:%L|%.10240m%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8" pattern="${LOG_PATTERN}" />
</Console>
</Appenders>
<Loggers>
<Root level="DEBUG">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.opentelekomcloud</groupId>
<artifactId>opentelekomcloud-functiongraph-java-samples-doc-pom</artifactId>
<version>1.0.0</version>
</parent>
<groupId>io.github.opentelekomcloud</groupId>
<artifactId>opentelekomcloud-functiongraph-java-samples-doc-logging-slf4j</artifactId>
<name>opentelekomcloud-functiongraph-java-samples-doc-logging-slf4j</name>
<packaging>jar</packaging>
<url>https://docs.otc.t-systems.com/opentelekomcloud-functiongraph-java</url>
<description>Open Telekom Cloud FunctionGraph Java SDK samples documentation for SLF4j logging</description>
<scm>
<connection>scm:git:git://github.com/opentelekomcloud/opentelekomcloud-functiongraph-java.git</connection>
<developerConnection>scm:git:ssh://github.com:opentelekomcloud/opentelekomcloud-functiongraph-java.git</developerConnection>
<url>http://github.com/opentelekomcloud/opentelekomcloud-functiongraph-java/tree/main</url>
</scm>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId>
<version>0.2.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>shade-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>${project.name}</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer
implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Log output
12025-08-01T08:13:22Z Start invoke request '0d0c9273-61d9-4dfb-b32a-52a4372a98dc', version: latest
22025-08-01T08:13:22.792Z|0d0c9273-61d9-4dfb-b32a-52a4372a98dc|DEBUG|FGLoggingSLF4j.java:97|debug log
32025-08-01T08:13:22.792Z|0d0c9273-61d9-4dfb-b32a-52a4372a98dc|INFO|FGLoggingSLF4j.java:98|info log
42025-08-01T08:13:22.793Z|0d0c9273-61d9-4dfb-b32a-52a4372a98dc|WARN|FGLoggingSLF4j.java:99|warn log
52025-08-01T08:13:22.793Z|0d0c9273-61d9-4dfb-b32a-52a4372a98dc|ERROR|FGLoggingSLF4j.java:100|error log
62025-08-01T08:13:22Z Finish invoke request '0d0c9273-61d9-4dfb-b32a-52a4372a98dc', duration: 60.378ms, billing duration: 61ms, memory used: 104.137MB, billing memory: 512MB, cpu used: 0.195U, storage used: 0.052MB
Lines 2-5 show outputs from configured logger.
Note
If initializer is not set, log output will be as follows:
12025-08-01T08:30:09Z Start invoke request '2146fee3-aa3b-44cb-af6a-d7d292ccf6e6', version: latest
2[2025-08-01 10:30:09.449 INFO FGLoggingSLF4j.java:98] info log
3[2025-08-01 10:30:09.453 WARN FGLoggingSLF4j.java:99] warn log
4[2025-08-01 10:30:09.453 ERROR FGLoggingSLF4j.java:100] error log
52025-08-01T08:30:09Z Finish invoke request '2146fee3-aa3b-44cb-af6a-d7d292ccf6e6', duration: 59.914ms, billing duration: 60ms, memory used: 99.527MB, billing memory: 512MB, cpu used: 0.398U, storage used: 0.052MB
Lines 2-5 show outputs from default logger configuration.
Deployment instructions:¶
Set Function execution entry point
Choose Settings > Basic Settings, set the Function Execution Entry parameter to com.opentelekomcloud.samples.FGLoggingSLF4j.handleRequest
Enable class isolation.
After the code package is successfully deployed, select Settings > Advanced Settings, turn on Class Isolation
Set function initialization entry point
Choose Settings > Advanced Settings:
enable Initialization
set the Initializer parameter to com.opentelekomcloud.samples.FGLoggingSLF4j.initializer
set the Initialization Timeout parameter to appropriate value, e.g. 10s
Set Environment Variable “LOG_LEVEL”
Choose Settings > Environment Variables and add new variable with key: LOG_LEVEL and value: DEBUG
(Possible values are DEBUG, INFO, WARN, ERROR)