Is your Java application running blind? Time to fix it
\n\nImagine: you deploy a new version of a microservice, everything works fine on your local machine, tests pass. An hour later — a crash in production. Where to look for the cause? Without proper monitoring and logging of Java applications, you'll be grasping at straws, losing money and nerves.
\n\nIn this article, we'll break down how to turn your application from a "black box" into a transparent system. You'll learn how to set up logging in Java using modern libraries, collect metrics, and build a full-fledged monitoring system. Let's go!
\n\nWhy monitoring and logging of Java applications is a must-have
\n\nModern Java development is not just about writing code. It's about managing complex distributed systems, microservices, and containers. Without observability tools, you won't be able to:
\n\n- \n
- Quickly find the causes of failures \n
- Forecast load \n
- Track performance \n
- Meet SLA commitments to clients \n
Properly configured monitoring of Java applications gives you a superpower — seeing what's happening inside the code in real time. And this is not a luxury, but a necessity.
\n\nLogging in Java: Choosing the technology stack
\n\nWhy System.out.println() is evil
\n\nMany beginner developers use System.out.println() for debugging. In a small educational project, it might pass, but in production, it will lead to disaster:
- \n
- No logging levels (debug, info, error) \n
- Cannot flexibly configure output \n
- Difficult to parse with automated systems \n
- Synchronous writing slows down the application \n
Forget this approach. Real Jedi use professional libraries.
\n\nBest choice: SLF4J + Logback
\n\nSLF4J (Simple Logging Facade for Java) is an abstraction that allows you to plug in any logging implementation. Logback is the most popular and performant implementation today.
\n\nAdd to pom.xml (Maven) or build.gradle (Gradle):
// Maven dependency\n<dependency>\n <groupId>ch.qos.logback</groupId>\n <artifactId>logback-classic</artifactId>\n <version>1.4.14</version>\n</dependency>\n\n// SLF4J API (usually comes with Logback)\n<dependency>\n <groupId>org.slf4j</groupId>\n <artifactId>slf4j-api</artifactId>\n <version>2.0.9</version>\n</dependency>\n\nLogback configuration example (logback.xml)
\n\n<configuration>\n <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">\n <file>logs/app.log</file>\n <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">\n <fileNamePattern>logs/app-%d{yyyy-MM-dd}.log</fileNamePattern>\n <maxHistory>30</maxHistory>\n </rollingPolicy>\n <encoder>\n <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n </encoder>\n </appender>\n\n <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">\n <encoder>\n <pattern>%d{HH:mm:ss.SSS} %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>\n </encoder>\n </appender>\n\n <root level="info">\n <appender-ref ref="FILE"/>\n <appender-ref ref="CONSOLE"/>\n </root>\n</configuration>\n\nHow to use in code
\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class OrderService {\n private static final Logger log = LoggerFactor