Repository: beam-telemetry/telemetry_metrics_statsd
Pull request #52 (2021-03-19 18:39:12)

Resolve host on reporter start
This improves the reporter throughput 20 times.


Patch:
diff --git a/lib/telemetry_metrics_statsd.ex b/lib/telemetry_metrics_statsd.ex
index d803e19..eba666a 100644
--- a/lib/telemetry_metrics_statsd.ex
+++ b/lib/telemetry_metrics_statsd.ex
@@ -376,10 +376,8 @@ defmodule TelemetryMetricsStatsd do
     can be overriden by tags sent via the `:telemetry.execute` call.
   * `:pool_size` - The number of UDP sockets to open to report metrics. Defaults to `1`.
   * `:host_resolution_interval` - When set, makes the reporter resolve the hostname of the StatsD server
-    on a specified interval instead of looking up the hostname on every packet send using the system DNS
-    stack. This can improve the performance of publishing metrics while still allowing for dynamic
-    hostname resolution. Only applies when `:host` is a string and no an IP address. If the provided hostname
-    resolves to multiple IP addresses, the first one is used.
+    on a specified interval instead of looking it up once on start. Only applies when `:host` is a string
+    and no an IP address. If the provided hostname resolves to multiple IP addresses, the first one is used.
 
 
   You can read more about all the options in the `TelemetryMetricsStatsd` module documentation.
@@ -574,7 +572,8 @@ defmodule TelemetryMetricsStatsd do
   end
 
   defp configure_host_resolution(%{host: host, port: port}) do
-    %{host: host, port: port}
+    {:ok, hostent(h_addr_list: [ip | _ips])} = :inet.gethostbyname(host)
+    %{host: ip, port: port}
   end
 
   defp update_pool(pool_id, new_host, new_port) do


Test patch:
diff --git a/test/telemetry_metrics_statsd_test.exs b/test/telemetry_metrics_statsd_test.exs
index 5a9e74f..3b1c264 100644
--- a/test/telemetry_metrics_statsd_test.exs
+++ b/test/telemetry_metrics_statsd_test.exs
@@ -587,16 +587,14 @@ defmodule TelemetryMetricsStatsdTest do
     assert_reported(socket, "http.requests:1|c")
   end
 
-  describe "periodic hostname resolution" do
-    test "is performed when configured" do
+  describe "hostname resolution" do
+    test "is performed on start by default" do
       counter = given_counter("http.request.count")
 
       reporter =
         start_reporter(
           host: "localhost",
-          metrics: [counter],
-          name: :my_statsd,
-          host_resolution_interval: 5000
+          metrics: [counter]
         )
 
       pool_id = TelemetryMetricsStatsd.get_pool_id(reporter)
@@ -605,14 +603,37 @@ defmodule TelemetryMetricsStatsdTest do
       assert udp.host == {127, 0, 0, 1}
     end
 
-    test "is periodically repeated" do
+    test "is not periodically repeated by default" do
+      counter = given_counter("http.request.count")
+
+      reporter =
+        start_reporter(
+          host: "localhost",
+          metrics: [counter]
+        )
+
+      pool_id = TelemetryMetricsStatsd.get_pool_id(reporter)
+      udp = TelemetryMetricsStatsd.get_udp(pool_id)
+      assert udp.host == {127, 0, 0, 1}
+
+      with_mock :inet, [:passthrough, :unstick],
+        gethostbyname: fn _ -> {:ok, {:hostent, 'localhost', [], :inet, 4, [{10, 0, 0, 0}]}} end do
+        assert_raise Liveness, fn ->
+          eventually(fn ->
+            udp = TelemetryMetricsStatsd.get_udp(pool_id)
+            udp.host == {10, 0, 0, 0}
+          end)
+        end
+      end
+    end
+
+    test "is periodically repeated if configured" do
       counter = given_counter("http.request.count")
 
       reporter =
         start_reporter(
           host: "localhost",
           metrics: [counter],
-          name: :my_statsd,
           host_resolution_interval: 100
         )