@@ -98,42 +98,42 @@ public NormalizedDataMetricsDataBuilder metric(String metricPrefix, String metri
9898
9999 public NormalizedDataMetricsDataBuilder resourceAttribute (String key , String value ) {
100100 if (hasText (key )) {
101- resourceAttributes .add (OtlpAttributeUtils . attribute (key , value ));
101+ resourceAttributes .add (attribute (key , value ));
102102 }
103103 return this ;
104104 }
105105
106106 public NormalizedDataMetricsDataBuilder resourceAttribute (String key , AnyValue value ) {
107107 if (hasText (key ) && value != null ) {
108- resourceAttributes .add (OtlpAttributeUtils . attribute (key , value ));
108+ resourceAttributes .add (attribute (key , value ));
109109 }
110110 return this ;
111111 }
112112
113113 public NormalizedDataMetricsDataBuilder resourceAttributes (List <KeyValue > attributes ) {
114114 if (attributes != null ) {
115- resourceAttributes .addAll (attributes );
115+ resourceAttributes .addAll (normalizeAttributeKeys ( attributes ) );
116116 }
117117 return this ;
118118 }
119119
120120 public NormalizedDataMetricsDataBuilder scopeAttribute (String key , String value ) {
121121 if (hasText (key )) {
122- scopeAttributes .add (OtlpAttributeUtils . attribute (key , value ));
122+ scopeAttributes .add (attribute (key , value ));
123123 }
124124 return this ;
125125 }
126126
127127 public NormalizedDataMetricsDataBuilder scopeAttribute (String key , AnyValue value ) {
128128 if (hasText (key ) && value != null ) {
129- scopeAttributes .add (OtlpAttributeUtils . attribute (key , value ));
129+ scopeAttributes .add (attribute (key , value ));
130130 }
131131 return this ;
132132 }
133133
134134 public NormalizedDataMetricsDataBuilder scopeAttributes (List <KeyValue > attributes ) {
135135 if (attributes != null ) {
136- scopeAttributes .addAll (attributes );
136+ scopeAttributes .addAll (normalizeAttributeKeys ( attributes ) );
137137 }
138138 return this ;
139139 }
@@ -236,9 +236,9 @@ private NumberDataPoint dataPoint(NormalizedData normalizedData, String contentP
236236 NumberDataPoint dataPoint = new NumberDataPoint ();
237237 dataPoint .setTimeUnixNano (OtlpTimeUtils .unixNanoAsString (normalizedData .getTimeObserved ()));
238238 dataPoint .setAsDouble (metricValue (content , jsonValue , jsonType ).doubleValue ());
239- dataPoint .getAttributes ().add (OtlpAttributeUtils . attribute ("iot.content.path" , contentPath ));
239+ dataPoint .getAttributes ().add (attribute ("iot.content.path" , contentPath ));
240240 dataPoint .getAttributes ()
241- .add (OtlpAttributeUtils . attribute ("iot.content.type" , normalizedData .getContentType ()));
241+ .add (attribute ("iot.content.type" , normalizedData .getContentType ()));
242242 return dataPoint ;
243243 }
244244
@@ -248,14 +248,25 @@ public String metricName(NormalizedData normalizedData) {
248248
249249 public String metricName (String contentPath ) {
250250 if (!hasText (contentPath )) {
251- return metricPrefix + ".value" ;
251+ return toDotSeparatedSnakeCase ( metricPrefix ) + ".value" ;
252252 }
253- String sanitizedPath = contentPath .strip ().replace ('\\' , '/' ).replaceAll ("^/+" , "" ). replace ( '/' , '.' )
254- .replaceAll ("[^A-Za-z0-9_.-]+" , "_" ).replaceAll ("\\ .+" , "." );
253+ String sanitizedPath = toDotSeparatedSnakeCase ( contentPath .strip ().replace ('\\' , '/' ).replaceAll ("^/+" , "" )
254+ .replace ( '/' , '.' ). replaceAll ("[^A-Za-z0-9_.-]+" , "_" ).replaceAll ("\\ .+" , "." ) );
255255 if (!hasText (sanitizedPath )) {
256256 sanitizedPath = "value" ;
257257 }
258- return metricPrefix + "." + sanitizedPath ;
258+ return toDotSeparatedSnakeCase (metricPrefix ) + "." + sanitizedPath ;
259+ }
260+
261+ public static String toDotSeparatedSnakeCase (String input ) {
262+ if (!hasText (input )) {
263+ return input ;
264+ }
265+ String [] parts = input .strip ().replace ('\\' , '/' ).replace ('/' , '.' ).split ("\\ ." );
266+ for (int i = 0 ; i < parts .length ; i ++) {
267+ parts [i ] = toSnakeCase (parts [i ]);
268+ }
269+ return String .join ("." , parts ).replaceAll ("\\ .+" , "." );
259270 }
260271
261272 public BigDecimal metricValue (NormalizedData normalizedData ) {
@@ -293,6 +304,19 @@ private BigDecimal metricValue(String content, OracleJsonValue jsonValue, Oracle
293304 }
294305 }
295306
307+ private static String toSnakeCase (String value ) {
308+ if (!hasText (value )) {
309+ return value ;
310+ }
311+ return value .strip ()
312+ .replaceAll ("([A-Z]+)([A-Z][a-z])" , "$1_$2" )
313+ .replaceAll ("([a-z0-9])([A-Z])" , "$1_$2" )
314+ .replaceAll ("[^A-Za-z0-9]+" , "_" )
315+ .replaceAll ("_+" , "_" )
316+ .replaceAll ("^_|_$" , "" )
317+ .toLowerCase (java .util .Locale .ROOT );
318+ }
319+
296320 private static String appendPath (String contentPath , String fieldName ) {
297321 if (!hasText (contentPath )) {
298322 return fieldName ;
@@ -310,9 +334,8 @@ private static boolean isNumeric(OracleJsonType jsonType) {
310334
311335 private ResourceMetrics resourceMetrics (NormalizedData normalizedData ) {
312336 Resource resource = new Resource ();
313- resource .getAttributes ().add (OtlpAttributeUtils .attribute ("service.name" , serviceName ));
314- resource .getAttributes ().add (OtlpAttributeUtils .attribute ("iot.digital_twin.instance_id" ,
315- normalizedData .getDigitalTwinInstanceId ()));
337+ resource .getAttributes ().add (attribute ("service.name" , serviceName ));
338+ resource .getAttributes ().add (attribute ("iot.digital_twin.instance_id" , normalizedData .getDigitalTwinInstanceId ()));
316339
317340 ResourceMetrics resourceMetrics = new ResourceMetrics ();
318341 resourceMetrics .setResource (resource );
@@ -321,7 +344,7 @@ private ResourceMetrics resourceMetrics(NormalizedData normalizedData) {
321344
322345 private ScopeMetrics scopeMetrics () {
323346 InstrumentationScope scope = new InstrumentationScope ();
324- scope .setName (scopeName );
347+ scope .setName (toDotSeparatedSnakeCase ( scopeName ) );
325348 scope .setVersion (scopeVersion );
326349
327350 ScopeMetrics scopeMetrics = new ScopeMetrics ();
@@ -337,6 +360,24 @@ private static void addMissingAttributes(List<KeyValue> target, List<KeyValue> a
337360 }
338361 }
339362
363+ private static List <KeyValue > normalizeAttributeKeys (List <KeyValue > attributes ) {
364+ List <KeyValue > normalizedAttributes = new ArrayList <>();
365+ for (KeyValue attribute : attributes ) {
366+ if (attribute != null ) {
367+ normalizedAttributes .add (attribute (attribute .getKey (), attribute .getValue ()));
368+ }
369+ }
370+ return normalizedAttributes ;
371+ }
372+
373+ private static KeyValue attribute (String key , String value ) {
374+ return OtlpAttributeUtils .attribute (toDotSeparatedSnakeCase (key ), value );
375+ }
376+
377+ private static KeyValue attribute (String key , AnyValue value ) {
378+ return OtlpAttributeUtils .attribute (toDotSeparatedSnakeCase (key ), value );
379+ }
380+
340381 private static boolean hasText (String value ) {
341382 return value != null && !value .isBlank ();
342383 }
0 commit comments