我有一个 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 | 用户 ID = [] | jvm.memory.max{area=heap,id=PS Survivor Space} value=12.5 MiB
如何以 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"
}
}
根据乔恩的回答用代码更新问题。@Jon,您认为下面的代码正确吗?我已经实现了一个扩展 LoggingMeterRegistry 的自定义 Meter Registry。
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());
}));
});
});
}
}
}
}