Skip to content

Commit 9964ab4

Browse files
Izeren1996fanrui
authored andcommitted
[FLINK-39130][metrics] Allow native types in MetricConfig
1 parent 3a13f8d commit 9964ab4

File tree

2 files changed

+188
-31
lines changed

2 files changed

+188
-31
lines changed

flink-metrics/flink-metrics-core/src/main/java/org/apache/flink/metrics/MetricConfig.java

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@
2222

2323
import java.util.Properties;
2424

25-
/** A properties class with added utility method to extract primitives. */
25+
/**
26+
* A properties class with added utility methods to extract primitives.
27+
*
28+
* <p>Values may be stored as strings via {@link #setProperty(String, String)} or as native Java
29+
* types via {@link #put(Object, Object)} (e.g., when Flink's YAML configuration parser stores
30+
* Integer, Long, or Boolean values directly). The getter methods handle both representations
31+
* transparently.
32+
*/
2633
@Public
2734
public class MetricConfig extends Properties {
2835

@@ -31,72 +38,108 @@ public String getString(String key, String defaultValue) {
3138
}
3239

3340
/**
34-
* Searches for the property with the specified key in this property list. If the key is not
35-
* found in this property list, the default property list, and its defaults, recursively, are
36-
* then checked. The method returns the default value argument if the property is not found.
41+
* Returns the value associated with the given key as an {@code int}.
42+
*
43+
* <p>If the value is a {@link Number}, its {@code intValue()} is returned directly. Otherwise,
44+
* the value's string representation is parsed via {@link Integer#parseInt(String)}.
3745
*
3846
* @param key the hashtable key.
3947
* @param defaultValue a default value.
40-
* @return the value in this property list with the specified key value parsed as an int.
48+
* @return the value in this property list with the specified key value as an int.
4149
*/
4250
public int getInteger(String key, int defaultValue) {
43-
String argument = getProperty(key, null);
44-
return argument == null ? defaultValue : Integer.parseInt(argument);
51+
final Object value = get(key);
52+
if (value == null) {
53+
return defaultValue;
54+
}
55+
if (value instanceof Number) {
56+
return ((Number) value).intValue();
57+
}
58+
return Integer.parseInt(value.toString());
4559
}
4660

4761
/**
48-
* Searches for the property with the specified key in this property list. If the key is not
49-
* found in this property list, the default property list, and its defaults, recursively, are
50-
* then checked. The method returns the default value argument if the property is not found.
62+
* Returns the value associated with the given key as a {@code long}.
63+
*
64+
* <p>If the value is a {@link Number}, its {@code longValue()} is returned directly. Otherwise,
65+
* the value's string representation is parsed via {@link Long#parseLong(String)}.
5166
*
5267
* @param key the hashtable key.
5368
* @param defaultValue a default value.
54-
* @return the value in this property list with the specified key value parsed as a long.
69+
* @return the value in this property list with the specified key value as a long.
5570
*/
5671
public long getLong(String key, long defaultValue) {
57-
String argument = getProperty(key, null);
58-
return argument == null ? defaultValue : Long.parseLong(argument);
72+
final Object value = get(key);
73+
if (value == null) {
74+
return defaultValue;
75+
}
76+
if (value instanceof Number) {
77+
return ((Number) value).longValue();
78+
}
79+
return Long.parseLong(value.toString());
5980
}
6081

6182
/**
62-
* Searches for the property with the specified key in this property list. If the key is not
63-
* found in this property list, the default property list, and its defaults, recursively, are
64-
* then checked. The method returns the default value argument if the property is not found.
83+
* Returns the value associated with the given key as a {@code float}.
84+
*
85+
* <p>If the value is a {@link Number}, its {@code floatValue()} is returned directly.
86+
* Otherwise, the value's string representation is parsed via {@link Float#parseFloat(String)}.
6587
*
6688
* @param key the hashtable key.
6789
* @param defaultValue a default value.
68-
* @return the value in this property list with the specified key value parsed as a float.
90+
* @return the value in this property list with the specified key value as a float.
6991
*/
7092
public float getFloat(String key, float defaultValue) {
71-
String argument = getProperty(key, null);
72-
return argument == null ? defaultValue : Float.parseFloat(argument);
93+
final Object value = get(key);
94+
if (value == null) {
95+
return defaultValue;
96+
}
97+
if (value instanceof Number) {
98+
return ((Number) value).floatValue();
99+
}
100+
return Float.parseFloat(value.toString());
73101
}
74102

75103
/**
76-
* Searches for the property with the specified key in this property list. If the key is not
77-
* found in this property list, the default property list, and its defaults, recursively, are
78-
* then checked. The method returns the default value argument if the property is not found.
104+
* Returns the value associated with the given key as a {@code double}.
105+
*
106+
* <p>If the value is a {@link Number}, its {@code doubleValue()} is returned directly.
107+
* Otherwise, the value's string representation is parsed via {@link
108+
* Double#parseDouble(String)}.
79109
*
80110
* @param key the hashtable key.
81111
* @param defaultValue a default value.
82-
* @return the value in this property list with the specified key value parsed as a double.
112+
* @return the value in this property list with the specified key value as a double.
83113
*/
84114
public double getDouble(String key, double defaultValue) {
85-
String argument = getProperty(key, null);
86-
return argument == null ? defaultValue : Double.parseDouble(argument);
115+
final Object value = get(key);
116+
if (value == null) {
117+
return defaultValue;
118+
}
119+
if (value instanceof Number) {
120+
return ((Number) value).doubleValue();
121+
}
122+
return Double.parseDouble(value.toString());
87123
}
88124

89125
/**
90-
* Searches for the property with the specified key in this property list. If the key is not
91-
* found in this property list, the default property list, and its defaults, recursively, are
92-
* then checked. The method returns the default value argument if the property is not found.
126+
* Returns the value associated with the given key as a {@code boolean}.
127+
*
128+
* <p>If the value is a {@link Boolean}, it is returned directly. Otherwise, the value's string
129+
* representation is parsed via {@link Boolean#parseBoolean(String)}.
93130
*
94131
* @param key the hashtable key.
95132
* @param defaultValue a default value.
96-
* @return the value in this property list with the specified key value parsed as a boolean.
133+
* @return the value in this property list with the specified key value as a boolean.
97134
*/
98135
public boolean getBoolean(String key, boolean defaultValue) {
99-
String argument = getProperty(key, null);
100-
return argument == null ? defaultValue : Boolean.parseBoolean(argument);
136+
final Object value = get(key);
137+
if (value == null) {
138+
return defaultValue;
139+
}
140+
if (value instanceof Boolean) {
141+
return (Boolean) value;
142+
}
143+
return Boolean.parseBoolean(value.toString());
101144
}
102145
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.flink.metrics;
20+
21+
import org.junit.jupiter.params.ParameterizedTest;
22+
import org.junit.jupiter.params.provider.Arguments;
23+
import org.junit.jupiter.params.provider.MethodSource;
24+
25+
import java.util.stream.Stream;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
29+
/** Tests for {@link MetricConfig}. */
30+
class MetricConfigTest {
31+
32+
@ParameterizedTest
33+
@MethodSource("fromStringCases")
34+
void testGetFromString(
35+
final String storedValue, final TypedGetter getter, final Object expected) {
36+
final MetricConfig config = new MetricConfig();
37+
config.setProperty("key", storedValue);
38+
assertThat(getter.get(config, "key")).isEqualTo(expected);
39+
}
40+
41+
@ParameterizedTest
42+
@MethodSource("nativeTypeCases")
43+
void testGetFromNativeType(
44+
final Object storedValue, final TypedGetter getter, final Object expected) {
45+
final MetricConfig config = new MetricConfig();
46+
config.put("key", storedValue);
47+
assertThat(getter.get(config, "key")).isEqualTo(expected);
48+
}
49+
50+
@ParameterizedTest
51+
@MethodSource("crossTypeCases")
52+
void testGetCrossType(
53+
final Object storedValue, final TypedGetter getter, final Object expected) {
54+
final MetricConfig config = new MetricConfig();
55+
config.put("key", storedValue);
56+
assertThat(getter.get(config, "key")).isEqualTo(expected);
57+
}
58+
59+
@ParameterizedTest
60+
@MethodSource("defaultValueCases")
61+
void testGetDefault(final TypedGetter getter, final Object expected) {
62+
final MetricConfig config = new MetricConfig();
63+
assertThat(getter.get(config, "missing")).isEqualTo(expected);
64+
}
65+
66+
@FunctionalInterface
67+
private interface TypedGetter {
68+
Object get(MetricConfig config, String key);
69+
}
70+
71+
private static Stream<Arguments> fromStringCases() {
72+
return Stream.of(
73+
Arguments.of("42", (TypedGetter) (c, k) -> c.getInteger(k, 0), 42),
74+
Arguments.of(
75+
"123456789012345",
76+
(TypedGetter) (c, k) -> c.getLong(k, 0L),
77+
123456789012345L),
78+
Arguments.of("3.14", (TypedGetter) (c, k) -> c.getFloat(k, 0.0f), 3.14f),
79+
Arguments.of(
80+
"2.718281828", (TypedGetter) (c, k) -> c.getDouble(k, 0.0), 2.718281828),
81+
Arguments.of("true", (TypedGetter) (c, k) -> c.getBoolean(k, false), true));
82+
}
83+
84+
private static Stream<Arguments> nativeTypeCases() {
85+
return Stream.of(
86+
Arguments.of(42, (TypedGetter) (c, k) -> c.getInteger(k, 0), 42),
87+
Arguments.of(
88+
123456789012345L,
89+
(TypedGetter) (c, k) -> c.getLong(k, 0L),
90+
123456789012345L),
91+
Arguments.of(3.14f, (TypedGetter) (c, k) -> c.getFloat(k, 0.0f), 3.14f),
92+
Arguments.of(2.718281828, (TypedGetter) (c, k) -> c.getDouble(k, 0.0), 2.718281828),
93+
Arguments.of(true, (TypedGetter) (c, k) -> c.getBoolean(k, false), true));
94+
}
95+
96+
private static Stream<Arguments> crossTypeCases() {
97+
return Stream.of(
98+
Arguments.of(42, (TypedGetter) (c, k) -> c.getLong(k, 0L), 42L),
99+
Arguments.of(100L, (TypedGetter) (c, k) -> c.getInteger(k, 0), 100),
100+
Arguments.of(42, (TypedGetter) (c, k) -> c.getDouble(k, 0.0), 42.0),
101+
Arguments.of(42, (TypedGetter) (c, k) -> c.getFloat(k, 0.0f), 42.0f));
102+
}
103+
104+
private static Stream<Arguments> defaultValueCases() {
105+
return Stream.of(
106+
Arguments.of((TypedGetter) (c, k) -> c.getInteger(k, 99), 99),
107+
Arguments.of((TypedGetter) (c, k) -> c.getLong(k, 99L), 99L),
108+
Arguments.of((TypedGetter) (c, k) -> c.getFloat(k, 1.5f), 1.5f),
109+
Arguments.of((TypedGetter) (c, k) -> c.getDouble(k, 1.5), 1.5),
110+
Arguments.of((TypedGetter) (c, k) -> c.getBoolean(k, true), true),
111+
Arguments.of((TypedGetter) (c, k) -> c.getBoolean(k, false), false),
112+
Arguments.of((TypedGetter) (c, k) -> c.getString(k, "default"), "default"));
113+
}
114+
}

0 commit comments

Comments
 (0)