DEV Community

FrankNPC
FrankNPC

Posted on • Edited on

How to automate log and trace together without writing a log and trace

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
}]
Enter fullscreen mode Exit fullscreen mode

Both, bitryon logger is a tracer; bitryon logger is a logger;

Steps to integrate bitryon logger

  1. Configure logger through yml in spring, or properties in java
  2. Annotate @Logging or build logging on methods and classes
  3. Initiate proxy and logger, pass trace/log id across applications
  4. Upload logs through agent or OpenTelemetry
  5. 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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode
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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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();
    }
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Upload logs through the agent or OpenTelemetry

  1. register account on Non-PRD Web Portal
  2. create and active your application and get the app_key for the agent
  3. download and configure bitryon-logging-agent to upload the logs into bitryon.io for traces.
  4. 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]
Screenshot of the example

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-invasively protects 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)