diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9c289e69071..85964c8ce3945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,12 +39,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Implement FieldMappingIngestionMessageMapper for pull-based ingestion ([#20729](https://github.com/opensearch-project/OpenSearch/pull/20729)) ### Changed +- Make telemetry `Tags` immutable ([#20788](https://github.com/opensearch-project/OpenSearch/pull/20788)) - Move Randomness from server to libs/common ([#20570](https://github.com/opensearch-project/OpenSearch/pull/20570)) - Use env variable (OPENSEARCH_FIPS_MODE) to enable opensearch to run in FIPS enforced mode instead of checking for existence of bcFIPS jars ([#20625](https://github.com/opensearch-project/OpenSearch/pull/20625)) - Update streaming flag to use search request context ([#20530](https://github.com/opensearch-project/OpenSearch/pull/20530)) - Move pull-based ingestion classes from experimental to publicAPI ([#20704](https://github.com/opensearch-project/OpenSearch/pull/20704)) ### Fixed +- Fix `AutoForceMergeMetrics` silently dropping tags due to unreassigned `addTag()` return value ([#20788](https://github.com/opensearch-project/OpenSearch/pull/20788)) - Fix flaky test failures in ShardsLimitAllocationDeciderIT ([#20375](https://github.com/opensearch-project/OpenSearch/pull/20375)) - Prevent criteria update for context aware indices ([#20250](https://github.com/opensearch-project/OpenSearch/pull/20250)) - Update EncryptedBlobContainer to adhere limits while listing blobs in specific sort order if wrapped blob container supports ([#20514](https://github.com/opensearch-project/OpenSearch/pull/20514)) diff --git a/libs/telemetry/src/main/java/org/opensearch/telemetry/metrics/tags/Tags.java b/libs/telemetry/src/main/java/org/opensearch/telemetry/metrics/tags/Tags.java index f2a8764f8021d..8f7311cecad83 100644 --- a/libs/telemetry/src/main/java/org/opensearch/telemetry/metrics/tags/Tags.java +++ b/libs/telemetry/src/main/java/org/opensearch/telemetry/metrics/tags/Tags.java @@ -10,90 +10,349 @@ import org.opensearch.common.annotation.ExperimentalApi; -import java.util.Collections; -import java.util.HashMap; +import java.util.Arrays; import java.util.Map; import java.util.Objects; /** - * Class to create tags for a meter. + * Immutable tags for a meter. * * @opensearch.experimental */ @ExperimentalApi -public class Tags { - private final Map tagsMap; +public final class Tags { + + private static final String[] EMPTY_KEYS = new String[0]; + private static final Object[] EMPTY_VALUES = new Object[0]; + /** - * Empty value. + * Empty tags singleton. */ - public final static Tags EMPTY = new Tags(Collections.emptyMap()); + public static final Tags EMPTY = new Tags(EMPTY_KEYS, EMPTY_VALUES, 1); + + private final String[] keys; + private final Object[] values; + private final int hashCode; + + private Tags(String[] keys, Object[] values, int hashCode) { + this.keys = keys; + this.values = values; + this.hashCode = hashCode; + } + + // ----------------------------------------------------------------------- + // Factories + // ----------------------------------------------------------------------- /** - * Factory method. - * @return tags. + * Creates an immutable Tags with one String-valued pair. + * @param key tag key + * @param value tag value + * @return new Tags instance */ - public static Tags create() { - return new Tags(new HashMap<>()); + public static Tags of(String key, String value) { + Objects.requireNonNull(key, "key must not be null"); + Objects.requireNonNull(value, "value must not be null"); + String[] k = { key }; + Object[] v = { value }; + return new Tags(k, v, computeHash(k, v)); } /** - * Constructor. + * Creates an immutable Tags with one long-valued pair. + * @param key tag key + * @param value tag value + * @return new Tags instance */ - private Tags(Map tagsMap) { - this.tagsMap = tagsMap; + public static Tags of(String key, long value) { + Objects.requireNonNull(key, "key must not be null"); + String[] k = { key }; + Object[] v = { value }; + return new Tags(k, v, computeHash(k, v)); + } + + /** + * Creates an immutable Tags with one double-valued pair. + * @param key tag key + * @param value tag value + * @return new Tags instance + */ + public static Tags of(String key, double value) { + Objects.requireNonNull(key, "key must not be null"); + String[] k = { key }; + Object[] v = { value }; + return new Tags(k, v, computeHash(k, v)); + } + + /** + * Creates an immutable Tags with one boolean-valued pair. + * @param key tag key + * @param value tag value + * @return new Tags instance + */ + public static Tags of(String key, boolean value) { + Objects.requireNonNull(key, "key must not be null"); + String[] k = { key }; + Object[] v = { value }; + return new Tags(k, v, computeHash(k, v)); + } + + /** + * Creates Tags from interleaved String key-value pairs; must be even length. + * @param keyValues alternating keys and values + * @return new Tags instance + */ + public static Tags ofStringPairs(String... keyValues) { + if (keyValues == null || keyValues.length == 0) return EMPTY; + if (keyValues.length % 2 != 0) { + throw new IllegalArgumentException("keyValues must be even length, got " + keyValues.length); + } + int count = keyValues.length / 2; + String[] keys = new String[count]; + Object[] values = new Object[count]; + for (int i = 0; i < count; i++) { + keys[i] = Objects.requireNonNull(keyValues[i * 2], "key at index " + (i * 2) + " must not be null"); + values[i] = Objects.requireNonNull(keyValues[i * 2 + 1], "value at index " + (i * 2 + 1) + " must not be null"); + } + return fromPairs(keys, values, count); + } + + /** + * Merges two Tags. On key collision, {@code b} wins. Either argument may be null. + * @param a first tags + * @param b second tags + * @return merged Tags instance + */ + public static Tags concat(Tags a, Tags b) { + if (a == null || a.keys.length == 0) return (b != null) ? b : EMPTY; + if (b == null || b.keys.length == 0) return a; + + int thisLength = a.keys.length; + int otherLength = b.keys.length; + String[] mergedKeys = new String[thisLength + otherLength]; + Object[] mergedValues = new Object[thisLength + otherLength]; + int thisIndex = 0, otherIndex = 0, sortedIndex = 0; + + while (thisIndex < thisLength && otherIndex < otherLength) { + int cmp = a.keys[thisIndex].compareTo(b.keys[otherIndex]); + if (cmp < 0) { + mergedKeys[sortedIndex] = a.keys[thisIndex]; + mergedValues[sortedIndex] = a.values[thisIndex]; + thisIndex++; + } else if (cmp > 0) { + mergedKeys[sortedIndex] = b.keys[otherIndex]; + mergedValues[sortedIndex] = b.values[otherIndex]; + otherIndex++; + } else { + mergedKeys[sortedIndex] = b.keys[otherIndex]; + mergedValues[sortedIndex] = b.values[otherIndex]; + thisIndex++; + otherIndex++; + } + sortedIndex++; + } + int thisRemaining = thisLength - thisIndex; + if (thisRemaining > 0) { + System.arraycopy(a.keys, thisIndex, mergedKeys, sortedIndex, thisRemaining); + System.arraycopy(a.values, thisIndex, mergedValues, sortedIndex, thisRemaining); + sortedIndex += thisRemaining; + } + int otherRemaining = otherLength - otherIndex; + if (otherRemaining > 0) { + System.arraycopy(b.keys, otherIndex, mergedKeys, sortedIndex, otherRemaining); + System.arraycopy(b.values, otherIndex, mergedValues, sortedIndex, otherRemaining); + sortedIndex += otherRemaining; + } + + String[] keys = (sortedIndex == mergedKeys.length) ? mergedKeys : Arrays.copyOf(mergedKeys, sortedIndex); + Object[] values = (sortedIndex == mergedValues.length) ? mergedValues : Arrays.copyOf(mergedValues, sortedIndex); + return new Tags(keys, values, computeHash(keys, values)); + } + + /** + * Creates Tags from a map. + * @param map key-value pairs + * @return new Tags instance + */ + public static Tags fromMap(Map map) { + if (map == null || map.isEmpty()) return EMPTY; + String[] keys = map.keySet().toArray(new String[0]); + Arrays.sort(keys); + Object[] values = new Object[keys.length]; + for (int i = 0; i < keys.length; i++) { + values[i] = Objects.requireNonNull(map.get(keys[i]), "value for key '" + keys[i] + "' must not be null"); + } + return new Tags(keys, values, computeHash(keys, values)); + } + + // ----------------------------------------------------------------------- + // Accessors + // ----------------------------------------------------------------------- + + /** + * Returns the number of tags. + * @return tag count + */ + public int size() { + return keys.length; + } + + /** + * Returns the key at the given index. + * @param i index + * @return key + */ + public String getKey(int i) { + return keys[i]; + } + + /** + * Returns the value at the given index. + * @param i index + * @return value + */ + public Object getValue(int i) { + return values[i]; + } + + /** + * Returns an unmodifiable map preserving original value types. + * @return unmodifiable map of tags + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Map getTagsMap() { + if (keys.length == 0) return Map.of(); + Map.Entry[] entries = new Map.Entry[keys.length]; + for (int i = 0; i < keys.length; i++) { + entries[i] = Map.entry(keys[i], values[i]); + } + return Map.ofEntries(entries); + } + + // ----------------------------------------------------------------------- + // equals / hashCode / toString + // ----------------------------------------------------------------------- + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Tags that)) return false; + if (this.hashCode != that.hashCode) return false; + return Arrays.equals(keys, that.keys) && Arrays.equals(values, that.values); + } + + @Override + public String toString() { + if (keys.length == 0) return "Tags{}"; + StringBuilder sb = new StringBuilder("Tags{"); + for (int i = 0; i < keys.length; i++) { + if (i > 0) sb.append(", "); + sb.append(keys[i]).append('=').append(values[i]); + } + return sb.append('}').toString(); + } + + /** + * Factory method. + * @return empty tags + */ + public static Tags create() { + return EMPTY; } /** * Add String attribute. - * @param key key + * @param key key * @param value value - * @return Same instance. + * @return new Tags instance with the added tag */ public Tags addTag(String key, String value) { + Objects.requireNonNull(key, "key cannot be null"); Objects.requireNonNull(value, "value cannot be null"); - tagsMap.put(key, value); - return this; + return Tags.concat(this, Tags.of(key, value)); } /** * Add long attribute. - * @param key key + * @param key key * @param value value - * @return Same instance. + * @return new Tags instance with the added tag */ public Tags addTag(String key, long value) { - tagsMap.put(key, value); - return this; - }; + Objects.requireNonNull(key, "key cannot be null"); + return Tags.concat(this, Tags.of(key, value)); + } /** * Add double attribute. - * @param key key + * @param key key * @param value value - * @return Same instance. + * @return new Tags instance with the added tag */ public Tags addTag(String key, double value) { - tagsMap.put(key, value); - return this; - }; + Objects.requireNonNull(key, "key cannot be null"); + return Tags.concat(this, Tags.of(key, value)); + } /** * Add boolean attribute. - * @param key key + * @param key key * @param value value - * @return Same instance. + * @return new Tags instance with the added tag */ public Tags addTag(String key, boolean value) { - tagsMap.put(key, value); - return this; - }; + Objects.requireNonNull(key, "key cannot be null"); + return Tags.concat(this, Tags.of(key, value)); + } - /** - * Returns the attribute map. - * @return tags map - */ - public Map getTagsMap() { - return Collections.unmodifiableMap(tagsMap); + // ----------------------------------------------------------------------- + // Internal + // ----------------------------------------------------------------------- + + private static int computeHash(String[] keys, Object[] values) { + int result = 1; + for (int i = 0; i < keys.length; i++) { + result = 31 * result + keys[i].hashCode(); + result = 31 * result + values[i].hashCode(); + } + return result; } + /** Insertion-sorts by key, deduplicates (last value wins). Mutates the provided arrays. */ + private static Tags fromPairs(String[] rawKeys, Object[] rawValues, int count) { + if (count == 0) return EMPTY; + + for (int i = 1; i < count; i++) { + String key = rawKeys[i]; + Object val = rawValues[i]; + int j = i - 1; + while (j >= 0 && rawKeys[j].compareTo(key) > 0) { + rawKeys[j + 1] = rawKeys[j]; + rawValues[j + 1] = rawValues[j]; + j--; + } + rawKeys[j + 1] = key; + rawValues[j + 1] = val; + } + + int w = 0; + for (int i = 0; i < count; i++) { + if (w > 0 && rawKeys[w - 1].equals(rawKeys[i])) { + rawValues[w - 1] = rawValues[i]; + } else { + rawKeys[w] = rawKeys[i]; + rawValues[w] = rawValues[i]; + w++; + } + } + + String[] keys = (w == count) ? rawKeys : Arrays.copyOf(rawKeys, w); + Object[] values = (w == count) ? rawValues : Arrays.copyOf(rawValues, w); + return new Tags(keys, values, computeHash(keys, values)); + } } diff --git a/libs/telemetry/src/test/java/org/opensearch/telemetry/metrics/tags/TagsTests.java b/libs/telemetry/src/test/java/org/opensearch/telemetry/metrics/tags/TagsTests.java new file mode 100644 index 0000000000000..c8eb4be01efc7 --- /dev/null +++ b/libs/telemetry/src/test/java/org/opensearch/telemetry/metrics/tags/TagsTests.java @@ -0,0 +1,325 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.telemetry.metrics.tags; + +import org.opensearch.test.OpenSearchTestCase; + +import java.util.HashMap; +import java.util.Map; + +public class TagsTests extends OpenSearchTestCase { + + // --- EMPTY --- + + public void testEmptyHasZeroSize() { + assertEquals(0, Tags.EMPTY.size()); + } + + public void testEmptyGetTagsMapReturnsEmptyMap() { + assertTrue(Tags.EMPTY.getTagsMap().isEmpty()); + } + + // --- of(key, value) --- + + public void testOfSingleTag() { + Tags t = Tags.of("env", "prod"); + assertEquals(1, t.size()); + assertEquals("env", t.getKey(0)); + assertEquals("prod", t.getValue(0)); + } + + public void testOfNullKeyThrows() { + expectThrows(NullPointerException.class, () -> Tags.of(null, "v")); + } + + public void testOfNullValueThrows() { + expectThrows(NullPointerException.class, () -> Tags.of("k", (String) null)); + } + + public void testOfLong() { + Tags t = Tags.of("retries", 3L); + assertEquals(1, t.size()); + assertEquals("retries", t.getKey(0)); + assertEquals(3L, t.getValue(0)); + } + + public void testOfDouble() { + Tags t = Tags.of("latency", 1.5); + assertEquals(1, t.size()); + assertEquals(1.5, t.getValue(0)); + } + + public void testOfBoolean() { + Tags t = Tags.of("enabled", true); + assertEquals(1, t.size()); + assertEquals(true, t.getValue(0)); + } + + // --- ofStringPairs(varargs) --- + + public void testOfStringPairsEmpty() { + assertSame(Tags.EMPTY, Tags.ofStringPairs(new String[0])); + } + + public void testOfStringPairsNull() { + assertSame(Tags.EMPTY, Tags.ofStringPairs((String[]) null)); + } + + public void testOfStringPairsOddLengthThrows() { + expectThrows(IllegalArgumentException.class, () -> Tags.ofStringPairs("a", "b", "c")); + } + + public void testOfStringPairsSorted() { + Tags t = Tags.ofStringPairs("z", "1", "a", "2", "m", "3"); + assertEquals(3, t.size()); + assertEquals("a", t.getKey(0)); + assertEquals("m", t.getKey(1)); + assertEquals("z", t.getKey(2)); + } + + // --- concat --- + + public void testConcatMergesTwoTags() { + Tags a = Tags.of("a", "1"); + Tags b = Tags.of("b", "2"); + Tags merged = Tags.concat(a, b); + assertEquals(2, merged.size()); + assertEquals("a", merged.getKey(0)); + assertEquals("b", merged.getKey(1)); + } + + public void testConcatBWinsOnCollision() { + Tags a = Tags.of("k", "old"); + Tags b = Tags.of("k", "new"); + Tags merged = Tags.concat(a, b); + assertEquals(1, merged.size()); + assertEquals("new", merged.getValue(0)); + } + + public void testConcatWithNullReturnsOther() { + Tags a = Tags.of("k", "v"); + assertSame(a, Tags.concat(a, null)); + assertSame(a, Tags.concat(null, a)); + } + + public void testConcatWithEmptyReturnsOther() { + Tags a = Tags.of("k", "v"); + assertSame(a, Tags.concat(a, Tags.EMPTY)); + assertSame(a, Tags.concat(Tags.EMPTY, a)); + } + + public void testConcatBothNullReturnsEmpty() { + assertSame(Tags.EMPTY, Tags.concat(null, null)); + } + + public void testConcatEmptyWithNullReturnsEmpty() { + assertSame(Tags.EMPTY, Tags.concat(Tags.EMPTY, null)); + } + + public void testConcatPartialOverlapMergesAndDeduplicates() { + Tags a = Tags.ofStringPairs("a", "1", "c", "3"); + Tags b = Tags.ofStringPairs("b", "2", "c", "4"); + Tags merged = Tags.concat(a, b); + assertEquals(3, merged.size()); + assertEquals("a", merged.getKey(0)); + assertEquals("1", merged.getValue(0)); + assertEquals("b", merged.getKey(1)); + assertEquals("2", merged.getValue(1)); + assertEquals("c", merged.getKey(2)); + assertEquals("4", merged.getValue(2)); + } + + public void testConcatInterleavedNoOverlap() { + Tags a = Tags.ofStringPairs("a", "1", "c", "3", "e", "5"); + Tags b = Tags.ofStringPairs("b", "2", "d", "4"); + Tags merged = Tags.concat(a, b); + assertEquals(5, merged.size()); + assertEquals("a", merged.getKey(0)); + assertEquals("b", merged.getKey(1)); + assertEquals("c", merged.getKey(2)); + assertEquals("d", merged.getKey(3)); + assertEquals("e", merged.getKey(4)); + } + + public void testConcatFullOverlapBWins() { + Tags a = Tags.ofStringPairs("a", "old_a", "b", "old_b"); + Tags b = Tags.ofStringPairs("a", "new_a", "b", "new_b"); + Tags merged = Tags.concat(a, b); + assertEquals(2, merged.size()); + assertEquals("new_a", merged.getValue(0)); + assertEquals("new_b", merged.getValue(1)); + } + + public void testConcatLargeRemainderPath() { + Tags a = Tags.of("z", "26"); + Tags b = Tags.ofStringPairs("a", "1", "b", "2", "c", "3", "d", "4"); + Tags merged = Tags.concat(a, b); + assertEquals(5, merged.size()); + assertEquals("a", merged.getKey(0)); + assertEquals("d", merged.getKey(3)); + assertEquals("z", merged.getKey(4)); + assertEquals("26", merged.getValue(4)); + } + + public void testConcatHashConsistency() { + Tags viaOfStringPairs = Tags.ofStringPairs("a", "1", "b", "2"); + Tags viaConcat = Tags.concat(Tags.of("a", "1"), Tags.of("b", "2")); + assertEquals(viaOfStringPairs, viaConcat); + assertEquals(viaOfStringPairs.hashCode(), viaConcat.hashCode()); + } + + public void testConcatResultIsSorted() { + Tags a = Tags.of("x", "1"); + Tags b = Tags.ofStringPairs("a", "2", "m", "3"); + Tags merged = Tags.concat(a, b); + for (int i = 0; i < merged.size() - 1; i++) { + assertTrue(merged.getKey(i).compareTo(merged.getKey(i + 1)) < 0); + } + } + + // --- fromMap --- + + public void testFromMapRoundTrips() { + Map map = new HashMap<>(); + map.put("b", "2"); + map.put("a", "1"); + Tags t = Tags.fromMap(map); + assertEquals(2, t.size()); + assertEquals("a", t.getKey(0)); + assertEquals("b", t.getKey(1)); + assertEquals("1", t.getValue(0)); + assertEquals("2", t.getValue(1)); + } + + public void testFromMapNullReturnsEmpty() { + assertSame(Tags.EMPTY, Tags.fromMap(null)); + } + + public void testFromMapEmptyReturnsEmpty() { + assertSame(Tags.EMPTY, Tags.fromMap(Map.of())); + } + + public void testFromMapNullValueThrows() { + Map map = new HashMap<>(); + map.put("k", null); + expectThrows(NullPointerException.class, () -> Tags.fromMap(map)); + } + + // --- getTagsMap --- + + public void testGetTagsMapPreservesOriginalTypes() { + Tags t = Tags.of("num", 42L); + assertEquals(42L, t.getTagsMap().get("num")); + } + + // --- equals / hashCode --- + + public void testEqualTagsAreEqual() { + Tags a = Tags.ofStringPairs("x", "1", "y", "2"); + Tags b = Tags.ofStringPairs("x", "1", "y", "2"); + assertEquals(a, b); + assertEquals(a.hashCode(), b.hashCode()); + } + + public void testDifferentTagsAreNotEqual() { + Tags a = Tags.of("x", "1"); + Tags b = Tags.of("x", "2"); + assertNotEquals(a, b); + } + + public void testEmptyEqualsEmpty() { + assertEquals(Tags.EMPTY, Tags.create()); + } + + public void testIdentityEquals() { + Tags t = Tags.of("k", "v"); + assertEquals(t, t); + } + + public void testNotEqualToNull() { + assertNotEquals(Tags.of("k", "v"), null); + } + + public void testNotEqualToNonTagsObject() { + assertNotEquals(Tags.of("k", "v"), "not a Tags"); + } + + public void testDifferentSizeNotEqual() { + Tags a = Tags.of("k", "v"); + Tags b = Tags.ofStringPairs("k", "v", "k2", "v2"); + assertNotEquals(a, b); + } + + // --- toString --- + + public void testToStringEmpty() { + assertEquals("Tags{}", Tags.EMPTY.toString()); + } + + public void testToStringWithTags() { + Tags t = Tags.of("a", "1"); + assertEquals("Tags{a=1}", t.toString()); + } + + // --- Deprecated API backward compatibility --- + + public void testCreateReturnsEmpty() { + assertSame(Tags.EMPTY, Tags.create()); + } + + public void testAddTagReturnsNewInstance() { + Tags original = Tags.create(); + Tags updated = original.addTag("k", "v"); + assertNotSame(original, updated); + assertEquals(0, original.size()); + assertEquals(1, updated.size()); + } + + public void testAddTagChaining() { + Tags t = Tags.create().addTag("a", "1").addTag("b", "2").addTag("c", "3"); + assertEquals(3, t.size()); + assertEquals("a", t.getKey(0)); + assertEquals("b", t.getKey(1)); + assertEquals("c", t.getKey(2)); + } + + public void testAddTagLong() { + Tags t = Tags.create().addTag("num", 42L); + assertEquals(1, t.size()); + assertEquals(42L, t.getValue(0)); + } + + public void testAddTagDouble() { + Tags t = Tags.create().addTag("val", 3.14); + assertEquals(1, t.size()); + assertEquals(3.14, t.getValue(0)); + } + + public void testAddTagBoolean() { + Tags t = Tags.create().addTag("flag", true); + assertEquals(1, t.size()); + assertEquals(true, t.getValue(0)); + } + + public void testAddTagOverwritesPreviousValue() { + Tags t = Tags.create().addTag("k", "old").addTag("k", "new"); + assertEquals(1, t.size()); + assertEquals("new", t.getValue(0)); + } + + // --- Concurrent safety: Tags is immutable so no sharing issues --- + + public void testUsableAsMapKey() { + Tags t1 = Tags.of("k", "v"); + Tags t2 = Tags.of("k", "v"); + Map map = new HashMap<>(); + map.put(t1, "found"); + assertEquals("found", map.get(t2)); + } +} diff --git a/server/src/main/java/org/opensearch/index/autoforcemerge/AutoForceMergeMetrics.java b/server/src/main/java/org/opensearch/index/autoforcemerge/AutoForceMergeMetrics.java index 417835006b7a2..4cbce2d9dc23e 100644 --- a/server/src/main/java/org/opensearch/index/autoforcemerge/AutoForceMergeMetrics.java +++ b/server/src/main/java/org/opensearch/index/autoforcemerge/AutoForceMergeMetrics.java @@ -111,9 +111,9 @@ public Optional getTags(Optional nodeId, Optional shardId) Tags tags = Tags.create(); if (shardId.isPresent()) { - tags.addTag(SHARD_ID, shardId.get()); + tags = tags.addTag(SHARD_ID, shardId.get()); } else if (nodeId.isPresent()) { - tags.addTag(NODE_ID, nodeId.get()); + tags = tags.addTag(NODE_ID, nodeId.get()); } return Optional.of(tags); diff --git a/test/telemetry/src/main/java/org/opensearch/test/telemetry/TestInMemoryHistogram.java b/test/telemetry/src/main/java/org/opensearch/test/telemetry/TestInMemoryHistogram.java index 6028fcb43114f..e8ee8b8eb0fdb 100644 --- a/test/telemetry/src/main/java/org/opensearch/test/telemetry/TestInMemoryHistogram.java +++ b/test/telemetry/src/main/java/org/opensearch/test/telemetry/TestInMemoryHistogram.java @@ -11,7 +11,7 @@ import org.opensearch.telemetry.metrics.Histogram; import org.opensearch.telemetry.metrics.tags.Tags; -import java.util.HashMap; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -24,7 +24,7 @@ public class TestInMemoryHistogram implements Histogram { private AtomicInteger histogramValue = new AtomicInteger(0); - private ConcurrentHashMap, Double> histogramValueForTags = new ConcurrentHashMap<>(); + private ConcurrentHashMap, Double> histogramValueForTags = new ConcurrentHashMap<>(); /** * Constructor. @@ -43,7 +43,7 @@ public Integer getHistogramValue() { * Returns the Histogram value for tags * @return */ - public ConcurrentHashMap, Double> getHistogramValueForTags() { + public ConcurrentHashMap, Double> getHistogramValueForTags() { return this.histogramValueForTags; } @@ -54,7 +54,7 @@ public void record(double value) { @Override public synchronized void record(double value, Tags tags) { - HashMap hashMap = (HashMap) tags.getTagsMap(); - histogramValueForTags.put(hashMap, value); + Map tagsMap = tags.getTagsMap(); + histogramValueForTags.put(tagsMap, value); } }