Skip to content

Commit 3f17f11

Browse files
committed
First idea in adding histogram metric
1 parent 1d565c0 commit 3f17f11

File tree

14 files changed

+169
-0
lines changed

14 files changed

+169
-0
lines changed

logstash-core/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ dependencies {
245245
exclude group: 'com.google.guava', module: 'guava'
246246
}
247247
implementation 'org.javassist:javassist:3.30.2-GA'
248+
implementation 'org.hdrhistogram:HdrHistogram:2.2.2'
248249
testImplementation "org.apache.logging.log4j:log4j-core:${log4jVersion}:tests"
249250
testImplementation 'org.hamcrest:hamcrest:2.2'
250251
testImplementation 'org.hamcrest:hamcrest-library:2.2'

logstash-core/lib/logstash/instrument/metric_type.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def self.create(type, namespaces, key)
2929
when :gauge then return org.logstash.instrument.metrics.gauge.LazyDelegatingGauge.new(key.to_s)
3030
when :uptime then return org.logstash.instrument.metrics.UptimeMetric.new(key.to_s)
3131
when :timer then return org.logstash.instrument.metrics.timer.TimerMetric::create(key.to_s)
32+
when :histogram then return org.logstash.instrument.metrics.histogram.HistogramMetric.new(key.to_s)
3233
else fail NameError, "Unknown Metric Type `#{type}`"
3334
end
3435
end

logstash-core/src/main/java/org/logstash/execution/AbstractPipelineExt.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
import org.logstash.instrument.metrics.MetricType;
9393
import org.logstash.instrument.metrics.NullMetricExt;
9494
import org.logstash.instrument.metrics.UpScaledMetric;
95+
import org.logstash.instrument.metrics.histogram.HistogramMetric;
9596
import org.logstash.instrument.metrics.timer.TimerMetric;
9697
import org.logstash.instrument.metrics.UptimeMetric;
9798
import org.logstash.instrument.metrics.counter.LongCounter;
@@ -286,6 +287,12 @@ private AbstractPipelineExt initialize(final ThreadContext context,
286287
} catch (InvalidIRException iirex) {
287288
throw new IllegalArgumentException(iirex);
288289
}
290+
291+
292+
// init histogram sample
293+
final RubySymbol[] eventsNamespace = buildNamespace(EVENTS_KEY);
294+
initOrGetHistogramMetric(context, eventsNamespace, BATCH_SIZE_KEY);
295+
289296
return this;
290297
}
291298

@@ -640,6 +647,16 @@ private TimerMetric initOrGetTimerMetric(final ThreadContext context,
640647
return retrievedMetric.toJava(TimerMetric.class);
641648
}
642649

