It is useful for user to work with own metrics, not only with provided by Ignite. The current public metrics API doesn't expose any method to add or delete additional metrics.
The most important reason to provide custom is probably the convenience of collecting of desired metrics using one platform, the same client, through the same API. This feature can simplify user application.
public static final class TestCustomMetricsService implements TestService {
@IgniteInstanceResource
private Ignite ignite;
@ServiceContextResource
private ServiceContext ctx;
private AtomicReference<UUID> remoteId;
private final AtomicInteger metricValue = new AtomicInteger();
@Override public void init() throws Exception {
remoteId = new AtomicReference<>();
// Registers metric "custom.service.svc.filteredInvocation"
ignite.metrics().customRegistry(regName(ctx.name())).gauge("filteredInvocation", metricValue::get, "Counter of speceific service invocation.");
// Registers metric "custom.service.svc.loaded"
ignite.metrics().customRegistry(regName(ctx.name())).gauge("loaded", () -> metricValue.get() >= 100, "Load flag.");
// Registers metric "custom.service.svc.remote.classId"
ignite.metrics().customRegistry(regName(ctx.name())).gauge("remote.classId", () -> remoteId.get(), UUID.class, "Remote system class id.");
}
@Override public void cancel() {
refresh();
ignite.metrics().customRegistry(regName(ctx.name())).remove(COUNTER_METRIC_NAME);
}
@Override public void refresh() {
metricValue.set(0);
remoteId.set(null);
}
@Override public void invoke(int param) {
if (ctx.isCancelled())
return;
remoteId.compareAndSet(null, UUID.randomUUID());
// Updates metric sometimes.
if (!ctx.isCancelled() && param % 10 == 0)
metricValue.set(param / 10);
}
private static String regName(String svcName) {
return "service." + svcName;
}
}
private static final class TestCustomMetricsComputeTask extends ComputeTaskAdapter<Void, Long> {
private static final class TestComputeJob extends ComputeJobAdapter {
@IgniteInstanceResource
private Ignite ignite;
@Override public Long execute() throws IgniteException {
long val = 0;
// Some job limit.
long limit = 300 + ThreadLocalRandom.current().nextLong(700);
// Registers metric "custom.task.test.current"
LongValueMetric metricCur = ignite.metrics().customRegistry("task.test").longMetric("current", null);
// Registers metric "custom.task.test.total.sum"
LongSumMetric metricTotal = ignite.metrics().customRegistry("task.test").longAdderMetric("total.sum", null);
// Registers metric "custom.task.test.ticks"
LongSumMetric metricTicks = ignite.metrics().customRegistry("task.test").longAdderMetric("ticks", null);
while (!isCancelled() && val < limit) {
// Does some job.
try {
U.sleep(ThreadLocalRandom.current().nextInt(50));
}
catch (IgniteInterruptedCheckedException ignored) {
//No op.
}
long increment = ThreadLocalRandom.current().nextLong(100);
val += increment;
metricTicks.increment()
}
metricCur.value(val);
metricTotal.add(val);
return isCancelled() ? 0 : val;
}
}
}
Further Steps
We already have implementations of more complex and useful metrics. We could also store custom metrics. Thus, the development stages might be:
An API to expose internals read-only internal metrics was already suggested. Might be joined with the custom metrics. By the methods like "findRegistry" we can also return read-only internal metrics.
Extending the initial API with metrics like Histogram or HitRate.
Introduce a permission for custom metric management.
Storing registered custom metrics.
Allowing to change settings of configurable custom metrics like histograms.