Изменить формат ведения журнала SpringBoot - микрометр на JSON - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть приложение SpringBoot, которое использует микрометр для распечатки метрик приложения.

Мой pom.xml имеет:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-core</artifactId>
    <version>1.1.3</version>
</dependency>

Мой класс конфигурации:

@Configuration
public class CoreConfiguration {

    public static final String USER_REQUEST_CHANNEL = "userRequestChannel";
    public static final String USER_RESPONSE_CHANNEL = "userResponseChannel";
    public static final String MDC_ADD = "add";
    public static final String DONE_CHANNEL = "nullChannel";
    public static final String ADMIN_REQUEST_CHANNEL = "adminRequestChannel";
    public static final String ADMIN_RESPONSE_CHANNEL = "adminResponseChannel";
    public static final String SUPPORT_COMPLETED_CHANNEL = "supportCompletedChannel";
    public static final String SUPPORT_RUNNING_CHANNEL = "nullChannel";
    public static final String SUPPORT_ERROR_CHANNEL = "nullChannel";

    @Bean(name = USER_REQUEST_CHANNEL)
    public MessageChannel oAuthRequestChannel() {
        return MessageChannels.direct().get();
    }

    @Bean(name = USER_RESPONSE_CHANNEL)
    public MessageChannel oAuthResponseChannel() {
        return MessageChannels.direct().get();
    }

    @Bean(name = FIRST_TRADE_CHANNEL)
    public MessageChannel firstTradeChannel() {
        return MessageChannels.direct().get();
    }

    @Bean(name = ADMIN_REQUEST_CHANNEL)
    public MessageChannel instructionExecutionRequestChannel() {
        return MessageChannels.direct().get();
    }

    @Bean(name = ADMIN_RESPONSE_CHANNEL)
    public MessageChannel instructionExecutionResponseChannel() {
        return MessageChannels.direct().get();
    }

    @Bean(name = SUPPORT_COMPLETED_CHANNEL)
    public MessageChannel groupExecutionCompletedChannel() {
        return MessageChannels.direct().get();
    }

    /**
     * Turn on the Micrometer log file metrics.
     *
     * @return
     */
    @Bean
    public LoggingMeterRegistry loggingMeterRegistry(@Value("${micrometer.log.minutes}") long minutes) {
        LoggingRegistryConfig config = new LoggingRegistryConfig() {
            @Override
            public String get(String s) {
                return null;
            }

            @Override
            public Duration step() {
                return Duration.ofMinutes(minutes);
            }
        };
        return LoggingMeterRegistry.builder(config).build();
    }
}

ИСПОЛЬЗОВАНИЕ В КЛАССЕ:

public IntegrationFlow processRequest(HttpRequest request) {
    return IntegrationFlows.from(INPUT_CHANNEL)
            .enrichHeader(m -> m.headerExpression(REQUEST_ID,"payload.message.headers." + REQUEST_ID))
            .log(LoggingHandler.Level.DEBUG, CoreConfiguration.class.getName(), m -> {
                Throwable t = (Throwable) m.getPayload();
                return throwableToString(t);})
            .get();
}

Я вижу вывод показателей, записанных в мой файл журнала, как:

2019-02-25 14: 40: 23,337 |ИНФО |[журнал-метрика-издатель] |[meter.core.instrument.logging.LoggingMeterRegistry] |MY_SAMPLE_APP |userId = [] |jvm.memory.max {area = heap, id = PS Survivor Space} значение = 12,5 МБ

Как выйти из системы в формате JSON?

ЧТО МНЕ НУЖНО:

{
"ts": "2019-02-25 14:40:23,337" ,
"level" : "INFO",
"className" : "meter.core.instrument.logging.LoggingMeterRegistry",
"appName" : "MY_SAMPLE_APP",
"userId" : "",
"metric" : 
        {"metricType": "jvm.memory.max",
         "area":"heap",
         "id":"PS Survivor Space",
         "value":"12.5 MiB"
         }
}

