Repository: denoland/deno
Pull request: fix: recording metrics with more than 3 attributes

We were calling `op_otel_metric_attribute3` with the wrong arguments.


Changed files:
filename: ext/telemetry/telemetry.ts
patch: @@ -924,8 +924,7 @@ function record(
       const remaining = attrs.length - i;
       if (remaining > 3) {
         op_otel_metric_attribute3(
-          instrument,
-          value,
+          attrs.length,
           attrs[i][0],
           attrs[i][1],
           attrs[i + 1][0],
@@ -982,8 +981,7 @@ function recordObservable(
       const remaining = attrs.length - i;
       if (remaining > 3) {
         op_otel_metric_attribute3(
-          instrument,
-          value,
+          attrs.length,
           attrs[i][0],
           attrs[i][1],
           attrs[i + 1][0],

filename: tests/specs/cli/otel_basic/main.ts
patch: @@ -45,13 +45,37 @@ const server = Deno.serve(
           data.metrics.sort((a, b) => a.name.localeCompare(b.name));
           for (const metric of data.metrics) {
             if ("histogram" in metric) {
+              metric.histogram.dataPoints.sort((a, b) => {
+                const aKey = a.attributes
+                  .sort((x, y) => x.key.localeCompare(y.key))
+                  .map(({ key, value }) => `${key}:${JSON.stringify(value)}`)
+                  .join("|");
+                const bKey = b.attributes
+                  .sort((x, y) => x.key.localeCompare(y.key))
+                  .map(({ key, value }) => `${key}:${JSON.stringify(value)}`)
+                  .join("|");
+                return aKey.localeCompare(bKey);
+              });
+
               for (const dataPoint of metric.histogram.dataPoints) {
                 dataPoint.attributes.sort((a, b) => {
                   return a.key.localeCompare(b.key);
                 });
               }
             }
             if ("sum" in metric) {
+              metric.sum.dataPoints.sort((a, b) => {
+                const aKey = a.attributes
+                  .sort((x, y) => x.key.localeCompare(y.key))
+                  .map(({ key, value }) => `${key}:${JSON.stringify(value)}`)
+                  .join("|");
+                const bKey = b.attributes
+                  .sort((x, y) => x.key.localeCompare(y.key))
+                  .map(({ key, value }) => `${key}:${JSON.stringify(value)}`)
+                  .join("|");
+                return aKey.localeCompare(bKey);
+              });
+
               for (const dataPoint of metric.sum.dataPoints) {
                 dataPoint.attributes.sort((a, b) => {
                   return a.key.localeCompare(b.key);

filename: tests/specs/cli/otel_basic/metric.out
patch: @@ -9,6 +9,39 @@
       "metadata": [],
       "sum": {
         "dataPoints": [
+          {
+            "attributes": [
+              {
+                "key": "a",
+                "value": {
+                  "stringValue": "b"
+                }
+              },
+              {
+                "key": "c",
+                "value": {
+                  "stringValue": "d"
+                }
+              },
+              {
+                "key": "e",
+                "value": {
+                  "stringValue": "f"
+                }
+              },
+              {
+                "key": "g",
+                "value": {
+                  "stringValue": "h"
+                }
+              }
+            ],
+            "startTimeUnixNano": [WILDCARD],
+            "timeUnixNano": [WILDCARD],
+            "exemplars": [],
+            "flags": 0,
+            "asDouble": 1
+          },
           {
             "attributes": [
               {
@@ -36,6 +69,39 @@
       "metadata": [],
       "sum": {
         "dataPoints": [
+          {
+            "attributes": [
+              {
+                "key": "a",
+                "value": {
+                  "stringValue": "b"
+                }
+              },
+              {
+                "key": "c",
+                "value": {
+                  "stringValue": "d"
+                }
+              },
+              {
+                "key": "e",
+                "value": {
+                  "stringValue": "f"
+                }
+              },
+              {
+                "key": "g",
+                "value": {
+                  "stringValue": "h"
+                }
+              }
+            ],
+            "startTimeUnixNano": [WILDCARD],
+            "timeUnixNano": [WILDCARD],
+            "exemplars": [],
+            "flags": 0,
+            "asDouble": 1
+          },
           {
             "attributes": [
               {

filename: tests/specs/cli/otel_basic/metric.ts
patch: @@ -81,6 +81,8 @@ upDownCounter.add(-1, attributes);
 gauge.record(1, attributes);
 histogram.record(1, attributes);
 
+counter.add(1, { a: "b", c: "d", e: "f", g: "h" });
+
 const timer = setTimeout(() => {}, 100000);
 
 await Promise.all([