Skip to content

Commit 5038420

Browse files
authored
Send instrumentation and feature as UTF-8 strings for Statsbeat (#1707)
* Send long as a utf8 string instead of base64 string because kusto doesn't support this * Refactor tests
1 parent 7a000d3 commit 5038420

File tree

8 files changed

+53
-49
lines changed

8 files changed

+53
-49
lines changed

core/src/main/java/com/microsoft/applicationinsights/internal/statsbeat/Feature.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
package com.microsoft.applicationinsights.internal.statsbeat;
2323

24-
import java.util.Base64;
2524
import java.util.BitSet;
2625
import java.util.HashMap;
2726
import java.util.Map;
@@ -58,12 +57,17 @@ static Feature fromJavaVendor(String javaVendor) {
5857
return feature != null ? feature : Feature.JAVA_VENDOR_OTHER;
5958
}
6059

61-
static String encode(Set<Feature> features) {
60+
static long encode(Set<Feature> features) {
6261
BitSet bitSet = new BitSet(64);
6362
for (Feature feature : features) {
6463
bitSet.set(feature.bitmapIndex);
6564
}
6665

67-
return Base64.getEncoder().withoutPadding().encodeToString(bitSet.toByteArray());
66+
long[] longArray = bitSet.toLongArray();
67+
if (longArray.length > 0) {
68+
return longArray[0];
69+
}
70+
71+
return 0L;
6872
}
6973
}

core/src/main/java/com/microsoft/applicationinsights/internal/statsbeat/FeatureStatsbeat.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ class FeatureStatsbeat extends BaseStatsbeat {
4242
}
4343

4444
/**
45-
* @return a base 64 encoded string of a 64-bit long that represents a list of features enabled. Each bitfield maps to a feature.
45+
* @return a long that represents a list of features enabled. Each bitfield maps to a feature.
4646
*/
47-
String getFeature() {
47+
long getFeature() {
4848
return Feature.encode(featureList);
4949
}
5050

core/src/main/java/com/microsoft/applicationinsights/internal/statsbeat/Instrumentations.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.slf4j.Logger;
2525
import org.slf4j.LoggerFactory;
2626

27-
import java.util.Base64;
2827
import java.util.BitSet;
2928
import java.util.HashMap;
3029
import java.util.Map;
@@ -99,8 +98,8 @@ class Instrumentations {
9998
INSTRUMENTATION_MAP.put("io.opentelemetry.javaagent.tomcat-7.0", 57);
10099
}
101100

102-
// encode BitSet to a base64 encoded string
103-
static String encode(Set<String> instrumentations) {
101+
// encode BitSet to a long
102+
static long encode(Set<String> instrumentations) {
104103
BitSet bitSet = new BitSet(64);
105104
for (String instrumentation : instrumentations) {
106105
Integer index = INSTRUMENTATION_MAP.get(instrumentation);
@@ -111,6 +110,11 @@ static String encode(Set<String> instrumentations) {
111110
}
112111
}
113112

114-
return Base64.getEncoder().withoutPadding().encodeToString(bitSet.toByteArray());
113+
long[] longArray = bitSet.toLongArray();
114+
if (longArray.length > 0) {
115+
return longArray[0];
116+
}
117+
118+
return 0L;
115119
}
116120
}

core/src/main/java/com/microsoft/applicationinsights/internal/statsbeat/NetworkStatsbeat.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ protected void send() {
5757
current = new IntervalMetrics();
5858
}
5959

60-
// send instrumentation as a base64 encoded string instead of the UTF-8 string
61-
String instrumentation = Instrumentations.encode(local.instrumentationList);
60+
// send instrumentation as an UTF-8 string
61+
String instrumentation = String.valueOf(Instrumentations.encode(local.instrumentationList));
6262

6363
if (local.requestSuccessCount.get() != 0) {
6464
MetricTelemetry requestSuccessCountSt = createStatsbeatTelemetry(REQUEST_SUCCESS_COUNT_METRIC_NAME, local.requestSuccessCount.get());
@@ -137,7 +137,7 @@ void incrementExceptionCount() {
137137
}
138138

139139
// only used by tests
140-
String getInstrumentationAsBase64EncodedString() {
140+
long getInstrumentation() {
141141
return Instrumentations.encode(current.instrumentationList);
142142
}
143143

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.microsoft.applicationinsights.internal.statsbeat;
2+
3+
import org.junit.Test;
4+
5+
import java.util.Collections;
6+
import java.util.Set;
7+
8+
import static org.junit.Assert.assertEquals;
9+
10+
public class FeatureTest {
11+
12+
private static final Set<Feature> features = Collections.singleton(Feature.JAVA_VENDOR_ZULU);
13+
14+
private static final long EXPECTED_FEATURE = 2L;
15+
16+
@Test
17+
public void tesEncodeAndDecodeFeature() {
18+
long number = Feature.encode(features);
19+
assertEquals(EXPECTED_FEATURE, number);
20+
Set<Feature> result = StatsbeatTestUtils.decodeFeature(number);
21+
assertEquals(features, result);
22+
}
23+
}
Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import static org.junit.Assert.assertEquals;
1010

11-
public class StatsbeatHelperTest {
11+
public class InstrumentationsTest {
1212

1313
private static final Set<String> instrumentations;
1414
static {
@@ -20,23 +20,11 @@ public class StatsbeatHelperTest {
2020

2121
private static final long EXPECTED_INSTRUMENTATION = (long)(Math.pow(2, 13) + Math.pow(2, 21) + Math.pow(2, 57)); // Exponents are keys from StatsbeatHelper.INSTRUMENTATION_MAP.)
2222

23-
private static final Set<Feature> features = Collections.singleton(Feature.JAVA_VENDOR_ZULU);
24-
25-
private static final long EXPECTED_FEATURE = 2L;
26-
2723
@Test
2824
public void testEncodeAndDecodeInstrumentations() {
29-
String base64EncodedString = Instrumentations.encode(instrumentations);
30-
assertEquals(EXPECTED_INSTRUMENTATION, StatsbeatTestUtils.convertBase64EncodedStringToLong(base64EncodedString));
31-
Set<String> result = StatsbeatTestUtils.decodeInstrumentations(base64EncodedString);
25+
long longVal = Instrumentations.encode(instrumentations);
26+
assertEquals(EXPECTED_INSTRUMENTATION, longVal);
27+
Set<String> result = StatsbeatTestUtils.decodeInstrumentations(longVal);
3228
assertEquals(instrumentations, result);
3329
}
34-
35-
@Test
36-
public void tesEncodeAndDecodeFeature() {
37-
String base64String = Feature.encode(features);
38-
assertEquals(EXPECTED_FEATURE, StatsbeatTestUtils.convertBase64EncodedStringToLong(base64String));
39-
Set<Feature> result = StatsbeatTestUtils.decodeFeature(base64String);
40-
assertEquals(features, result);
41-
}
4230
}

core/src/test/java/com/microsoft/applicationinsights/internal/statsbeat/NetworkStatsbeatTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public void testAddInstrumentation() {
2525
networkStatsbeat.addInstrumentation("io.opentelemetry.javaagent.jdbc");
2626
networkStatsbeat.addInstrumentation("io.opentelemetry.javaagent.tomcat-7.0");
2727
networkStatsbeat.addInstrumentation("io.opentelemetry.javaagent.http-url-connection");
28-
assertEquals((long)(Math.pow(2, 13) + Math.pow(2, 21) + Math.pow(2, 57)), StatsbeatTestUtils.convertBase64EncodedStringToLong(networkStatsbeat.getInstrumentationAsBase64EncodedString())); // Exponents are keys from StatsbeatHelper.INSTRUMENTATION_MAP.)
28+
assertEquals((long)(Math.pow(2, 13) + Math.pow(2, 21) + Math.pow(2, 57)), networkStatsbeat.getInstrumentation()); // Exponents are keys from StatsbeatHelper.INSTRUMENTATION_MAP.)
2929
}
3030

3131
@Test

core/src/test/java/com/microsoft/applicationinsights/internal/statsbeat/StatsbeatTestUtils.java

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.microsoft.applicationinsights.internal.statsbeat;
22

3-
import java.util.Base64;
43
import java.util.HashMap;
54
import java.util.HashSet;
65
import java.util.Map;
@@ -81,16 +80,15 @@ public final class StatsbeatTestUtils {
8180
FEATURE_MAP_DECODING.put(5, Feature.JAVA_VENDOR_OTHER);
8281
}
8382

84-
static Set<String> decodeInstrumentations(String based64String) {
85-
return decode(based64String, INSTRUMENTATION_MAP_DECODING);
83+
static Set<String> decodeInstrumentations(long number) {
84+
return decode(number, INSTRUMENTATION_MAP_DECODING);
8685
}
8786

88-
static Set<Feature> decodeFeature(String based64String) {
89-
return decode(based64String, FEATURE_MAP_DECODING);
87+
static Set<Feature> decodeFeature(long num) {
88+
return decode(num, FEATURE_MAP_DECODING);
9089
}
9190

92-
private static <E> Set<E> decode(String based64String, Map<Integer, E> decodedMap) {
93-
long num = convertBase64EncodedStringToLong(based64String);
91+
private static <E> Set<E> decode(long num, Map<Integer, E> decodedMap) {
9492
Set<E> result = new HashSet<>();
9593
for(Map.Entry<Integer, E> entry: decodedMap.entrySet()) {
9694
double value = entry.getKey();
@@ -101,17 +99,4 @@ private static <E> Set<E> decode(String based64String, Map<Integer, E> decodedMa
10199
}
102100
return result;
103101
}
104-
105-
// convert base64 encoded string to long
106-
static long convertBase64EncodedStringToLong(String base64EncodedString) {
107-
byte[] bytes = Base64.getDecoder().decode(base64EncodedString.getBytes());
108-
long result = 0;
109-
for (int i = 0; i < bytes.length; i++) {
110-
result += ((long) bytes[i] & 0xffL) << (8 * i); // use Big Endian Byte Order.
111-
}
112-
return result;
113-
}
114-
115-
private StatsbeatTestUtils() {
116-
}
117102
}

0 commit comments

Comments
 (0)