Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

It is useful for user to work with own metrics, not only with provided by Ignite. Current public metrics API doesn't expose any method to add or delete additional metrics. We should allow user to register custom 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.

...

  • Some metrics may not be provided yet and user registers own.
  • Metrics for load balancing.
  • Various metrics of business processes or related to user application.
  • Administration metrics.
  • Security-related metrics.

...

  • Custom Metrics are based on the New Metric System.
  • Custom metric name always begins with the prefix "custom.".
  • GridMetricManager handles custom metrics.

  • Allow registration of simple metrics like LongMetric, DoubleMetric, ObjectMetric Provide essential ready-to-use metrics like LongMetric which can be exported by the a existing metric exporters like JMX exporter.exporter.
  • User can store own metrics in different registers corresponding to metrics groups.
  • Custom metrics are separated from the internals by registry name prefix "custom.".
  • Custom metrics management might require a permission.
  • We should document examples of effecient metrics implementations like LongAdder.

...

   1. New metrics facade to Ignite:

In future, we might want to provide an internal API to obtain metrics like this. It could be quite different and we should split them. 

package org.apache.ignite;

public interface Ignite {
   public IgniteMetricsIgniteCustomMetrics metrics();

}

   2. New interface

...

IgniteCustomMetrics

To keep custom metrics detached from the internals, we should either automaticall add a prefix to custom name or throw an exception if provided metric name doesn't start with that prefix.


package org.apache.ignite;

/**
* Custom metric manager. Allows to add owncustom metrics. inCustom metrics registers is always stored with names starting with "custom.". name prefix "custom.".
* If provided registry name is "a.b.regname", it is automatically converted to "custom.a.b.regname".
* If the name is "custom.a.b.regname", it is used as is.
*/
public interface IgniteMetricsIgniteCustomMetrics {
/**
* Registers metric in register 'custom.' +registry {@code registryName}. Adds new metric registerregistry if absent.
*
* @return New {@codePrevious metric} or previous metric if it already exists with the same name. {@code metric} otherwise.
*/
<T extends Metric> T metric(String registryName, String metricName, T metric);

/** Removes metric from register 'custom.' +registry {@code registryName}. */
void removeMetric(String registryName, String metricName);

/** @return Metric registry named '"custom." + {@code registryName}'. */
ReadOnlyMetricRegistry registry(String registryName);

/** Removes registry named '"custom." + {@code registryName}'. */
void removeRegistry(String registryName);


// Simple type metrics. Int, Long and Double should be enough.

/**
* Registers a {@link LongMetric} in register 'custom.' + registry {@code registryName}. Adds new metric registry if absent.
*
* @return New or previously registered long value setter Previous long value setter if it already exists with the same name. A new one otherwise.
*/
LongConsumer longMetric(String registryName, String metricName, @Nullable String description);

/**
* Registers a {@link DoubleMetric} in register 'custom.' + registry {@code registryName}. Adds new metric registry if absent.
*
* @return New or previously registered double value setterPrevious double value setter if it already exists with the same name. A new one otherwise.
*/
DoubleConsumer doubleMetric(String registryName, String metricName, @Nullable String description);

/**
* Registers a {@link BooleanMetricIntMetric} in register 'custom.' +registry {@code registryName}. Adds new metric registry if absent.
*
* @return New or previously registered boolean value setter Previous int value setter if it already exists with the same name. A new one otherwise.
*/
Consumer<Boolean>IntConsumer booleanMetric(String registryName, String metricName, @Nullable String description);



// Might be useful the gauges.

/**
* Registers a {@link ObjectMetricLongMetric} metric in register 'custom.' + registry {@code registryName} with long value supplier {@code registryNamevalueSupplier}.
* Adds new metric registry if absent.
*
* @return New {@code True} if metric was added. {@code False} if another meric already exists under the same name. or previously registered object setter.
*/
<T> Consumer<T> objectMetricboolean longMetric(String registryName, String metricName, Class<T>LongSupplier valueTypevalueSupplier, @Nullable String description);

// Might be useful the gauges:
/**
* Registers a {@link LongMetricDoubleMetric} metric in register 'custom.' + registry {@code registryName} with longdouble value supplier {@code valueSupplier}.
* Adds new metric registry if absent.
*
* @return {@code True} if metric was added. {@code False} if another meric already exists under the same name.
*/
boolean longMetricdoubleMetric(String registryName, String metricName, LongSupplierDoubleSupplier valueSupplier, @Nullable String description);

/**
* Registers a {@link DoubleMetricIntMetric} metric in register 'custom.' + registry {@code registryName} with doubleint value supplier {@code valueSupplier}.
* Adds new metric registry if absent.
*
* @return {@code True} if metric was added. {@code False} if another meric already exists under the same name.
*/
boolean doubleMetricintMetric(String registryName, String metricName, DoubleSupplierBooleanSupplier valueSupplier, @Nullable String description);


   // Additionnaly, we might expose an object metrics API.

/**
* Registers a {@link BooleanMetricObjectMetric} metric in register 'custom.' + registry {@code registryName} with booleanobject value supplier {@code valueSupplier}.
* Adds new metric registry if absent.
*
* @return {@code True} if metric was added. {@code False} if another meric already exists under the same name.
*/
<T> boolean booleanMetricobjectMetric(String registryName, String metricName, Class<T> valueType, BooleanSupplierSupplier<T> valueSupplier, @Nullable String description);

/**
* Registers a {@link ObjectMetric} metric in register 'custom.' + registry {@code registryName} with object value supplier {@code valueSupplier}.
* Adds new metric registry if absent.
*
* @return {@codeNew True}or ifpreviously metricregistered wasobject added. {@code False} if another meric already exists under the same name. setter.
*/
<T> booleanConsumer<T> objectMetric(String registryName, String metricName, Class<T> valueType, Supplier<T> valueSupplier, @Nullable String description);
}

Risks and Assumptions

  • Custom metrics can affect the performance.
  • There could be race conditions on metric registrations.
  • We do not provide varuous useful metric implementatons.
  • Custom metrics aren't stored and require re-registration after node restart. At least at the first phase.

Phases

Further Steps

We already have implementations of more complex and useful metricsThe custom metric API might be also enriched with more complex metrics like historgams. We could also store custom metrics and their configurations. Thus, the development steps stages might be:

  1. Implementation of the described initial API.
  2. Extending the this API with metrics like Histogram, HitRate. Allowing to configure metrics, LongAdder.
  3. Introduce a permission of custom metric management.
  4. Storing registered custom metrics with their configurations..
  5. Allowing to change settings of configurable custom metrics like histograms.

References

  1. IEP-35 Monitoring & Profiling
  2. Ticket of a public metric API

Discussion Links

Tickets