Обновление вопроса с кодом в соответствии с ответом Джона.@ Джон, как ты думаешь, приведенный ниже код верен?Я реализовал пользовательский реестр счетчиков, который расширяет LoggingMeterRegistry.

Единственное отличие между LoggingMeterRegistry и CustomMeterRegistry заключается в том, что мой пользовательский класс выводит ID =

В LoggingMeterRegistry: this.loggingSink.accept(print.id() + " throughput=" + print.rate(count));

В CustomMeterRegistry: this.loggingSink.accept("ID=" + print.id() + " throughput=" + print.rate(count));

ПОЛНЫЙ КОД:

public abstract class SplunkMeterRegistry extends LoggingMeterRegistry {
@Override
protected void publish() {
{
    if (this.config.enabled()) {
        this.getMeters().stream().sorted((m1, m2) -> {
            int typeComp = m1.getId().getType().compareTo(m2.getId().getType());
            return typeComp == 0 ? m1.getId().getName().compareTo(m2.getId().getName()) : typeComp;
        }).forEach((m) -> {
            LoggingMeterRegistry.Printer print = new LoggingMeterRegistry.Printer(m);
            m.use((gauge) -> {
                this.loggingSink.accept("ID=" + print.id() + " value=" + print.value(gauge.value()));
            }, (counter) -> {
                double count = counter.count();
                if (this.config.logInactive() || count != 0.0D) {
                    this.loggingSink.accept("ID=" + print.id() + " throughput=" + print.rate(count));
                }
            }, (timer) -> {
                HistogramSnapshot snapshot = timer.takeSnapshot();
                long count = snapshot.count();
                if (this.config.logInactive() || count != 0L) {
                    this.loggingSink.accept("ID=" + print.id() + " throughput=" + print.unitlessRate((double)count) + " mean=" + print.time(snapshot.mean(this.getBaseTimeUnit())) + " max=" + print.time(snapshot.max(this.getBaseTimeUnit())));
                }
            }, (summary) -> {
                HistogramSnapshot snapshot = summary.takeSnapshot();
                long count = snapshot.count();
                if (this.config.logInactive() || count != 0L) {
                    this.loggingSink.accept("ID=" + print.id() + " throughput=" + print.unitlessRate((double)count) + " mean=" + print.value(snapshot.mean()) + " max=" + print.value(snapshot.max()));
                }
            }, (longTaskTimer) -> {
                int activeTasks = longTaskTimer.activeTasks();
                if (this.config.logInactive() || activeTasks != 0) {
                    this.loggingSink.accept("ID=" + print.id() + " active=" + print.value((double)activeTasks) + " duration=" + print.time(longTaskTimer.duration(this.getBaseTimeUnit())));
                }
            }, (timeGauge) -> {
                double value = timeGauge.value(this.getBaseTimeUnit());
                if (this.config.logInactive() || value != 0.0D) {
                    this.loggingSink.accept("ID=" + print.id() + " value=" + print.time(value));
                }
            }, (counter) -> {
                double count = counter.count();
                if (this.config.logInactive() || count != 0.0D) {
                    this.loggingSink.accept("ID=" + print.id() + " throughput=" + print.rate(count));
                }
            }, (timer) -> {
                double count = timer.count();
                if (this.config.logInactive() || count != 0.0D) {
                    this.loggingSink.accept("ID=" + print.id() + " throughput=" + print.rate(count) + " mean=" + print.time(timer.mean(this.getBaseTimeUnit())));
                }
            }, (meter) -> {
                this.loggingSink.accept("ID=" + print.id() + StreamSupport.stream(meter.measure().spliterator(), false).map((ms) -> {
                    return ms.getStatistic().getTagValueRepresentation() + "=" + DoubleFormat.decimalOrNan(ms.getValue());
                }));
            });
        });
    }

}
}

}

1 Ответ

0 голосов
/ 28 февраля 2019

Вы должны реализовать пользовательский MeterRegistry, возможно, используя LoggingMeterRegistry в качестве ссылки, который сериализует данные в желаемом формате.По сути, именно такие реализации MeterRegistry, основанные на push-технологиях, - это просто разные форматы сериализации для разных потребителей.

...