You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让HikariCP指标在NewRelic中按实体正常显示?

问题描述

我们有一个基于HikariCP的自定义Web应用,打包成Jar后在Docker容器中运行。根据环境差异,启动webapp.jar时会通过-javaagent参数加载newrelic-agent.jar。

HikariCP配置如下:

private DataSource createDataSource() {
    final HikariConfig config = new HikariConfig();

    config.setJdbcUrl(...);
    config.setUsername(...);
    config.setPassword(...);
    config.setSchema(...);

    config.setConnectionTimeout(...);
    config.setMinimumIdle(...);
    config.setMaximumPoolSize(...);
    config.setIdleTimeout(...);

    config.setLeakDetectionThreshold(...);
    config.setMaxLifetime(...);

    config.addDataSourceProperty("cachePrepStmts", "true");
    config.addDataSourceProperty("prepStmtCacheSize", "250");
    config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");

    config.setMetricRegistry(metricsRegistry.getRegistry());

    return new HikariDataSource(config);
}

我们实现了NewRelicMetricsService,在应用启动时检测NewRelic类是否存在,存在则启动上报器并复用newrelic.yaml配置:

public class NewRelicMetricsService {

    private static final Logger logger = LoggerFactory.getLogger(NewRelicMetricsService.class);

    private final NewRelicReporter reporter;

    @Inject
    public NewRelicMetricsService(ApplicationMetricsRegistry metricRegistry) {
        NewRelicReporter tmpReporter = null;
        // 检查NewRelic Java Agent是否加载
        try {
            Class.forName("com.newrelic.api.agent.NewRelic");
            Config config = NewRelic.getAgent().getConfig();

            SenderConfiguration sender = MetricBatchSender.configurationBuilder()
                    .apiKey(config.getValue("license_key"))
                    .useLicenseKey(true)
                    .httpPoster(new OkHttpPoster(Duration.ofSeconds(2)))
                    .build();

            MetricBatchSender metricBatchSender = MetricBatchSender.create(sender);

            // 定义APM和服务中可见的自定义属性
            Attributes commonAttributes = new Attributes();

            tmpReporter = NewRelicReporter.build(metricRegistry.getRegistry(), metricBatchSender)
                                          .commonAttributes(commonAttributes)
                                          .build();

        } catch (ClassNotFoundException e) {
            logger.info("New Relic Java Agent未加载,指标不会上报到New Relic。");
        }

        this.reporter = tmpReporter;

        // 启动上报
        start();
    }

    public void start() {
        if (reporter == null) {
            return;
        }
        reporter.start(1, TimeUnit.SECONDS);
    }

    public void stop() {
        if (reporter == null) {
            return;
        }
        reporter.stop();
    }
}

当前代码能正常上报指标到NewRelic,但无法通过实体过滤找到这些指标,疑似指标被归类到「所有指标」的根实体中。需要解决如何让指标关联到对应的APM实体。


解决方案

问题出在上报指标时没有关联到NewRelic的实体标识属性,导致NewRelic无法将指标归属到对应的APM服务实体。需要在commonAttributes中添加实体关联的核心属性,常用方案如下:

1. 添加实体GUID与服务名称

从NewRelic Agent的API和配置中直接获取当前应用的唯一标识,添加到公共属性:

// 定义APM和服务中可见的自定义属性
Attributes commonAttributes = new Attributes();
// 添加实体唯一GUID,直接从Agent获取当前应用实体标识
commonAttributes.put("entity.guid", NewRelic.getAgent().getEntity().getGuid());
// 添加服务名称,对应newrelic.yaml中的app_name配置
commonAttributes.put("service.name", config.getValue("app_name"));

2. 备选:添加实体类型与名称

若无法获取实体GUID,可通过实体类型+名称的组合来关联:

commonAttributes.put("entity.type", "SERVICE");
commonAttributes.put("entity.name", config.getValue("app_name"));

修改后的NewRelicMetricsService核心代码片段:

try {
    Class.forName("com.newrelic.api.agent.NewRelic");
    Config config = NewRelic.getAgent().getConfig();

    SenderConfiguration sender = MetricBatchSender.configurationBuilder()
            .apiKey(config.getValue("license_key"))
            .useLicenseKey(true)
            .httpPoster(new OkHttpPoster(Duration.ofSeconds(2)))
            .build();

    MetricBatchSender metricBatchSender = MetricBatchSender.create(sender);

    // 定义APM和服务中可见的自定义属性
    Attributes commonAttributes = new Attributes();
    // 关联到当前APM实体的关键属性
    commonAttributes.put("entity.guid", NewRelic.getAgent().getEntity().getGuid());
    commonAttributes.put("service.name", config.getValue("app_name"));

    tmpReporter = NewRelicReporter.build(metricRegistry.getRegistry(), metricBatchSender)
                                  .commonAttributes(commonAttributes)
                                  .build();

} catch (ClassNotFoundException e) {
    logger.info("New Relic Java Agent未加载,指标不会上报到New Relic。");
}

原理说明

NewRelic的指标系统通过entity.guid、service.name这类属性识别指标所属实体。如果缺少这些属性,上报的指标会被默认归类到根级别的「所有指标」中,无法关联到具体的APM服务实体。添加这些属性后,NewRelic就能自动将指标映射到对应的应用实体,你就可以在实体过滤中找到这些指标了。


内容的提问来源于stack exchange,提问作者tftd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 06:27:52