Nikolay,

>> 1. There is no unified approach to adding metrics during development.

> Yes, we have it.
> Just call `MetricRegistry#longMetric` or other method and you got your 
> counter.

I talk about code structure, not API.

>> Now the logic is spread throughout the code base and there is now any
>> way to find proper place where particular metric could be added to the
>> registry

> You should obtain your counter in the place where it be updated or exported.

And again, I talk about code structure, not API.

>> Moreover, we can create registry in one place and add some
>> set of metrics to the registry in another place and we have many
>> examples of it.

> What's wrong with this approach?

Bad code organization. Redundant synchronization because there is no
real life cases for changing metric registry content  at runtime.

>> Of course, metrics API allows it and it is meaningful drawback from my point 
>> view

> I know many cases where specific metrics was not implemented because of 
> development complexity.

>  From my point of view, we shouldn't complicate process of creation of 
> specific metric.
> It will slow down creation of new metric therefore slow down product evolving.

My proposal target is simplification of metrics adding to the code.
There is no any complexity.

>> 2. Introduce MetricRegistryBuilder that returns immutable instance of 
>> MetricRegistry

> We can extend `AttibuteWalkerGenerator` to generate all required boilerplace 
> code (for enabling/disabling metrics, etc.)

I think it is redundant complexity. Code generation is is a
controversial approach. Metrics and system vies is not a case for code
generation. IMHO.

> I want to bold my statement: We should keep metric creation as simple as we 
> can.

Please, read my proposal again. Main point is code structure changing
in order to simplify adding new metrics for developer.

> Developer of specific metric shouldn't change dozens of static interfaces, 
> implementations, enable/disable methods.

Absolutely agree. But metric sources should have unified life-cycle methods.

> It should only update metric in the specific places in core code.

It is not related with my proposal and will true after implementation.

