Repository: beam-telemetry/telemetry_metrics_statsd
Pull request #47 (2020-10-16 11:21:06)

Always report sum as a counter with DataDog formatter
Previously, sum updates were reported as gauge increments/decrements. However, this sort of metric updates do not allow to view the sum of measurements in the DataDog dashboard, because with gauges, only the last measurement in the flush interval is shown.

With counter, it is possible to view the total sum of measurement values in a flush interval. To make sure that the actual sum and not a rate is displayed in the DataDog dashboard, the [`as_count()`](docs.datadoghq.com/developers/metrics/type_modifiers/?tab=rate#in-application-modifiers) modifier should be used.

While this is a breaking change, the previous behaviour was simply wrong.


Patch:
diff --git a/lib/telemetry_metrics_statsd.ex b/lib/telemetry_metrics_statsd.ex
index c66eedd..d803e19 100644
--- a/lib/telemetry_metrics_statsd.ex
+++ b/lib/telemetry_metrics_statsd.ex
@@ -232,9 +232,16 @@ defmodule TelemetryMetricsStatsd do
 
   #### Metric types
 
-  There is no difference in how the counter, last value, and sum metrics are handled between
+  There is no difference in how the counter and last value metrics are handled between
   the standard and DataDog formatters.
 
+  The sum metric is reporter as DataDog counter, which is being transformed into a rate metric
+  in DataDog: https://docs.datadoghq.com/developers/metrics/dogstatsd_metrics_submission/#count.
+  To be able to observe the actual sum of measurements make sure to use the
+  [`as_count()`](https://docs.datadoghq.com/developers/metrics/type_modifiers/?tab=rate#in-application-modifiers)
+  modifier in your DataDog dashboard. The `report_as: :count` option does not have any effect
+  with the DataDog formatter.
+
   The summary metric is reported as [DataDog
   histogram](https://docs.datadoghq.com/developers/metrics/types/?tab=histogram), as that is the
   metric that provides a set of statistics about gathered measurments on the DataDog side.
diff --git a/lib/telemetry_metrics_statsd/formatter/datadog.ex b/lib/telemetry_metrics_statsd/formatter/datadog.ex
index dcbdc98..05d5f19 100644
--- a/lib/telemetry_metrics_statsd/formatter/datadog.ex
+++ b/lib/telemetry_metrics_statsd/formatter/datadog.ex
@@ -9,19 +9,13 @@ defmodule TelemetryMetricsStatsd.Formatter.Datadog do
 
   @impl true
   def format(metric, value, tags) do
-    case format_metric_value(metric, value) do
-      [] ->
-        []
-
-      val ->
-        [
-          format_metric_name(metric.name),
-          ?:,
-          val,
-          format_sampling_rate(metric.reporter_options),
-          format_metric_tags(tags)
-        ]
-    end
+    [
+      format_metric_name(metric.name),
+      ?:,
+      format_metric_value(metric, value),
+      format_sampling_rate(metric.reporter_options),
+      format_metric_tags(tags)
+    ]
   end
 
   defp format_metric_name([segment]) do
@@ -42,29 +36,7 @@ defmodule TelemetryMetricsStatsd.Formatter.Datadog do
   defp format_metric_value(%Metrics.LastValue{}, value),
     do: [format_number(value), "|g"]
 
-  defp format_metric_value(%Metrics.Sum{reporter_options: reporter_options} = sum, value) do
-    case Keyword.get(reporter_options, :report_as) do
-      :counter -> format_counter_metric_value(sum, value)
-      _ -> format_sum_metric_value(sum, value)
-    end
-  end
-
-  defp format_counter_metric_value(%Metrics.Sum{}, value) when value >= 0,
-    do: [format_number(value), "|c"]
-
-  defp format_counter_metric_value(%Metrics.Sum{}, value) do
-    Logger.warn(
-      "Unable to format negative value: #{inspect(value)} for reporting to Datadog Counter"
-    )
-
-    []
-  end
-
-  defp format_sum_metric_value(%Metrics.Sum{}, value) when value >= 0,
-    do: [?+, format_number(value), "|g"]
-
-  defp format_sum_metric_value(%Metrics.Sum{}, value),
-    do: [format_number(value), "|g"]
+  defp format_metric_value(%Metrics.Sum{}, value), do: [format_number(value), "|c"]
 
   defp format_number(number) when is_integer(number) do
     :erlang.integer_to_binary(number)


Test patch:
diff --git a/test/telemetry_metrics_statsd/formatter/datadog_test.exs b/test/telemetry_metrics_statsd/formatter/datadog_test.exs
index 9a16eb9..6764387 100644
--- a/test/telemetry_metrics_statsd/formatter/datadog_test.exs
+++ b/test/telemetry_metrics_statsd/formatter/datadog_test.exs
@@ -11,29 +11,16 @@ defmodule TelemetryMetricsStatsd.Formatter.DatadogTest do
     assert format(m, 30, []) == "my.awesome.metric:1|c"
   end
 
-  test "positive sum update is formatted as a Datadog gauge with +n value" do
+  test "positive sum update is formatted as a Datadog counter with n value" do
     m = given_sum("my.awesome.metric")
 
-    assert format(m, 21, []) == "my.awesome.metric:+21|g"
-  end
-
-  test "negative sum update is formatted as a Datadog gauge with -n value" do
-    m = given_sum("my.awesome.metric")
-
-    assert format(m, -21, []) == "my.awesome.metric:-21|g"
-  end
-
-  test "positive sum update as counter is formatted as a Datadog counter with n value" do
-    m = given_sum("my.awesome.metric", reporter_options: [report_as: :counter])
-
     assert format(m, 21, []) == "my.awesome.metric:21|c"
   end
 
-  @tag capture_log: true
-  test "negative sum update as counter for Datadog is dropped" do
-    m = given_sum("my.awesome.metric", reporter_options: [report_as: :counter])
+  test "negative sum update is formatted as a Datadog counter with -n value" do
+    m = given_sum("my.awesome.metric")
 
-    assert format(m, -21, []) == ""
+    assert format(m, -21, []) == "my.awesome.metric:-21|c"
   end
 
   test "last_value update is formatted as a Datadog gauge with absolute value" do