650+
private HistogramMetric initOrGetHistogramMetric(final ThreadContext context,
651+
final RubySymbol[] subPipelineNamespacePath,
652+
final RubySymbol metricName) {
653+
final IRubyObject collector = this.metric.collector(context);
654+
final IRubyObject fullNamespace = pipelineNamespacedPath(subPipelineNamespacePath);
655+
656+
final IRubyObject retrievedMetric = collector.callMethod(context, "get", new IRubyObject[]{fullNamespace, metricName, context.runtime.newSymbol("histogram")});
657+
return retrievedMetric.toJava(HistogramMetric.class);
658+
}
659+
643660
private Optional<NumberGauge> initOrGetNumberGaugeMetric(final ThreadContext context,
644661
final RubySymbol[] subPipelineNamespacePath,
645662
final RubySymbol metricName) {

logstash-core/src/main/java/org/logstash/execution/QueueReadClientBase.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.logstash.RubyUtil;
3535
import org.logstash.instrument.metrics.AbstractNamespacedMetricExt;
3636
import org.logstash.instrument.metrics.MetricKeys;
37+
import org.logstash.instrument.metrics.histogram.HistogramMetric;
3738
import org.logstash.instrument.metrics.timer.TimerMetric;
3839
import org.logstash.instrument.metrics.counter.LongCounter;
3940

@@ -60,6 +61,7 @@ public abstract class QueueReadClientBase extends RubyObject implements QueueRea
6061
private transient LongCounter pipelineMetricOut;
6162
private transient LongCounter pipelineMetricFiltered;
6263
private transient TimerMetric pipelineMetricTime;
64+
private transient HistogramMetric pipelineMetricBatch;
6365

6466
protected QueueReadClientBase(final Ruby runtime, final RubyClass metaClass) {
6567
super(runtime, metaClass);
@@ -90,6 +92,7 @@ public IRubyObject setPipelineMetric(final IRubyObject metric) {
9092
pipelineMetricOut = LongCounter.fromRubyBase(namespacedMetric, MetricKeys.OUT_KEY);
9193
pipelineMetricFiltered = LongCounter.fromRubyBase(namespacedMetric, MetricKeys.FILTERED_KEY);
9294
pipelineMetricTime = TimerMetric.fromRubyBase(namespacedMetric, MetricKeys.DURATION_IN_MILLIS_KEY);
95+
pipelineMetricBatch = HistogramMetric.fromRubyBase(namespacedMetric, MetricKeys.BATCH_SIZE_KEY);
9396
}
9497
return this;
9598
}
@@ -193,6 +196,7 @@ public void startMetrics(QueueBatch batch) {
193196
// JTODO getId has been deprecated in JDK 19, when JDK 21 is the target version use threadId() instead
194197
long threadId = Thread.currentThread().getId();
195198
inflightBatches.put(threadId, batch);
199+
pipelineMetricBatch.update(batch.filteredSize());
196200
}
197201

198202
@Override

logstash-core/src/main/java/org/logstash/instrument/metrics/AbstractNamespacedMetricExt.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ public IRubyObject timer(final ThreadContext context, final IRubyObject key) {
5353
return getTimer(context, key);
5454
}
5555

56+
@JRubyMethod
57+
public IRubyObject histogram(final ThreadContext context, final IRubyObject key) {
58+
return getHistogram(context, key);
59+
}
60+
5661
@JRubyMethod(required = 1, optional = 1)
5762
public IRubyObject increment(final ThreadContext context, final IRubyObject[] args) {
5863
return doIncrement(context, args);
@@ -95,6 +100,8 @@ protected abstract IRubyObject getGauge(ThreadContext context, IRubyObject key,
95100

96101
protected abstract IRubyObject getTimer(ThreadContext context, IRubyObject key);
97102

103+
protected abstract IRubyObject getHistogram(ThreadContext context, IRubyObject key);
104+
98105
protected abstract IRubyObject doTime(ThreadContext context, IRubyObject key, Block block);
99106

100107
protected abstract IRubyObject doReportTime(ThreadContext context,

logstash-core/src/main/java/org/logstash/instrument/metrics/AbstractSimpleMetricExt.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ public IRubyObject timer(final ThreadContext context,
6060
return getTimer(context, namespace, key);
6161
}
6262

63+
@JRubyMethod
64+
public IRubyObject histogram(final ThreadContext context,
65+
final IRubyObject namespace,
66+
final IRubyObject key) {
67+
return getHistogram(context, namespace, key);
68+
}
69+
6370
@JRubyMethod(name = "report_time")
6471
public IRubyObject reportTime(final ThreadContext context, final IRubyObject namespace,
6572
final IRubyObject key, final IRubyObject duration) {
@@ -83,6 +90,8 @@ protected abstract IRubyObject getGauge(ThreadContext context, IRubyObject names
8390

8491
protected abstract IRubyObject getTimer(ThreadContext context, IRubyObject namespace, IRubyObject key);
8592

93+
protected abstract IRubyObject getHistogram(ThreadContext context, IRubyObject namespace, IRubyObject key);
94+
8695
protected abstract IRubyObject doReportTime(ThreadContext context, IRubyObject namespace,
8796
IRubyObject key, IRubyObject duration);
8897

logstash-core/src/main/java/org/logstash/instrument/metrics/MetricExt.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public final class MetricExt extends AbstractSimpleMetricExt {
5454

5555
private static final RubySymbol GAUGE = RubyUtil.RUBY.newSymbol("gauge");
5656
private static final RubySymbol TIMER = RubyUtil.RUBY.newSymbol("timer");
57+
private static final RubySymbol HISTOGRAM = RubyUtil.RUBY.newSymbol("histogram");
5758
private static final RubySymbol SET = RubyUtil.RUBY.newSymbol("set");
5859
private static final RubySymbol GET = RubyUtil.RUBY.newSymbol("get");
5960

@@ -153,6 +154,16 @@ protected IRubyObject getTimer(final ThreadContext context,
153154
);
154155
}
155156

157+
@Override
158+
protected IRubyObject getHistogram(final ThreadContext context,
159+
final IRubyObject namespace,
160+
final IRubyObject key) {
161+
MetricExt.validateKey(context, null, key);
162+
return collector.callMethod(context,
163+
"get", new IRubyObject[]{normalizeNamespace(namespace), key, HISTOGRAM}
164+
);
165+
}
166+
156167
@Override
157168
protected IRubyObject doReportTime(final ThreadContext context, final IRubyObject namespace,
158169
final IRubyObject key, final IRubyObject duration) {

logstash-core/src/main/java/org/logstash/instrument/metrics/MetricKeys.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,5 @@ private MetricKeys() {
116116

117117
public static final RubySymbol WRITES_IN_KEY = RubyUtil.RUBY.newSymbol("writes_in");
118118

119+
public static final RubySymbol BATCH_SIZE_KEY = RubyUtil.RUBY.newSymbol("batch_size");
119120
}

logstash-core/src/main/java/org/logstash/instrument/metrics/MetricType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ public enum MetricType {
7777
* A flow-rate {@link FlowMetric}, instantiated with one or more backing {@link Metric}{@code <Number>}.
7878
*/
7979
FLOW_RATE("flow/rate"),
80+
81+
/**
82+
* A histogram metric to record values and obtain percentiles measurements.
83+
* */
84+
HISTOGRAM_LONG("histogram/long"),
8085
;
8186

8287
private final String type;

logstash-core/src/main/java/org/logstash/instrument/metrics/NamespacedMetricExt.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ protected IRubyObject getTimer(ThreadContext context, IRubyObject key) {
8484
return metric.timer(context, namespaceName, key);
8585
}
8686

87+
@Override
88+
protected IRubyObject getHistogram(ThreadContext context, IRubyObject key) {
89+
return metric.histogram(context, namespaceName, key);
90+
}
91+
8792
@Override
8893
protected IRubyObject doIncrement(final ThreadContext context, final IRubyObject[] args) {
8994
if (args.length == 1) {

0 commit comments

Comments
 (0)