Decades, Java developers have been struggling with the flooding logs. Now the concern would be added with spanned logs and business logic across separated micro-services. Thanks to the evolving technology, it's time to try new way to overcome the bumpy headaches.
Not like traditional loggers, bitryon logger provides a way to serialize the method's parameters and return as tracing logs below, which is annotated with @Logging, to free developers from manually writing logs.
2025-11-11 16:31:22.299|http-nio-80-exec-4#45|6HGHFOWTCdhjI0GkuTbd6PvbLra2KOE4|8-2|JSON|
UserServiceImpl.java#io.bitryon.example.web.service.rpc.UserServiceImpl#getById#24#|
[{
"userId": 0
}]
2025-11-11 16:31:22.299|http-nio-80-exec-4#45|6HGHFOWTCdhjI0GkuTbd6PvbLra2KOE4|8-3|TEXT|
UserServiceImpl.java#io.bitryon.example.web.service.rpc.UserServiceImpl#getById#29|
This should be remote service, will be with trace for user 0
2025-11-11 16:31:22.301|http-nio-80-exec-4#45|6HGHFOWTCdhjI0GkuTbd6PvbLra2KOE4|8-4|JSON|
UserServiceImpl.java#io.bitryon.example.web.service.rpc.UserServiceImpl#getById#24#R|
[{
"name": "ra***ly",
"id": 123,
"driverLisenceId": "****************************",
"age": null
}]
Both, bitryon logger is a tracer; bitryon logger is a logger;
Steps to integrate bitryon logger
- Configure logger through yml in spring, or properties in java
- Annotate
@Loggingor build logging on methods and classes - Initiate proxy and logger, pass trace/log id across applications
- Upload logs through agent or OpenTelemetry
- Log in web portal to access log traces
Now, show you my code
Configure logger through yml in spring, properties in java
bitryon:
logger:
file-name: ./logs/${spring.application.name} # will be like ./logs/bitryon-logging-integration-java-spring-example.20250415-161023-565.0.log
file-max-length: 536870912
print-stdout: true
print-file: true
log-date-time-format: yyyy-MM-dd HH:mm:ss.SSS # UTC.
log-async: true
log-light: false
log-pretty: true
log-sanitizer-patterns: >
/JSON/*Service*.java*.service.*UserService*#*/*/MASK(driverLisenceId)/*/MASK$2(name)//SKIP(birthday),
/JSON/*MedicService*#*/*/MASK(driverLisenceId)/*/MASK$2(name)//SKIP(birthday),
/JSON/*.java*.Medic*#*/*/MASK$4(deceases)/yyyy-MM-dd HH:mm:ss.ssss/DATE_FORMATER(timeCreated),
/HTTP/*LoggingHttpRequestWebReader#readHttpRequest*/*/MASK(driverLisenceId)/*/MASK$2(name)//SKIP(birthday)
app-node:
http-header-id-type: 1 # write log/trace id to the http response header; 0 default no write header, 1 trace id, 2 step log id
application-name: ${spring.application.name}
host-id: node-123.test.test # to identify unique file
github: # If you'd like to jump to your source code page from the trace page
host: https://github.com/
source-paths: >
src/main/java
repository: RepoOwner/Your-Repo
branch: master
commit: xxxxxxx
boot-info: # for info purpose, bitryon don't use it
version: 1.2.3 # the version of the app.
internal-ip: 12.2.2.2
external-ip: 12.2.2.2
program: 1.2.2-1231321.jar
region: use-1
platform:
cloud: aws
Annotate @Logging or build logging on methods and classes
<dependency>
<groupId>io.bitryon</groupId>
<artifactId>bitryon-logger-spring-boot-starter</artifactId>
<version>1.0.74</version><!-- https://repo1.maven.org/maven2/io/bitryon/bitryon-logger-spring-boot-starter -->
</dependency>
import io.bitryon.logger.Logger;
import io.bitryon.logger.provider.LoggerFactory;
@Service
@Logging
public class UserServiceImpl {
private static final Logger logger = LoggerFactory.getLogger();
public User getById(Long userId){
if (userId==null) {
return null;
}
logger.text("This should be remote service, will be with trace for user {}", userId);
User user = new User();
user.setId(123L);
try {
SimpleDateFormat simpleDateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
user.setBirthday(simpleDateFormater.parse("2025-08-10T15:42:17.123+02"));
} catch (ParseException e) {
logger.exception(e);
}
user.setDriverLisenceId("a number that you can't know");
user.setName("randome guy probably");
return user;
}
}
Initiate proxy and logger, pass trace/log id across applications
public static void main(String[] args) {
// In Spring
//LoggingProxyInitiation.premain(null); // must load before everything. or add https://github.com/FrankNPC/bitryon-logging-examples/blob/master/bitryon-logging-integration-java-spring-example/src/main/resources/META-INF/spring.factories
new SpringApplicationBuilder(ServerBootApplication.class).run(args);
// In non-spring
// 1: load logger agent
LoggingProxyInitiation.premain(null);
// 2: load logger configure from default bitryon_logger.properties
LoggerProvider provider = LoggerProvider.getProvider();
// 3: load LoggingMethodIntercepter
new LoggingMethodIntercepter(provider);
}
If cross applications/services, we need to pass step log id through http client header to next web server
import io.bitryon.logger.annotation.LoggingUnit;
import io.bitryon.logger.provider.LoggerProvider;
import io.bitryon.logger.spring.LoggingHttpClientHeaderWriterInterceptor;
import io.bitryon.logger.spring.LoggingMethodPointcut;
@Resource
LoggerProvider bitryonLoggerProvider;
public RestClient getRestClient() {
return RestClient
.builder(new RestTemplate(new HttpComponentsClientHttpRequestFactory()))
.baseUrl(getBaseUrl())
// write step log id to the http request header to the next app/service to form traces
.requestInterceptor(new LoggingHttpClientHeaderWriterInterceptor(bitryonLoggerProvider))
.build();
}
And we need to pick up step log id from http request header to continue the trace.
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import io.bitryon.logger.provider.LoggerProvider;
import io.bitryon.logger.spring.AutoConfigurationBitryonLogger;
import io.bitryon.logger.spring.LoggingHttpRequestWebFilter;
@Configuration
@Import(AutoConfigurationBitryonLogger.class)
public class ExampleWebServerConfiguration {
@Resource
LoggerProvider bitryonLoggerProvider;
// read step log id from last app/service/http request header to form traces, and log http payload for specific paths
@Bean
FilterRegistrationBean<LoggingHttpRequestWebFilter> loggingResetInFilter() {
FilterRegistrationBean<LoggingHttpRequestWebFilter> reg = new FilterRegistrationBean<>(
new LoggingHttpRequestWebFilter(bitryonLoggerProvider, true));
reg.setOrder(Ordered.HIGHEST_PRECEDENCE);
reg.addUrlPatterns("/api", "/api/*", "/remote_api/*");
return reg;
}
}
Upload logs through the agent or OpenTelemetry
- register account on Non-PRD Web Portal
- create and active your application and get the app_key for the agent
- download and configure bitryon-logging-agent to upload the logs into bitryon.io for traces.
- Or point to OpenTelemetry OTLP exporter
Log in web portal to access the log traces, and search logs.
Use trace id in the http response header to access the trace: https://dev-portal.bitryon.io/trace.html?id=[X-Step-Trace-Id]

More over
- It is not spring only, it works alone without spring.
- With github configuration, trace page links logs to source code page.
- The sanitizer
non-invasivelyprotects Personal Identify Information. - Keep updated bitryon-logging-examples for more use cases.
Conclusion
So now java developers will be freed hands to focus on solving problem with well-groomed traces and workflows not just plain logs but also better eyes protection.
#java
#microservices
#startup
#observation
#logging
#log
#logger
#trace
#tracer
#tracing
#workflow
#OpenTelemetry
Top comments (0)