On Fri, Sep 20, 2019 at 1:03 PM Nikolay Izhikov <nizhi...@apache.org> wrote:
>
> Hello, Andrey.
>
> Thanks for starting this discussion.
>
> > 1. There is no unified approach to adding metrics during development.
>
> Yes, we have it.
> Just call `MetricRegistry#longMetric` or other method and you got your 
> counter.
>
> > Now the logic is spread throughout the code base and there is now any
> > way to find proper place where particular metric could be added to the
> > registry
>
> You should obtain your counter in the place where it be updated or exported.
> If you update the same counter in several place, it seems to be as a bad code 
> design which should be investigated.
>
> I treat this as a feature that adds flexibility to the Ignite code.
>
> > Moreover, we can create registry in one place and add some
> > set of metrics to the registry in another place and we have many
> > examples of it.
>
> What's wrong with this approach?
> I treat this as a feature, also.
>
> > Of course, metrics API allows it and it is meaningful drawback from my 
> > point view
>
> The goal of Metric API was simplifying of metric creation.
> Because, in the past years Ignite doesn't have a way to create meaningfull 
> metric.
> I know many cases where specific metrics was not implemented because of 
> development complexity.
>
> From my point of view, we shouldn't complicate process of creation of 
> specific metric.
> It will slow down creation of new metric therefore slow down product evolving.
>
> > 2. Introduce MetricRegistryBuilder that returns immutable instance of 
> > MetricRegistry
>
> If we want immutable MetricRegistry we can create simple POJO objects with 
> metric getters as follows
>
> public class CacheMetric {
>         public LongMetric putsCount() { ... }
>         public LongMetric getsCount() { ... }
> }
>
> and export it using `AttributeWalker` approach I implement in System View 
> contribution.
> There is no need for a HashMap unified solution.
>
> We can extend `AttibuteWalkerGenerator` to generate all required boilerplace 
> code (for enabling/disabling metrics, etc.)
>
> I want to bold my statement: We should keep metric creation as simple as we 
> can.
> Developer of specific metric shouldn't change dozens of static interfaces, 
> implementations, enable/disable methods.
> It should only update metric in the specific places in core code.
>
>
> В Пн, 26/08/2019 в 20:36 +0300, Andrey Gura пишет:
> > Hi, Igniters!
> >
> > I'm working on some metrics related aspects and it seems that we have
> > missed some points regarding the metrics management. There are at
> > least two major problems from my point of view.
> >
> > Problem definition.
> > ---------------------------
> >
> > 1. There is no unified approach to adding metrics during development.
> >
> > It would be grate to have one common place where developer should add
> > new metrics or can find answer for question "What kind of metrics do
> > we have for smth?". I talk only about Ignite internal metrics, not
> > user's metrics.
> >
> > Now the logic is spread throughout the code base and there is now any
> > way to find proper place where particular metric could be added to the
> > registry. Moreover, we can create registry in one place and add some
> > set of metrics to the registry in another place and we have many
> > examples of it.
> >
> > Of course, metrics API allows it and it is meaningful drawback from my
> > point view. MetricRegistry is mutable and could be modified at any
> > place of the code and any time of program execution. It  allows
> > developer follow the simplest way which is usually wrong. Also
> > GridMetricManager.registry() method has two responsibilities: it
> > creates and lookups registries. When I see registry() method call in
> > the code I can't assume what exactly intention had developer (is it
> > first creation of registry or modification of existing registry).
> >
> > 2. There is no unified approach to enabling/disabling metrics.
> >
> > Here I mean both problems: runtime enabling/disabling and code design
> > that should allow do it in proper way. There is JIRA issue [1] about
> > it.
> >
> > Now some metrics can be enabled/disabled in static configuration and
> > at runtime (cache metrics for example) and other don't have such
> > functionality. It should be unified. Any metrics set (eq.
> > MetricRegistry in current implementation) should have one unified
> > approach for enabling/disabling. Also we should provide infrastructure
> > for it as part of metrics framework.
> >
> >
> > Proposed solution.
> > ---------------------------
> >
> > 1. Introduce new interface, e.g. MetriсSource that is responsible for
> > metrics life cycle for one metrics source (e.g. cache metrics, system
> > metrics, etc.) Each component with metrics should register own
> > implementation of this interface in metrics manager
> > (GridMetricManager).
> >
> > Interface declares the following methods:
> >
> > - String name() - returns sources name that will be available in
> > special MBean responsible for access for metrics manager.
> >
> > - MetricRegistry enable() - returns MetricRegistry instance with
> > allready registered metrics. Metric registry has the same name as name
> > returned by MetricSource.name() method. This method can be invoked on
> > node start (if metrics are statically enabled) or as result of metric
> > enabling via MBean. As result all instance of MetricSource will have
> > all metric instances initialized and MetricRegistry must be added to
> > the registries map by GridMetricManager.
> >
> > - void disable() - Should be invoked after removing corresponding
> > MetricRegistry from GridMetricManager.registries. The responsibility
> > is destroying of all metric instances (just assign null). This method
> > can be invoked during stopping component (e.g. cache stop, index
> > removing) or as result of metric disabling via MBean.
> >
> > - boolean enabled() - Actual state for current implemntation.
> >
> > NOTE 1: Adding/removing metric registries in GridMetricManager should
> > be performed with copy-on-write semantic in order to avoid possible
> > data races in related threads (e.g. exporters). It also allows avoid
> > data copy during exporting (just use link to the registries). Also we
> > can avoid using ConcurrentHashMap in such case. But of course
> > additional copies will be created per each registries map
> > modification. But we assume that it isn't frequent operation.
> >
> > NOTE 2: MetricSource interface specific implementation is also
> > responsible for keeping direct references to metric instances and also
> > for functionality related with metric values calculation (including
> > checking whether metrics are enabled or not).
> >
> > NOTE 3: GridMetricManager is responsible for
> > registration/deregistration of MBeans corresponding to each metrics
> > source. GridMetricManager is responsible for proper actions sequence
> > (e.g. we should first create metric registry and after it add it to
> > registries collection).
> >
> > At this point we have:
> >
> > - Way to find out all metrics in the system just navigating throughout
> > all implementations of MetricSource interface.
> > - Unified approach to metric creation.
> > - Unified approach to metric enabling/disabling at runtime.
> >
> > 2. Introduce MetricRegistryBuilder that returns immutable instance of
> > MetricRegistry. It will force developer to write code related with
> > metric creation at exactly one place. It also allows to avoid
> > MetricRegistry modification at runtime. Also we should remove
> > GridMetricRegistry.registry() method and introduce two new methods:
> > register(MetricRegistry) and unregister(String registryName). Each
> > method should assert that no old value for register() case or registry
> > was deleted for unregister case (we have some problems with it now,
> > e.g. for cache with near cache configuration).
> >
> > At this point we have some additional guaranties of proper metrics
> > framework usage. Such design also will allow optimize metric exporters
> > because it can sure that metric registry will not modified at runtime
> > with out removing and conseqent adding registry to the
> > GridMetricManager.registires map.
> >
> > 3. Introduce MetricManagementMBean that returns list of all metric
> > sources with boolean flag that indicates whether metrics are enabled
> > or disabled for this source. List of all sources should be supported
> > by GridMetricManager (so metricSources collection should be added and
> > accessors).
> >
> > This MBean also should provide methods for enabling and disabling metrics.
> >
> > At this point we have interface for enabling/disabling metrics via JMX
> > and basis for implementation other tools (e.g. we can manage metrics
> > via control.sh after additional development).
> >
> > All current metrics related code should be refactored accordingly this
> > proposal and it is most complex and time consuming part.
> >
> > I'm ready to do all this things. Also anybody can implement and contribute 
> > this.
> >
> > But first I would like to hear your thoughts and ideas.
> >
> > Thanks!
> >
> > [1] https://issues.apache.org/jira/browse/IGNITE-11927

Reply via email to