agura commented on code in PR #957:
URL: https://github.com/apache/ignite-3/pull/957#discussion_r936438725


##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/composite/CompositeMetric.java:
##########
@@ -0,0 +1,33 @@
+/*

Review Comment:
   IMHO, it doesn't make sense to have two different packages `scalar` and 
`composite`. A metrics user should not think about such things. Also, I think 
that there is no real need for separate packages for metrics implementation at 
all. All entities could be placed in one `metrics` package.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/Metric.java:
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Basic metric interface.
+ */
+public interface Metric {
+    /**
+     * Name of the metric.
+     *
+     * @return Name of the metric.
+     */
+    String name();
+
+    /**
+     * Description of the metric.
+     *
+     * @return Description of the metric.
+     */
+    String description();
+
+    /**
+     * String representation of metric value.
+     *
+     * @return String representation of metric value.
+     */
+    @Nullable
+    String getAsString();

Review Comment:
   It seems that `getValueAsString` is more descriptive name of the method.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/AbstractMetric.java:
##########
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Abstract metric.
+ */
+public abstract class AbstractMetric implements Metric {
+    /** Metric name. It is local for a particular {@link MetricSet}. */
+    private final String name;
+
+    /** Metric description. */
+    private final String desc;

Review Comment:
   `@Nullable`



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/LongMetric.java:
##########
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import org.apache.ignite.internal.metrics.Metric;
+
+/**
+ * Interface for the metrics that holds long primitive.
+ */
+public interface LongMetric extends Metric {
+    /**
+     * Value of the metric.
+     *
+     * @return Value of the metric.
+     */
+    public long value();

Review Comment:
   `public` is redundant.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/Metric.java:
##########
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Basic metric interface.
+ */
+public interface Metric {
+    /**
+     * Name of the metric.
+     *
+     * @return Name of the metric.
+     */
+    String name();
+
+    /**
+     * Description of the metric.
+     *
+     * @return Description of the metric.
+     */
+    String description();

Review Comment:
   `@Nullable`



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/AbstractMetric.java:
##########
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Abstract metric.
+ */
+public abstract class AbstractMetric implements Metric {
+    /** Metric name. It is local for a particular {@link MetricSet}. */
+    private final String name;
+
+    /** Metric description. */
+    private final String desc;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     */
+    public AbstractMetric(String name, String desc) {

Review Comment:
   Description should be annotated as `@Nullable`.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/LongMetric.java:
##########
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import org.apache.ignite.internal.metrics.Metric;
+
+/**
+ * Interface for the metrics that holds long primitive.
+ */
+public interface LongMetric extends Metric {
+    /**
+     * Value of the metric.
+     *
+     * @return Value of the metric.
+     */
+    public long value();
+
+    /** {@inheritDoc} */
+    @Override public default String getAsString() {

Review Comment:
   `public` is redundant.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/DoubleMetric.java:
##########
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import org.apache.ignite.internal.metrics.Metric;
+
+/**
+ * Basic interface for double metric.
+ */
+public interface DoubleMetric extends Metric {
+    /**
+     * Value of the metric.
+     *
+     * @return Value of the metric.
+     */
+    public double value();
+
+    /** {@inheritDoc} */
+    @Override public default String getAsString() {

Review Comment:
   `public` is redundant.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/AtomicIntMetric.java:
##########
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Integer metric is implemented as a volatile {@code int} value.
+ */
+public class AtomicIntMetric extends AbstractMetric implements IntMetric {
+    /** Field updater. */
+    private static final AtomicIntegerFieldUpdater<AtomicIntMetric> updater =
+            AtomicIntegerFieldUpdater.newUpdater(AtomicIntMetric.class, "val");
+
+    /** Value. */
+    private volatile int val;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     */
+    public AtomicIntMetric(String name, @Nullable String desc) {
+        super(name, desc);
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param x Value to be added.
+     */
+    public void add(int x) {
+        updater.addAndGet(this, x);
+    }
+
+    /** Increment the metric. */
+    public void increment() {

Review Comment:
   Please, use `updater.incrementAndGet` here. There is different ways to 
implement inc/dec and some of them could be more effective then CAS.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/DoubleMetric.java:
##########
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import org.apache.ignite.internal.metrics.Metric;
+
+/**
+ * Basic interface for double metric.
+ */
+public interface DoubleMetric extends Metric {
+    /**
+     * Value of the metric.
+     *
+     * @return Value of the metric.
+     */
+    public double value();

Review Comment:
   `public` is redundant.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/AtomicIntMetric.java:
##########
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Integer metric is implemented as a volatile {@code int} value.
+ */
+public class AtomicIntMetric extends AbstractMetric implements IntMetric {
+    /** Field updater. */
+    private static final AtomicIntegerFieldUpdater<AtomicIntMetric> updater =
+            AtomicIntegerFieldUpdater.newUpdater(AtomicIntMetric.class, "val");
+
+    /** Value. */
+    private volatile int val;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     */
+    public AtomicIntMetric(String name, @Nullable String desc) {
+        super(name, desc);
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param x Value to be added.
+     */
+    public void add(int x) {
+        updater.addAndGet(this, x);
+    }
+
+    /** Increment the metric. */
+    public void increment() {
+        add(1);
+    }
+
+    /** Decrement the metric. */
+    public void decrement() {
+        add(-1);

Review Comment:
   Please, use `updater.decrementAndGet` here.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/LongAdderMetric.java:
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import java.util.concurrent.atomic.LongAdder;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Long metric based on {@link LongAdder}.
+ */
+public class LongAdderMetric extends AbstractMetric implements LongMetric {
+    /** Value. */
+    private volatile LongAdder val;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     */
+    public LongAdderMetric(String name, @Nullable String desc) {
+        super(name, desc);
+
+        this.val = new LongAdder();
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param x Value to be added.
+     */
+    public void add(long x) {
+        val.add(x);
+    }
+
+    /**
+     * Increment the metric.
+     */
+    public void increment() {
+        add(1);
+    }
+
+    /**
+     * Decrement the metric.
+     */
+    public void decrement() {

Review Comment:
   Please use direct calls like `val.add(-1)` or `val.decrement` here



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/AtomicLongMetric.java:
##########
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Long metric implementation.
+ */
+public class AtomicLongMetric extends AbstractMetric implements LongMetric {
+    /** Field updater. */
+    static final AtomicLongFieldUpdater<AtomicLongMetric> updater =
+            AtomicLongFieldUpdater.newUpdater(AtomicLongMetric.class, "val");
+
+    /** Field value. */
+    private volatile long val;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     */
+    public AtomicLongMetric(String name, @Nullable String desc) {
+        super(name, desc);
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param x Value to be added.
+     */
+    public void add(long x) {
+        updater.getAndAdd(this, x);
+    }
+
+    /** Adds 1 to the metric. */
+    public void increment() {
+        add(1);
+    }
+
+    /** Adds -1 to the metric. */
+    public void decrement() {
+        add(-1);

Review Comment:
   Please, use `updater.decrementAndGet` here.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/HitRateMetric.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import static org.apache.ignite.internal.util.IgniteUtils.currentTimeMillis;
+import static org.apache.ignite.internal.util.IgniteUtils.ensure;
+
+import java.util.concurrent.atomic.AtomicLongArray;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Accumulates approximate hit rate statistics.
+ * Calculates number of hits in last {@code rateTimeInterval} milliseconds.
+ * Algorithm is based on circular array of {@code size} hit counters, each is 
responsible for last corresponding time
+ * interval of {@code rateTimeInterval}/{@code size} milliseconds. Resulting 
number of hits is sum of all counters.
+ *
+ * <p>Implementation is nonblocking and protected from hits loss.
+ * Maximum relative error is 1/{@code size}.
+ * 2^55 - 1 hits per interval can be accumulated without numeric overflow.
+ */
+public class HitRateMetric extends AbstractMetric implements LongMetric {
+    /** Default counters array size. */
+    public static final int DFLT_SIZE = 10;
+
+    /** Bits that store actual hit count. */
+    private static final int TAG_OFFSET = 56;
+
+    /** Useful part mask. */
+    private static final long NO_TAG_MASK = ~(-1L << TAG_OFFSET);
+
+    /** Time interval when hits are counted to calculate rate, in 
milliseconds. */
+    private final long rateTimeInterval;
+
+    /** Counters array size. */
+    private final int size;
+
+    /** Tagged counters. */
+    private final AtomicLongArray taggedCounters;
+
+    /** Last hit times. */
+    private final AtomicLongArray lastHitTimes;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param rateTimeInterval Rate time interval in milliseconds.
+     */
+    public HitRateMetric(String name, @Nullable String desc, long 
rateTimeInterval) {
+        this(name, desc, rateTimeInterval, DFLT_SIZE);
+    }
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param rateTimeInterval Rate time interval in milliseconds.
+     * @param size Counters array size.
+     */
+    public HitRateMetric(String name, @Nullable String desc, long 
rateTimeInterval, int size) {
+        super(name, desc);
+
+        ensure(rateTimeInterval > 0, "rateTimeInterval should be positive");
+        ensure(size > 1, "Minimum value for size is 2");
+
+        this.rateTimeInterval = rateTimeInterval;
+        this.size = size;
+        taggedCounters = new AtomicLongArray(size);
+        lastHitTimes = new AtomicLongArray(size);
+    }
+
+    /**
+     * Adds x to the metric.

Review Comment:
   What is `x`? Java doc is not descriptive enough.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/composite/DistributionMetric.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLongArray;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.scalar.LongGauge;
+import org.apache.ignite.internal.metrics.scalar.LongMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Distribution metric calculates counts of measurements that gets into each 
bounds interval.
+ * Note, that {@link #value()} will return array length of {@code 
bounds.length + 1}.
+ * Last element contains count of measurements bigger than most right value of 
bounds.
+ */
+public class DistributionMetric extends AbstractMetric implements 
CompositeMetric {
+    /** Count of measurement for each bound. */
+    private final AtomicLongArray measurements;
+
+    /** Bounds of measurements. */
+    private final long[] bounds;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param bounds Bounds of the buckets.
+     */
+    public DistributionMetric(String name, @Nullable String desc, long[] 
bounds) {
+        super(name, desc);
+
+        assert bounds != null && bounds.length > 0;
+        assert isSorted(bounds);
+
+        this.bounds = bounds;
+        this.measurements = new AtomicLongArray(bounds.length + 1);
+    }
+
+    /**
+     * Check whether given array is sorted.
+     *
+     * @param arr Array to check.
+     * @return {@code True} if array sorted, {@code false} otherwise.
+     */
+    public static boolean isSorted(long[] arr) {
+        if (arr == null || arr.length < 2) {
+            return true;
+        }
+
+        for (int i = 1; i < arr.length; i++) {
+            if (arr[i - 1] > arr[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Sets value.
+     *
+     * @param x Value.
+     */
+    public void value(long x) {
+        assert x >= 0;
+
+        //Expect arrays of few elements.
+        for (int i = 0; i < bounds.length; i++) {
+            if (x <= bounds[i]) {
+                measurements.incrementAndGet(i);
+
+                return;
+            }
+        }
+
+        measurements.incrementAndGet(bounds.length);
+    }
+
+    /** {@inheritDoc} */
+    public long[] value() {
+        long[] res = new long[measurements.length()];
+
+        for (int i = 0; i < measurements.length(); i++) {
+            res[i] = measurements.get(i);
+        }
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public @Nullable String getAsString() {
+        return asScalarMetrics().stream()

Review Comment:
   Please, rewrite it without streams. During exporting this implementation 
will be on a hot path and can waste resources.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/composite/DistributionMetric.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLongArray;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.scalar.LongGauge;
+import org.apache.ignite.internal.metrics.scalar.LongMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Distribution metric calculates counts of measurements that gets into each 
bounds interval.
+ * Note, that {@link #value()} will return array length of {@code 
bounds.length + 1}.
+ * Last element contains count of measurements bigger than most right value of 
bounds.
+ */
+public class DistributionMetric extends AbstractMetric implements 
CompositeMetric {
+    /** Count of measurement for each bound. */
+    private final AtomicLongArray measurements;
+
+    /** Bounds of measurements. */
+    private final long[] bounds;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param bounds Bounds of the buckets.
+     */
+    public DistributionMetric(String name, @Nullable String desc, long[] 
bounds) {
+        super(name, desc);
+
+        assert bounds != null && bounds.length > 0;
+        assert isSorted(bounds);
+
+        this.bounds = bounds;
+        this.measurements = new AtomicLongArray(bounds.length + 1);
+    }
+
+    /**
+     * Check whether given array is sorted.
+     *
+     * @param arr Array to check.
+     * @return {@code True} if array sorted, {@code false} otherwise.
+     */
+    public static boolean isSorted(long[] arr) {
+        if (arr == null || arr.length < 2) {
+            return true;
+        }
+
+        for (int i = 1; i < arr.length; i++) {
+            if (arr[i - 1] > arr[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Sets value.
+     *
+     * @param x Value.
+     */
+    public void value(long x) {
+        assert x >= 0;
+
+        //Expect arrays of few elements.
+        for (int i = 0; i < bounds.length; i++) {
+            if (x <= bounds[i]) {
+                measurements.incrementAndGet(i);
+
+                return;
+            }
+        }
+
+        measurements.incrementAndGet(bounds.length);
+    }
+
+    /** {@inheritDoc} */
+    public long[] value() {
+        long[] res = new long[measurements.length()];
+
+        for (int i = 0; i < measurements.length(); i++) {
+            res[i] = measurements.get(i);
+        }
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public @Nullable String getAsString() {
+        return asScalarMetrics().stream()
+            .map(m -> m.name() + ":" + ((LongMetric) m).value())
+            .collect(Collectors.joining(", ", "[", "]"));
+    }
+
+    /**
+     * Bounds of the buckets of distribution.
+     *
+     * @return Bounds of the buckets of distribution.
+     */
+    public long[] bounds() {
+        return bounds;
+    }
+
+    /** {@inheritDoc} */
+    @Override public List<Metric> asScalarMetrics() {

Review Comment:
    A lot of actions. You can do it only once and always return this list just 
because you use gauges that always will return actual values from measurements.
    
   Also, return list should be immutable.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/composite/DistributionMetric.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLongArray;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.scalar.LongGauge;
+import org.apache.ignite.internal.metrics.scalar.LongMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Distribution metric calculates counts of measurements that gets into each 
bounds interval.
+ * Note, that {@link #value()} will return array length of {@code 
bounds.length + 1}.
+ * Last element contains count of measurements bigger than most right value of 
bounds.
+ */
+public class DistributionMetric extends AbstractMetric implements 
CompositeMetric {
+    /** Count of measurement for each bound. */
+    private final AtomicLongArray measurements;
+
+    /** Bounds of measurements. */
+    private final long[] bounds;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param bounds Bounds of the buckets.
+     */
+    public DistributionMetric(String name, @Nullable String desc, long[] 
bounds) {
+        super(name, desc);
+
+        assert bounds != null && bounds.length > 0;
+        assert isSorted(bounds);
+
+        this.bounds = bounds;
+        this.measurements = new AtomicLongArray(bounds.length + 1);
+    }
+
+    /**
+     * Check whether given array is sorted.
+     *
+     * @param arr Array to check.
+     * @return {@code True} if array sorted, {@code false} otherwise.
+     */
+    public static boolean isSorted(long[] arr) {

Review Comment:
   The method should be private.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/MetricSource.java:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+/**
+ * Interface for all metrics source.
+ */
+public interface MetricSource {

Review Comment:
   This entity is source for set of metrics, so right name is `MetricsSource`. 
Please fix also java docs where this name is wrong. 



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/MetricSource.java:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+/**
+ * Interface for all metrics source.

Review Comment:
   I think we should describe the purpose of the metrics source in java doc.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/MetricSet.java:
##########
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.ignite.internal.metrics.composite.CompositeMetric;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * The Metric set that consists of set of metrics identified by a metric name.
+ * The metrics set is immutable.
+ */
+public class MetricSet implements Iterable<Metric> {

Review Comment:
   This entity is a set of metrics, so right name is `MetricsSet`. Usually we 
don't use such names in Java (e.g. for variables), but it is needed to symmetry 
with `MetricsSource` and `MetricsRegistry` entities. 



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/AtomicLongMetric.java:
##########
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Long metric implementation.
+ */
+public class AtomicLongMetric extends AbstractMetric implements LongMetric {
+    /** Field updater. */
+    static final AtomicLongFieldUpdater<AtomicLongMetric> updater =
+            AtomicLongFieldUpdater.newUpdater(AtomicLongMetric.class, "val");
+
+    /** Field value. */
+    private volatile long val;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     */
+    public AtomicLongMetric(String name, @Nullable String desc) {
+        super(name, desc);
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param x Value to be added.
+     */
+    public void add(long x) {
+        updater.getAndAdd(this, x);
+    }
+
+    /** Adds 1 to the metric. */
+    public void increment() {
+        add(1);

Review Comment:
   Please, use `updater.incrementAndGet` here. See `AtomicIntMetric` class for 
arguments.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/HitRateMetric.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import static org.apache.ignite.internal.util.IgniteUtils.currentTimeMillis;
+import static org.apache.ignite.internal.util.IgniteUtils.ensure;
+
+import java.util.concurrent.atomic.AtomicLongArray;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Accumulates approximate hit rate statistics.
+ * Calculates number of hits in last {@code rateTimeInterval} milliseconds.
+ * Algorithm is based on circular array of {@code size} hit counters, each is 
responsible for last corresponding time
+ * interval of {@code rateTimeInterval}/{@code size} milliseconds. Resulting 
number of hits is sum of all counters.
+ *
+ * <p>Implementation is nonblocking and protected from hits loss.
+ * Maximum relative error is 1/{@code size}.
+ * 2^55 - 1 hits per interval can be accumulated without numeric overflow.
+ */
+public class HitRateMetric extends AbstractMetric implements LongMetric {
+    /** Default counters array size. */
+    public static final int DFLT_SIZE = 10;
+
+    /** Bits that store actual hit count. */
+    private static final int TAG_OFFSET = 56;
+
+    /** Useful part mask. */
+    private static final long NO_TAG_MASK = ~(-1L << TAG_OFFSET);
+
+    /** Time interval when hits are counted to calculate rate, in 
milliseconds. */
+    private final long rateTimeInterval;
+
+    /** Counters array size. */
+    private final int size;
+
+    /** Tagged counters. */
+    private final AtomicLongArray taggedCounters;
+
+    /** Last hit times. */
+    private final AtomicLongArray lastHitTimes;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param rateTimeInterval Rate time interval in milliseconds.
+     */
+    public HitRateMetric(String name, @Nullable String desc, long 
rateTimeInterval) {
+        this(name, desc, rateTimeInterval, DFLT_SIZE);
+    }
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param rateTimeInterval Rate time interval in milliseconds.
+     * @param size Counters array size.
+     */
+    public HitRateMetric(String name, @Nullable String desc, long 
rateTimeInterval, int size) {
+        super(name, desc);
+
+        ensure(rateTimeInterval > 0, "rateTimeInterval should be positive");
+        ensure(size > 1, "Minimum value for size is 2");
+
+        this.rateTimeInterval = rateTimeInterval;
+        this.size = size;
+        taggedCounters = new AtomicLongArray(size);
+        lastHitTimes = new AtomicLongArray(size);
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param hits Value to be added.
+     */
+    public void add(long hits) {
+        long curTs = currentTimeMillis();

Review Comment:
   It seems we have a scalability bug here. `currentTimeMillis` returns a 
cached value that refreshes every 10 ms. So all threads on this period of time 
will contend for the same array element. It should be investigated and a JIRA 
ticket should be created. It could be replaced by `System.currentTimeMillis` 
which takes a little bit more time but will scale threads between array 
elements better so will decrease number of CAS cycles.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/HitRateMetric.java:
##########
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import static org.apache.ignite.internal.util.IgniteUtils.currentTimeMillis;
+import static org.apache.ignite.internal.util.IgniteUtils.ensure;
+
+import java.util.concurrent.atomic.AtomicLongArray;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Accumulates approximate hit rate statistics.
+ * Calculates number of hits in last {@code rateTimeInterval} milliseconds.
+ * Algorithm is based on circular array of {@code size} hit counters, each is 
responsible for last corresponding time
+ * interval of {@code rateTimeInterval}/{@code size} milliseconds. Resulting 
number of hits is sum of all counters.
+ *
+ * <p>Implementation is nonblocking and protected from hits loss.
+ * Maximum relative error is 1/{@code size}.
+ * 2^55 - 1 hits per interval can be accumulated without numeric overflow.
+ */
+public class HitRateMetric extends AbstractMetric implements LongMetric {
+    /** Default counters array size. */
+    public static final int DFLT_SIZE = 10;
+
+    /** Bits that store actual hit count. */
+    private static final int TAG_OFFSET = 56;
+
+    /** Useful part mask. */
+    private static final long NO_TAG_MASK = ~(-1L << TAG_OFFSET);
+
+    /** Time interval when hits are counted to calculate rate, in 
milliseconds. */
+    private final long rateTimeInterval;
+
+    /** Counters array size. */
+    private final int size;
+
+    /** Tagged counters. */
+    private final AtomicLongArray taggedCounters;
+
+    /** Last hit times. */
+    private final AtomicLongArray lastHitTimes;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param rateTimeInterval Rate time interval in milliseconds.
+     */
+    public HitRateMetric(String name, @Nullable String desc, long 
rateTimeInterval) {
+        this(name, desc, rateTimeInterval, DFLT_SIZE);
+    }
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param rateTimeInterval Rate time interval in milliseconds.
+     * @param size Counters array size.
+     */
+    public HitRateMetric(String name, @Nullable String desc, long 
rateTimeInterval, int size) {
+        super(name, desc);
+
+        ensure(rateTimeInterval > 0, "rateTimeInterval should be positive");
+        ensure(size > 1, "Minimum value for size is 2");
+
+        this.rateTimeInterval = rateTimeInterval;
+        this.size = size;
+        taggedCounters = new AtomicLongArray(size);
+        lastHitTimes = new AtomicLongArray(size);
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param hits Value to be added.
+     */
+    public void add(long hits) {
+        long curTs = currentTimeMillis();
+
+        int curPos = position(curTs);
+
+        clearIfObsolete(curTs, curPos);
+
+        lastHitTimes.set(curPos, curTs);
+
+        // Order is important. Hit won't be cleared by concurrent 
#clearIfObsolete.
+        taggedCounters.addAndGet(curPos, hits);
+    }
+
+    /** Adds 1 to the metric. */
+    public void increment() {
+        add(1);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long value() {
+        long curTs = currentTimeMillis();
+
+        long sum = 0;
+
+        for (int i = 0; i < size; i++) {
+            clearIfObsolete(curTs, i);
+
+            sum += untag(taggedCounters.get(i));
+        }
+
+        return sum;
+    }
+
+    /**
+     * Clear specific counter if obsolete.
+     *
+     * @param curTs Current timestamp.
+     * @param i Index.
+     */
+    private void clearIfObsolete(long curTs, int i) {
+        long cur = taggedCounters.get(i);
+
+        byte curTag = getTag(cur);
+
+        long lastTs = lastHitTimes.get(i);
+
+        if (isObsolete(curTs, lastTs)) {
+            if (taggedCounters.compareAndSet(i, cur, 
taggedLongZero(++curTag))) { // ABA problem prevention.
+                lastHitTimes.set(i, curTs);
+            }
+            // If CAS failed, counter is reset by another thread.
+        }
+    }
+
+    /**
+     * Whether the last hit time was too long ago.
+     *
+     * @param curTs Current timestamp.
+     * @param lastHitTime Last hit timestamp.
+     * @return True, is last hit time was too long ago.
+     */
+    private boolean isObsolete(long curTs, long lastHitTime) {
+        return curTs - lastHitTime > rateTimeInterval * (size - 1) / size;
+    }
+
+    /**
+     * Index of counter for given timestamp.
+     *
+     * @param time Timestamp.
+     * @return Index of counter for given timestamp.
+     */
+    private int position(long time) {
+        return (int) ((time % rateTimeInterval * size) / rateTimeInterval);
+    }
+
+    /**
+     * Create a zero value with tag byte.
+     *
+     * @param tag Tag byte.
+     * @return 0L with given tag byte.
+     */
+    private static long taggedLongZero(byte tag) {
+        return ((long) tag << TAG_OFFSET);
+    }
+
+    /**
+     * Long without tag byte.
+     *
+     * @param l Tagged long.
+     * @return Long without tag byte.
+     */
+    private static long untag(long l) {
+        return l & NO_TAG_MASK;
+    }
+
+    /**
+     * Tag byte.
+     *
+     * @param taggedLong Tagged long.
+     * @return Tag byte.
+     */
+    private static byte getTag(long taggedLong) {
+        return (byte) (taggedLong >> TAG_OFFSET);
+    }
+
+    /**
+     * Rate time interval in milliseconds.
+     *
+     * @return Rate time interval in milliseconds.
+     */
+    public long rateTimeInterval() {

Review Comment:
   It seems that this method is unused.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/scalar/LongAdderMetric.java:
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.scalar;
+
+import java.util.concurrent.atomic.LongAdder;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Long metric based on {@link LongAdder}.
+ */
+public class LongAdderMetric extends AbstractMetric implements LongMetric {
+    /** Value. */
+    private volatile LongAdder val;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     */
+    public LongAdderMetric(String name, @Nullable String desc) {
+        super(name, desc);
+
+        this.val = new LongAdder();
+    }
+
+    /**
+     * Adds x to the metric.
+     *
+     * @param x Value to be added.
+     */
+    public void add(long x) {
+        val.add(x);
+    }
+
+    /**
+     * Increment the metric.
+     */
+    public void increment() {

Review Comment:
   Please use direct calls like `val.add(1)` or `val.increment` here



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/composite/DistributionMetric.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLongArray;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.scalar.LongGauge;
+import org.apache.ignite.internal.metrics.scalar.LongMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Distribution metric calculates counts of measurements that gets into each 
bounds interval.
+ * Note, that {@link #value()} will return array length of {@code 
bounds.length + 1}.
+ * Last element contains count of measurements bigger than most right value of 
bounds.
+ */
+public class DistributionMetric extends AbstractMetric implements 
CompositeMetric {
+    /** Count of measurement for each bound. */
+    private final AtomicLongArray measurements;
+
+    /** Bounds of measurements. */
+    private final long[] bounds;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param bounds Bounds of the buckets.
+     */
+    public DistributionMetric(String name, @Nullable String desc, long[] 
bounds) {
+        super(name, desc);
+
+        assert bounds != null && bounds.length > 0;
+        assert isSorted(bounds);
+
+        this.bounds = bounds;
+        this.measurements = new AtomicLongArray(bounds.length + 1);
+    }
+
+    /**
+     * Check whether given array is sorted.
+     *
+     * @param arr Array to check.
+     * @return {@code True} if array sorted, {@code false} otherwise.
+     */
+    public static boolean isSorted(long[] arr) {
+        if (arr == null || arr.length < 2) {

Review Comment:
   Passed array can't be `null` 



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/composite/DistributionMetric.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLongArray;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.metrics.AbstractMetric;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.scalar.LongGauge;
+import org.apache.ignite.internal.metrics.scalar.LongMetric;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Distribution metric calculates counts of measurements that gets into each 
bounds interval.
+ * Note, that {@link #value()} will return array length of {@code 
bounds.length + 1}.
+ * Last element contains count of measurements bigger than most right value of 
bounds.
+ */
+public class DistributionMetric extends AbstractMetric implements 
CompositeMetric {
+    /** Count of measurement for each bound. */
+    private final AtomicLongArray measurements;
+
+    /** Bounds of measurements. */
+    private final long[] bounds;
+
+    /**
+     * The constructor.
+     *
+     * @param name Name.
+     * @param desc Description.
+     * @param bounds Bounds of the buckets.
+     */
+    public DistributionMetric(String name, @Nullable String desc, long[] 
bounds) {
+        super(name, desc);
+
+        assert bounds != null && bounds.length > 0;
+        assert isSorted(bounds);
+
+        this.bounds = bounds;
+        this.measurements = new AtomicLongArray(bounds.length + 1);
+    }
+
+    /**
+     * Check whether given array is sorted.
+     *
+     * @param arr Array to check.
+     * @return {@code True} if array sorted, {@code false} otherwise.
+     */
+    public static boolean isSorted(long[] arr) {
+        if (arr == null || arr.length < 2) {
+            return true;
+        }
+
+        for (int i = 1; i < arr.length; i++) {
+            if (arr[i - 1] > arr[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Sets value.
+     *
+     * @param x Value.
+     */
+    public void value(long x) {

Review Comment:
   The method behave in a different way then described and named. It increments 
the value in the given interval, but doesn't sets the value. Please, rename and 
rewrite javadoc.
   
   BTW, in general it is possible to have increment/decrement operations as 
well as add operation. And then the first assert will not make sense.



##########
modules/metrics/src/main/java/org/apache/ignite/internal/metrics/MetricSource.java:
##########
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+/**
+ * Interface for all metrics source.
+ */
+public interface MetricSource {
+    /**
+     * Returns metric source name.
+     *
+     * @return Metric source name.
+     */
+    String name();
+
+    /**
+     * Enables metrics for metric source. Creates and returns {@link 
MetricSet} built during enabling. Nothing happens if
+     * the metrics are already enabled for this source.
+     *
+     * @return Newly created {@link MetricSet} instance or {@code null} if 
metrics are already enabled.
+     */
+    MetricSet enable();

Review Comment:
   `@Nullable`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to