Added support for GAUGE_LIST metric type (#17721)

* Added support for GAUGE_LIST metric type

Prior to the changes, log emits a warning about an unknown gauge metric type
when running pipeline-to-pipeline due to serialization of `{send_to:[pipeline_name]}`.

This commit added support of List type to eliminate the warning.
This commit is contained in:
kaisecheng 2025-06-23 13:23:07 +01:00 committed by GitHub
parent e2919ec284
commit 909d66c467
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 148 additions and 2 deletions

View file

@ -68,6 +68,11 @@ public enum MetricType {
*/
GAUGE_RUBYTIMESTAMP("gauge/rubytimestamp"),
/**
* A gauge backed by a {@link java.util.List} type.
*/
GAUGE_LIST("gauge/list"),
/**
* A flow-rate {@link FlowMetric}, instantiated with one or more backing {@link Metric}{@code <Number>}.
*/

View file

@ -27,6 +27,7 @@ import org.logstash.ext.JrubyTimestampExtLibrary.RubyTimestamp;
import org.logstash.instrument.metrics.AbstractMetric;
import org.logstash.instrument.metrics.MetricType;
import java.util.List;
import java.util.Optional;
/**
@ -117,6 +118,8 @@ public class LazyDelegatingGauge extends AbstractMetric<Object> implements Gauge
lazyMetric = new RubyHashGauge(key, (RubyHash) value);
} else if (value instanceof RubyTimestamp) {
lazyMetric = new RubyTimeStampGauge(key, (RubyTimestamp) value);
} else if (value instanceof List<?>) {
lazyMetric = new ListGauge(key, (List<?>) value);
} else {
LOGGER.warn("A gauge metric of an unknown type ({}) has been created for key: {}. This may result in invalid serialization. It is recommended to " +
"log an issue to the responsible developer/development team.", value.getClass().getCanonicalName(), key);

View file

@ -0,0 +1,41 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.logstash.instrument.metrics.gauge;
import org.logstash.instrument.metrics.MetricType;
import java.util.List;
public class ListGauge extends AbstractGaugeMetric<List<?>> {
protected ListGauge(String name) {
super(name);
}
protected ListGauge(String name, List<?> initialValue) {
super(name, initialValue);
}
public MetricType getType() {
return MetricType.GAUGE_LIST;
}
}

View file

@ -47,6 +47,7 @@ public class MetricTypeTest {
nameMap.put(MetricType.GAUGE_TEXT, "gauge/text");
nameMap.put(MetricType.GAUGE_BOOLEAN, "gauge/boolean");
nameMap.put(MetricType.GAUGE_NUMBER, "gauge/number");
nameMap.put(MetricType.GAUGE_LIST, "gauge/list");
nameMap.put(MetricType.GAUGE_UNKNOWN, "gauge/unknown");
nameMap.put(MetricType.GAUGE_RUBYHASH, "gauge/rubyhash");
nameMap.put(MetricType.GAUGE_RUBYTIMESTAMP, "gauge/rubytimestamp");

View file

@ -20,8 +20,6 @@
package org.logstash.instrument.metrics.gauge;
import java.net.URI;
import java.util.Collections;
import org.jruby.RubyHash;
import org.junit.Test;
import org.logstash.RubyUtil;
@ -29,6 +27,10 @@ import org.logstash.Timestamp;
import org.logstash.ext.JrubyTimestampExtLibrary;
import org.logstash.instrument.metrics.MetricType;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -91,6 +93,11 @@ public class LazyDelegatingGaugeTest {
assertThat(gauge.get()).isNull();
assertThat(gauge.getType()).isNull();
//List
gauge = new LazyDelegatingGauge("bar", List.of("one", "two"));
assertThat(gauge.getValue().toString()).isEqualTo("[one, two]");
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LIST);
assertThat(gauge.getName()).isNotEmpty();
}
@ -169,6 +176,13 @@ public class LazyDelegatingGaugeTest {
gauge.set(null);
assertThat(gauge.getValue()).isNull();
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_TEXT);
// List
gauge = new LazyDelegatingGauge("bar");
gauge.set(List.of(1,2));
assertThat(gauge.getValue().toString()).isEqualTo("[1, 2]");
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LIST);
}
}

View file

@ -0,0 +1,82 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.logstash.instrument.metrics.gauge;
import org.jruby.RubyHash;
import org.jruby.runtime.builtin.IRubyObject;
import org.junit.Test;
import org.logstash.RubyUtil;
import org.logstash.instrument.metrics.MetricType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link TextGauge}
*/
public class ListGaugeTest {
@Test
public void getSetStrings() {
ListGauge gauge = new ListGauge("bar");
gauge.set(List.of("pipeline_name1", "pipeline_name2"));
assertThat(gauge.getValue().toString()).isEqualTo("[pipeline_name1, pipeline_name2]");
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LIST);
}
@Test
public void getSetNull() {
ListGauge gauge = new ListGauge("bar");
gauge.set(null);
assertThat(gauge.getValue()).isNull();
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LIST);
}
@Test
public void getSetListOfNull() {
List<Object> nullList = new ArrayList<>(Collections.nCopies(2, null));
ListGauge gauge = new ListGauge("bar");
gauge.set(nullList);
assertThat(gauge.getValue().toString()).isEqualTo("[null, null]");
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LIST);
}
@Test
public void getSetHash() {
IRubyObject[] args = {RubyUtil.RUBY.newString("k"), RubyUtil.RUBY.newString("v")};
RubyHash rubyHash = RubyHash.newHash(RubyUtil.RUBY, args[0], args[1]);
ListGauge gauge = new ListGauge("bar");
gauge.set(List.of(rubyHash));
assertThat(gauge.getValue().toString()).isEqualTo("[{\"k\"=>\"v\"}]");
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LIST);
}
@Test
public void getSetNumber() {
ListGauge gauge = new ListGauge("bar");
gauge.set(List.of(123, 456.7));
assertThat(gauge.getValue().toString()).isEqualTo("[123, 456.7]");
assertThat(gauge.getType()).isEqualTo(MetricType.GAUGE_LIST);
}
}