Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

K8s support #140

Merged
merged 2 commits into from
Oct 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/new_relic/harvest/collector/connect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ defmodule NewRelic.Harvest.Collector.Connect do
%{label_type: key, label_value: value}
end),
utilization: NewRelic.Util.utilization(),
metadata: NewRelic.Util.metadata(),
environment: NewRelic.Util.elixir_environment(),
agent_version: NewRelic.Config.agent_version()
}
Expand Down
52 changes: 48 additions & 4 deletions lib/new_relic/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule NewRelic.Util do
alias NewRelic.Util.Vendor

def hostname do
Vendor.maybe_heroku_dyno_hostname() || get_hostname()
maybe_heroku_dyno_hostname() || get_hostname()
end

def pid, do: System.get_pid() |> String.to_integer()
Expand Down Expand Up @@ -57,15 +57,59 @@ defmodule NewRelic.Util do
]
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: 3,
metadata_version: 5,
logical_processors: :erlang.system_info(:logical_processors),
total_ram_mib: get_system_memory(),
hostname: hostname()
}
|> Vendor.maybe_add_linux_boot_id()
|> Vendor.maybe_add_cloud_vendors()
|> 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
Expand Down
33 changes: 17 additions & 16 deletions lib/new_relic/util/vendor.ex
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
defmodule NewRelic.Util.Vendor do
@moduledoc false

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_heroku_dyno_hostname do
System.get_env("DYNO")
def maybe_add_vendors(util, options \\ []) do
%{}
|> maybe_add_aws(options)
|> maybe_add_kubernetes()
|> case do
nil -> nil
"scheduler." <> _ -> "scheduler.*"
"run." <> _ -> "run.*"
name -> name
vendors when map_size(vendors) == 0 -> util
vendors -> Map.put(util, :vendors, vendors)
end
end

@aws_url "http://169.254.169.254/2016-09-02/dynamic/instance-identity/document"
def maybe_add_cloud_vendors(util, options \\ []) do
def maybe_add_aws(vendors, options \\ []) do
Keyword.get(options, :aws_url, @aws_url)
|> aws_vendor_hash()
|> case do
nil -> util
aws_hash -> Map.put(util, :vendors, %{aws: aws_hash})
nil -> vendors
aws_hash -> Map.put(vendors, :aws, aws_hash)
end
end

def maybe_add_kubernetes(vendors) do
System.get_env("KUBERNETES_SERVICE_HOST")
|> case do
nil -> vendors
value -> Map.put(vendors, :kubernetes, %{kubernetes_service_host: value})
end
end

Expand Down
12 changes: 8 additions & 4 deletions test/integration/agent_run_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ defmodule AgentRunIntegrationTest do
:ok
end

test "has util data in connect payload" do
payload = Collector.Connect.payload()
ram = get_in(payload, [Access.at(0), :utilization, :total_ram_mib])
assert is_integer(ram)
test "Connect payload" do
[payload] = Collector.Connect.payload()

assert get_in(payload, [:utilization, :total_ram_mib])
|> is_integer

assert get_in(payload, [:metadata])
|> is_map
end

test "Stores needed connect data" do
Expand Down
26 changes: 23 additions & 3 deletions test/util_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,43 @@ defmodule UtilTest do
end

test "minimal utilization check" do
assert %{metadata_version: 3} = NewRelic.Util.utilization()
assert %{metadata_version: 5} = util = NewRelic.Util.utilization()

assert util[:ip_address] |> is_list
assert util[:full_hostname] |> is_binary
end

test "AWS utilization fast timeout" do
assert %{} ==
NewRelic.Util.Vendor.maybe_add_cloud_vendors(%{},
NewRelic.Util.Vendor.maybe_add_vendors(%{},
aws_url: "http://httpbin.org/delay/10"
)
end

test "AWS utilization info" do
{:ok, _} = Plug.Cowboy.http(FakeAwsPlug, [], port: 8883)

util = NewRelic.Util.Vendor.maybe_add_cloud_vendors(%{}, aws_url: "http://localhost:8883")
util = NewRelic.Util.Vendor.maybe_add_vendors(%{}, aws_url: "http://localhost:8883")
assert get_in(util, [:vendors, :aws, "instanceId"]) == "test.id"
end

test "Kubernetes utilization info" do
System.put_env("KUBERNETES_SERVICE_HOST", "k8s-host")

util = NewRelic.Util.utilization()
assert get_in(util, [:vendors, :kubernetes, :kubernetes_service_host]) == "k8s-host"

System.delete_env("KUBERNETES_SERVICE_HOST")
end

test "New Relic metadata detection" do
System.put_env("NEW_RELIC_METADATA_TEST", "value")

assert NewRelic.Util.metadata() == %{"NEW_RELIC_METADATA_TEST" => "value"}

System.delete_env("NEW_RELIC_METADATA_TEST")
end

test "hostname detection" do
System.put_env("DYNO", "foobar")
assert NewRelic.Util.hostname() == "foobar"
Expand Down