Как я могу распечатать наносекунды в временной метке журнала при входе в Spring Boot 3.3 и Java 17, используя logback или log4j?

Я пытаюсь распечатать отметку времени с точностью до наносекунды в журналах моего приложения весенней загрузки. Я использую logback 1.5.6 в Spring Boot 3.3 с Java 17. Я искал разные подходы и пришел к выводу, что у нас уже есть доступ к наносекундной точности из Java 9+, а log4j был обновлен с помощью SimpleDateFormatter, который поддерживает наносекундную точность. Мы можем реализовать то же самое, используя кодировщик в logback-spring.xml с форматом %d{HH:mm:ss.SSSSSSSS} или %date{HH:mm:ss.SSSSSSSSS}

Но, учитывая все обстоятельства, я получил в журналах наносекундный формат (дд: мм: сс.СССССССС), но, к сожалению, данные были в миллисекундах. (12:30:17:815000000).

Таким образом, хотя он поддерживает точность в наносекундах, данные поступают с точностью до миллисекунды. Кажется, это проблема с кастингом где-то в библиотеке журналов.

Я также обнаружил, что мы можем использовать собственный кодер или фильтр или переменную пользовательского формата MDC, чтобы вручную получать данные и преобразовывать их в наносекунды, но по умолчанию это не должно давать наносекунды, как это предложено в документации и вариантах использования? По сути, поскольку в библиотеке уже есть такая функциональность, почему я не могу ее использовать.

logback-spring.xml

<configuration status = "TRACE">
    <appender name = "CONSOLE" class = "ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSSSSSSSS} [%thread] [%logger] [%level] - %msg%n</pattern>
        </encoder>
    </appender>

    <root level = "INFO">
        <appender-ref ref = "CONSOLE" />
    </root>
</configuration>

pom.xml

<?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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.demo.ems</groupId>
    <artifactId>ems</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>employee-service</module>
        <module>task-service</module>
        <module>discovery-service</module>
        <module>gateway-service</module>
        <module>admin-server-service</module>
        <module>config-service</module>
    </modules>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud.version>2023.0.0</spring-cloud.version>
        <spring-boot-admin.version>3.2.1</spring-boot-admin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>de.codecentric</groupId>
                <artifactId>spring-boot-admin-dependencies</artifactId>
                <version>${spring-boot-admin.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Также я отлаживал при входе в систему и обнаружил это. В журнале %d указан атрибут this.timeStamp, присутствующий в классе LoggingEvent.class пакета ch.qos.logback.classic.spi, который фактически формируется с использованием миллисекунд вместо наносекунд, хотя он доступен.

Также я отлаживал при входе в систему и обнаружил это. В журнале %d указан атрибут this.timeStamp, присутствующий в классе LoggingEvent.class пакета ch.qos.logback.classic.spi, который фактически формируется с использованием миллисекунд вместо наносекунд, хотя он доступен.

LoggingEvent.class

Вы используете log4j или log4j2? Log4j2 должен обеспечивать эту функциональность. Проверьте документацию: logging.apache.org/log4j/2.x/manual/…

BIBOO unit 18.06.2024 12:01

Я использую журнал 1.5.6. Не уверен, но, похоже, в серверной части используется log4j.

Amar Chandu 18.06.2024 14:21

Ваши системные часы имеют наносекундную точность?

Anonymous 18.06.2024 17:32

Как запечатлеть текущий момент с разрешением в наносекунды? Обычные компьютерные часы не могут отслеживать текущий момент с такой точностью. Современный Instant.now фиксирует текущий момент с разрешением микросекунд в Java 9+ (миллисекунд в Java 8). Наследие System.currentTimeMillis() сводится к считанным миллисекундам.

Basil Bourque 22.06.2024 08:31
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для входа в систему вам необходимо написать собственный конвертер.

Это преобразователь клиентов, который возвращает время прошедшее с момента его создания в наносекундах:

public class MySampleConverter extends ClassicConverter {

  long start = System.nanoTime();

  @Override
  public String convert(ILoggingEvent event) {
    long nowInNanos = System.nanoTime();
    return Long.toString(nowInNanos-start);
  }
}

а затем укажите на него в файле конфигурации

<configuration>

  <conversionRule conversionWord = "nanos"
                  converterClass = "chapters.;layouts.MySampleConverter" />

  <appender name = "STDOUT" class = "ch.qos.logback.;core.ConsoleAppender">
    <encoder>
      <pattern>%-6nanos [%thread] -%kvp -%msg%n</pattern>
    </encoder>
  </appender>

  <root level = "DEBUG">
    <appender-ref ref = "STDOUT" />
  </root>
</configuration>

Подробности смотрите https://logback.qos.ch/manual/layouts.html

Да, как я уже говорил, мы можем сделать это разными способами, но это требует дополнительных усилий, но по умолчанию, согласно справочному документу, должно работать, но не работать. Хотя в любом случае спасибо. Также нашел проблему: jira.qos.ch/browse/LOGBACK-1658

Amar Chandu 18.06.2024 12:55

Другие вопросы по теме