У меня есть приложение 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());
}));
});
});
}
}
}
}