We have a custom webapp hat is using HikariCP. The application is compiled into a jar
and then started in a docker container. Depending on the environment we are loading the newrelic-agent.jar
via the -javaagent
flag when we're starting the webapp.jar
.
Our HikariCP setup looks like this:
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);
}
We have created a service that starts the reporter upon application boot based whether or not the NewRelic class exists. Since we're loading the java agent
it does also provide us with the parsed newrelic.yaml
configuration which we're re-using down below:
public class NewRelicMetricsService {
private static final Logger logger = LoggerFactory.getLogger(NewRelicMetricsService.class);
private final NewRelicReporter reporter;
@Inject
public NewRelicMetricsService(ApplicationMetricsRegistry metricRegistry) {
NewRelicReporter tmpReporter = null;
// Check if the NewRelic java agent has been loaded.
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);
// Use this to define custom attributes visible in the APM & Service.
Attributes commonAttributes = new Attributes();
tmpReporter = NewRelicReporter.build(metricRegistry.getRegistry(), metricBatchSender)
.commonAttributes(commonAttributes)
.build();
} catch (ClassNotFoundException e) {
logger.info("New Relic java agent has not been loaded. Metrics will not be showing in New Relic.");
}
this.reporter = tmpReporter;
// Start reporting.
start();
}
public void start() {
if (reporter == null) {
return;
}
reporter.start(1, TimeUnit.SECONDS);
}
public void stop() {
if (reporter == null) {
return;
}
reporter.stop();
}
}
The code above works just fine and metrics start appearing in NewRelic under Metrics
.
However, once you attempt to filter the metrics via entity
-- those metrics are nowhere to be seen. It is as if the metrics are scoped to be in the "root" entity where you see "all metrics".
Not entirely sure what's wrong here. Does anybody have any ideas?
Maybe we need to add a specific/additional attributes
?
The problem is that the Telemetry SDK does not know about the application (entity) you are instrumenting.
If you set entity.guid
to the common attributes in your Telemetry SDK config, it will link the metrics to the application.
String entityGuid = NewRelic.getAgent().getLinkingMetadata().get("entity.guid");
Attributes commonAttributes = new Attributes()
.put("entity.guid", entityGuid);
Alternatively you could use the agent API (see "Create and accumulate custom metrics").