Skip to content

Commit 187fec8

Browse files
authored
Merge pull request #79 from avaje/feature/addTags
Add Tags support, add Metric.ID
2 parents 09f82dc + 9cb5feb commit 187fec8

36 files changed

+651
-144
lines changed

metrics-ebean/src/main/java/io/avaje/metrics/ebean/DatabaseMetricSupplier.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ public List<Metric.Statistics> collectMetrics() {
3636
log.log(Level.DEBUG, dbMetrics.asJson().withHash(false).withNewLine(false).json());
3737
}
3838
for (MetaTimedMetric timedMetric : dbMetrics.timedMetrics()) {
39-
metrics.add(new TimerStats(timedMetric.name(), timedMetric.count(), timedMetric.total(), timedMetric.max()));
39+
metrics.add(new TimerStats(Metric.ID.of(timedMetric.name()), timedMetric.count(), timedMetric.total(), timedMetric.max()));
4040
}
4141
for (MetaQueryMetric metric : dbMetrics.queryMetrics()) {
42-
metrics.add(new TimerStats(metric.name(), metric.count(), metric.total(), metric.max()));
42+
metrics.add(new TimerStats(Metric.ID.of(metric.name()), metric.count(), metric.total(), metric.max()));
4343
}
4444
for (MetaCountMetric metric : dbMetrics.countMetrics()) {
45-
metrics.add(new CounterStats(metric.name(), metric.count()));
45+
metrics.add(new CounterStats(Metric.ID.of(metric.name()), metric.count()));
4646
}
4747
return metrics;
4848
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package io.avaje.metrics;
2+
3+
import java.util.Objects;
4+
5+
import static java.util.Objects.requireNonNull;
6+
7+
final class MId implements Metric.ID {
8+
9+
private final String name;
10+
private final Tags tags;
11+
12+
MId(String name, Tags tags) {
13+
this.name = name;
14+
this.tags = tags;
15+
}
16+
17+
@Override
18+
public String name() {
19+
return name;
20+
}
21+
22+
@Override
23+
public Tags tags() {
24+
return tags;
25+
}
26+
27+
@Override
28+
public Metric.ID suffix(String suffix) {
29+
return new MId(name + requireNonNull(suffix), tags);
30+
}
31+
32+
@Override
33+
public Metric.ID withName(String otherName) {
34+
if (name.equals(requireNonNull(otherName))) {
35+
return this;
36+
}
37+
return new MId(otherName, tags);
38+
}
39+
40+
@Override
41+
public Metric.ID withTags(Tags otherTags) {
42+
if (tags.equals(requireNonNull(otherTags))) {
43+
return this;
44+
}
45+
return new MId(name, otherTags);
46+
}
47+
48+
@Override
49+
public boolean equals(Object object) {
50+
if (this == object) return true;
51+
if (!(object instanceof MId)) return false;
52+
MId key = (MId) object;
53+
return Objects.equals(name, key.name) && Objects.equals(tags, key.tags);
54+
}
55+
56+
@Override
57+
public int hashCode() {
58+
return Objects.hash(name, tags);
59+
}
60+
61+
@Override
62+
public String toString() {
63+
return tags.isEmpty() ? name : name + ' ' + tags;
64+
}
65+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.avaje.metrics;
2+
3+
import java.util.Arrays;
4+
import java.util.Objects;
5+
6+
final class MTags implements Tags {
7+
8+
static Tags EMPTY = new MTags(new String[]{});
9+
10+
private final String[] keyValuePairs;
11+
12+
MTags(String[] keyValuePairs) {
13+
if (keyValuePairs.length % 2 != 0) {
14+
throw new IllegalArgumentException("Incorrect length, must be pairs of key values");
15+
}
16+
this.keyValuePairs = keyValuePairs;
17+
}
18+
19+
@Override
20+
public boolean isEmpty() {
21+
return keyValuePairs.length == 0;
22+
}
23+
24+
@Override
25+
public String[] array() {
26+
return keyValuePairs;
27+
}
28+
29+
@Override
30+
public boolean equals(Object object) {
31+
if (this == object) return true;
32+
if (!(object instanceof MTags)) return false;
33+
MTags dTags = (MTags) object;
34+
return Objects.deepEquals(keyValuePairs, dTags.keyValuePairs);
35+
}
36+
37+
@Override
38+
public int hashCode() {
39+
return Arrays.hashCode(keyValuePairs);
40+
}
41+
42+
@Override
43+
public String toString() {
44+
return keyValuePairs.length == 0 ? "" : "tags:" + Arrays.toString(keyValuePairs);
45+
}
46+
}

metrics/src/main/java/io/avaje/metrics/Metric.java

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
*/
1515
public interface Metric {
1616

17+
/**
18+
* Return the Id of the metric.
19+
*/
20+
ID id();
21+
1722
/**
1823
* Return the name of the metric.
1924
*/
@@ -28,19 +33,69 @@ public interface Metric {
2833
/**
2934
* Reset the statistics resetting any internal counters etc.
3035
* <p>
31-
* Typically the MetricManager takes care of resetting the statistic/counters for the metrics when
32-
* it periodically collects and reports all the metrics and you are not expected to use this method.
33-
* </p>
36+
* Typically, the MetricRegistry takes care of resetting the statistic/counters for the metrics when
37+
* it periodically collects and reports all the metrics, and you are not expected to use this method.
3438
*/
3539
void reset();
3640

41+
/**
42+
* Identifier of a Metric based on both the name and tags.
43+
*/
44+
interface ID {
45+
46+
/**
47+
* Create an Id given a name only.
48+
*/
49+
static ID of(String name) {
50+
return new MId(name, Tags.EMPTY);
51+
}
52+
53+
/**
54+
* Create an Id given name and tags.
55+
*/
56+
static ID of(String name, Tags tags) {
57+
return new MId(name, tags);
58+
}
59+
60+
/**
61+
* Return the metric name.
62+
*/
63+
String name();
64+
65+
/**
66+
* Return the tags.
67+
*/
68+
Tags tags();
69+
70+
/**
71+
* Return an Id appending the suffix to the name.
72+
*/
73+
ID suffix(String suffix);
74+
75+
/**
76+
* Return an Id with the given name..
77+
*/
78+
ID withName(String otherName);
79+
80+
/**
81+
* Return an Id with the given name..
82+
*/
83+
ID withTags(Tags tags);
84+
85+
}
86+
3787
/**
3888
* Common for statistics of all metrics.
3989
*/
4090
interface Statistics {
4191

4292
/**
43-
* Return the associated metric name.
93+
* Return the metric id.
94+
*/
95+
ID id();
96+
97+
/**
98+
* Return the metric name.
4499
*/
45100
String name();
46101

metrics/src/main/java/io/avaje/metrics/MetricRegistry.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,51 @@ public interface MetricRegistry extends JvmMetrics {
1515
*/
1616
Counter counter(String name);
1717

18+
/**
19+
* Return the Counter with the given name and tags.
20+
*/
21+
Counter counter(String name, Tags tags);
22+
1823
/**
1924
* Return the Meter using the metric name.
2025
*/
2126
Meter meter(String name);
2227

28+
/**
29+
* Return the Meter using the metric name and tags.
30+
*/
31+
Meter meter(String name, Tags tags);
32+
2333
/**
2434
* Create and register a gauge using the supplied double values.
2535
*/
2636
GaugeDouble gauge(String name, DoubleSupplier supplier);
2737

38+
/**
39+
* Create and register a gauge using the supplied double values.
40+
*/
41+
GaugeDouble gauge(String name, Tags tags, DoubleSupplier supplier);
42+
2843
/**
2944
* Create and register a gauge using the supplied long values.
3045
*/
3146
GaugeLong gauge(String name, LongSupplier supplier);
3247

48+
/**
49+
* Create and register a gauge using the supplied long values.
50+
*/
51+
GaugeLong gauge(String name, Tags tags, LongSupplier supplier);
52+
3353
/**
3454
* Return the timer using the metric name.
3555
*/
3656
Timer timer(String name);
3757

58+
/**
59+
* Return the timer using the metric name and tags.
60+
*/
61+
Timer timer(String name, Tags tags);
62+
3863
/**
3964
* Return the bucket timer using the given base metric name and bucketRanges.
4065
*
@@ -43,6 +68,15 @@ public interface MetricRegistry extends JvmMetrics {
4368
*/
4469
Timer timer(String name, int... bucketRanges);
4570

71+
/**
72+
* Return the bucket timer using the given base metric name, tags and bucketRanges.
73+
*
74+
* @param name The metric name
75+
* @param tags The metric tags
76+
* @param bucketRanges Time in milliseconds which are used to create buckets.
77+
*/
78+
Timer timer(String name, Tags tags, int... bucketRanges);
79+
4680
/**
4781
* Return the TimerGroup using the given base metric name.
4882
*/
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.avaje.metrics;
2+
3+
public interface Tags {
4+
5+
Tags EMPTY = MTags.EMPTY;
6+
7+
static Tags of() {
8+
return EMPTY;
9+
}
10+
11+
static Tags of(String... keyValuePairs) {
12+
return new MTags(keyValuePairs);
13+
}
14+
15+
String[] array();
16+
17+
boolean isEmpty();
18+
}

metrics/src/main/java/io/avaje/metrics/core/BaseReportName.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,21 @@
55

66
abstract class BaseReportName {
77

8-
final String name;
9-
@Nullable String reportName;
8+
final Metric.ID id;
9+
volatile Metric.@Nullable ID reportId;
1010

11-
BaseReportName(String name) {
12-
this.name = name;
11+
BaseReportName(Metric.ID id) {
12+
this.id = id;
1313
}
1414

15-
final String reportName(Metric.Visitor collector) {
16-
final String tmp = collector.namingConvention().apply(name);
17-
this.reportName = tmp;
15+
final Metric.ID reportId(Metric.Visitor collector) {
16+
final var id = reportId;
17+
return id != null ? id : useNamingConvention(collector);
18+
}
19+
20+
final Metric.ID useNamingConvention(Metric.Visitor collector) {
21+
final Metric.ID tmp = id.withName(collector.namingConvention().apply(id.name()));
22+
this.reportId = tmp;
1823
return tmp;
1924
}
2025

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
package io.avaje.metrics.core;
22

3+
import io.avaje.metrics.Metric;
34
import io.avaje.metrics.Timer;
45
import io.avaje.metrics.spi.SpiMetricBuilder;
56

67
final class BucketTimerFactory implements SpiMetricBuilder.Factory<Timer> {
78

89
@Override
9-
public Timer createMetric(String name, int[] bucketRanges) {
10+
public Timer createMetric(Metric.ID id, int[] bucketRanges) {
1011
int rangeBottom = 0;
1112
Timer[] buckets = new Timer[bucketRanges.length + 1];
1213
for (int i = 0; i < bucketRanges.length; i++) {
1314
int rangeTop = bucketRanges[i];
14-
buckets[i] = createTimedMetric(name, rangeBottom, rangeTop);
15+
buckets[i] = createTimedMetric(id, rangeBottom, rangeTop);
1516
// move the range bottom up to the last rangeTop
1617
rangeBottom = rangeTop;
1718
}
18-
buckets[bucketRanges.length] = createTimedMetric(name, rangeBottom, 0);
19-
return new DBucketTimer(name, bucketRanges, buckets);
19+
buckets[bucketRanges.length] = createTimedMetric(id, rangeBottom, 0);
20+
return new DBucketTimer(id, bucketRanges, buckets);
2021
}
2122

22-
private static Timer createTimedMetric(String name, int rangeBottom, int rangeTop) {
23+
private static Timer createTimedMetric(Metric.ID id, int rangeBottom, int rangeTop) {
2324
String suffix = (rangeTop == 0) ? String.valueOf(rangeBottom) : rangeBottom + "-" + rangeTop;
24-
return new DTimer(name, suffix);
25+
return new DTimer(id, suffix);
2526
}
2627

2728
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package io.avaje.metrics.core;
22

33
import io.avaje.metrics.Counter;
4+
import io.avaje.metrics.Metric;
45
import io.avaje.metrics.spi.SpiMetricBuilder;
56

67
final class CounterFactory implements SpiMetricBuilder.Factory<Counter> {
78

89
@Override
9-
public Counter createMetric(String name, int[] bucketRanges) {
10-
return new DCounter(name);
10+
public Counter createMetric(Metric.ID id, int[] bucketRanges) {
11+
return new DCounter(id);
1112
}
1213

1314
}

0 commit comments

Comments
 (0)