Packages
new_relic_agent
1.21.1
1.40.3
1.40.2
1.40.1
1.40.0
1.39.0
1.38.0
1.37.0
1.36.0
1.35.0
1.34.0
1.33.0
1.32.0
1.31.1
1.31.0
1.30.0
1.29.0
1.28.0
1.27.8
1.27.7
1.27.6
1.27.5
1.27.4
1.27.3
1.27.2
1.27.1
1.27.0
1.26.0
1.25.3
1.25.2
1.25.1
1.25.0
1.24.5
1.24.4
1.24.3
1.24.2
1.24.1
1.24.0
1.24.0-rc.10
1.24.0-rc.9
1.24.0-rc.8
1.24.0-rc.7
1.23.6
1.23.5
1.23.4
1.23.3
1.23.2
1.23.1
1.23.0
1.23.0-rc.6
1.23.0-rc.5
1.23.0-rc.4
1.23.0-rc.3
1.23.0-rc.2
1.23.0-rc.1
1.22.6
1.22.5
1.22.4
1.22.3
1.22.2
1.22.1
1.22.0
1.21.2
1.21.1
1.21.0
1.21.0-rc.3
1.21.0-rc.1
1.20.0
1.20.0-rc.1
1.19.7
1.19.6
1.19.5
1.19.4
1.19.3
1.19.2
1.19.1
1.19.0
1.18.5
1.18.4
1.18.3
1.18.2
1.18.1
1.18.0
1.18.0-rc.5
1.18.0-rc.4
1.18.0-rc.2
1.18.0-rc.1
1.17.1
1.17.0
1.17.0-rc.4
1.17.0-rc.3
1.17.0-rc.2
1.17.0-rc.1
1.17.0-rc.0
1.16.7
1.16.6
1.16.5
1.16.4
1.16.3
1.16.2
1.16.1
1.16.0
1.16.0-rc.2
1.16.0-rc.1
1.16.0-rc.0
1.15.0
1.15.0-rc.3
1.15.0-rc.2
1.15.0-rc.1
1.14.0
1.13.1
1.13.0
1.12.0
1.11.0
1.10.2
1.10.1
1.10.0
1.9.12
1.9.11
1.9.10
1.9.9
1.9.8
1.9.7
1.9.6
1.9.5
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.0
1.7.0
1.6.2
1.6.1
1.6.0
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.0
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
New Relic's Open-Source Elixir Agent
Current section
Files
Jump to
Current section
Files
lib/new_relic/util.ex
defmodule NewRelic.Util do
@moduledoc false
alias NewRelic.Util.Vendor
def hostname do
maybe_heroku_dyno_hostname() || get_hostname()
end
def pid, do: System.get_pid() |> String.to_integer()
def time_to_ms({megasec, sec, microsec}),
do: (megasec * 1_000_000 + sec) * 1_000 + round(microsec / 1_000)
def process_name(pid) do
case Process.info(pid, :registered_name) do
nil -> nil
{:registered_name, []} -> nil
{:registered_name, name} -> name
end
end
def metric_join(segments) when is_list(segments) do
segments
|> Enum.filter(& &1)
|> Enum.map(&to_string/1)
|> Enum.map(&String.replace_leading(&1, "/", ""))
|> Enum.map(&String.replace_trailing(&1, "/", ""))
|> Enum.join("/")
end
def deep_flatten(attrs) when is_list(attrs) do
Enum.flat_map(attrs, &deep_flatten/1)
end
def deep_flatten({key, list_value}) when is_list(list_value) do
list_value
|> Enum.slice(0..9)
|> Enum.with_index()
|> Enum.flat_map(fn {v, index} -> deep_flatten({"#{key}.#{index}", v}) end)
|> Enum.concat([{"#{key}.length", length(list_value)}])
end
def deep_flatten({key, %{__struct__: _} = value}) do
[{key, value}]
end
def deep_flatten({key, map_value}) when is_map(map_value) do
map_value
|> Enum.slice(0..9)
|> Enum.flat_map(fn {k, v} -> deep_flatten({"#{key}.#{k}", v}) end)
|> Enum.concat([{"#{key}.size", map_size(map_value)}])
end
def deep_flatten({key, value}) do
[{key, value}]
end
def coerce_attributes(attrs) when is_map(attrs) do
do_coerce_attributes(attrs) |> Map.new()
end
def coerce_attributes(attrs) when is_list(attrs) do
do_coerce_attributes(attrs)
end
defp do_coerce_attributes(attrs) do
Enum.flat_map(attrs, fn
{_key, nil} ->
[]
{key, value} when is_number(value) when is_boolean(value) ->
[{key, value}]
{key, value} when is_bitstring(value) ->
case String.valid?(value) do
true -> [{key, value}]
false -> [bad_value(key, value)]
end
{key, value} when is_reference(value) when is_pid(value) when is_port(value) ->
[{key, inspect(value)}]
{key, value} when is_atom(value) ->
[{key, to_string(value)}]
{key, %struct{} = value} when struct in [Date, DateTime, Time, NaiveDateTime] ->
[{key, struct.to_iso8601(value)}]
{key, value} ->
[bad_value(key, value)]
end)
end
defp bad_value(key, value) do
NewRelic.log(:debug, "Bad attribute value: #{inspect(key)} => #{inspect(value)}")
{key, "[BAD_VALUE]"}
end
def elixir_environment() do
build_info = System.build_info()
[
["Language", "Elixir"],
["Elixir Version", build_info[:version]],
["OTP Version", build_info[:otp_release]],
["Elixir build", build_info[:build]]
]
end
@nr_metadata_prefix "NEW_RELIC_METADATA_"
def metadata() do
System.get_env()
|> Enum.filter(fn {key, _} -> String.starts_with?(key, @nr_metadata_prefix) end)
|> Enum.into(%{})
end
def utilization() do
%{
metadata_version: 5,
logical_processors: :erlang.system_info(:logical_processors),
total_ram_mib: get_system_memory(),
hostname: hostname()
}
|> maybe_add_ip_addresses
|> maybe_add_fqdn
|> maybe_add_linux_boot_id()
|> Vendor.maybe_add_vendors()
end
def maybe_heroku_dyno_hostname do
System.get_env("DYNO")
|> case do
nil -> nil
"scheduler." <> _ -> "scheduler.*"
"run." <> _ -> "run.*"
name -> name
end
end
def maybe_add_linux_boot_id(util) do
case File.read("/proc/sys/kernel/random/boot_id") do
{:ok, boot_id} -> Map.put(util, "boot_id", boot_id)
_ -> util
end
end
def maybe_add_ip_addresses(util) do
case :inet.getif() do
{:ok, addrs} ->
ip_address = Enum.map(addrs, fn {ip, _, _} -> to_string(:inet.ntoa(ip)) end)
Map.put(util, :ip_address, ip_address)
_ ->
util
end
end
def maybe_add_fqdn(util) do
case :net_adm.dns_hostname(:net_adm.localhost()) do
{:ok, fqdn} -> Map.put(util, :full_hostname, to_string(fqdn))
_ -> util
end
end
@mb 1024 * 1024
defp get_system_memory() do
case :memsup.get_system_memory_data()[:system_total_memory] do
nil -> nil
bytes -> trunc(bytes / @mb)
end
end
defp get_hostname do
with {:ok, name} <- :inet.gethostname(), do: to_string(name)
end
def uuid4() do
"#{u(4)}-#{u(2)}-4a#{u(1)}-#{u(2)}-#{u(6)}"
end
defp u(len) do
:crypto.strong_rand_bytes(len)
|> Base.encode16(case: :lower)
end
end