Packages
new_relic_agent
1.12.0
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/harvest/collector/protocol.ex
defmodule NewRelic.Harvest.Collector.Protocol do
alias NewRelic.Harvest.Collector
@moduledoc false
@protocol_version 16
def preconnect, do: call_remote(%{method: "preconnect"}, [])
def connect(payload), do: call_remote(%{method: "connect"}, payload)
def transaction_event([agent_run_id, _sampling, _events] = payload),
do: call_remote(%{method: "analytic_event_data", run_id: agent_run_id}, payload)
def error_event([agent_run_id, _sampling, _events] = payload),
do: call_remote(%{method: "error_event_data", run_id: agent_run_id}, payload)
def span_event([agent_run_id, _sampling, _spans] = payload),
do: call_remote(%{method: "span_event_data", run_id: agent_run_id}, payload)
def custom_event([agent_run_id, _sampling, _events] = payload),
do: call_remote(%{method: "custom_event_data", run_id: agent_run_id}, payload)
def metric_data([agent_run_id, _ts_start, _ts_end, _data_array] = payload),
do: call_remote(%{method: "metric_data", run_id: agent_run_id}, payload)
def error([agent_run_id, _errors] = payload),
do: call_remote(%{method: "error_data", run_id: agent_run_id}, payload)
def transaction_trace([agent_run_id, _traces] = payload),
do: call_remote(%{method: "transaction_sample_data", run_id: agent_run_id}, payload)
defp call_remote(params, payload), do: call_remote(params, payload, NewRelic.Config.enabled?())
defp call_remote(_params, _payload, false), do: {:error, :harvest_disabled}
defp call_remote(params, payload, true),
do:
params
|> issue_call(payload)
|> retry_call(params, payload)
|> parse_collector_response
defp issue_call(params, payload),
do:
params
|> collector_method_url
|> NewRelic.Util.HTTP.post(payload, collector_headers())
|> parse_http_response(params)
defp retry_call({:ok, response}, _params, _payload), do: {:ok, response}
defp retry_call({:error, _response}, params, payload), do: issue_call(params, payload)
defp collector_method_url(params) do
params = Map.merge(default_collector_params(), params)
%URI{
host:
Application.get_env(:new_relic_agent, :collector_instance_host) ||
Application.get_env(:new_relic_agent, :collector_host),
path: "/agent_listener/invoke_raw_method",
query: URI.encode_query(params),
scheme: Application.get_env(:new_relic_agent, :scheme, "https"),
port: Application.get_env(:new_relic_agent, :port, 443)
}
|> URI.to_string()
end
defp parse_http_response({:ok, %{status_code: 200, body: body}}, _params),
do: {:ok, Jason.decode!(body)}
defp parse_http_response({:ok, %{status_code: status, body: body}}, params) do
NewRelic.log(:error, "#{params[:method]}: (#{status}) #{body}")
{:error, status}
end
defp parse_http_response({:error, reason}, params) do
NewRelic.log(:error, "#{params[:method]}: #{inspect(reason)}")
{:error, reason}
end
defp parse_collector_response({:error, code}), do: code
defp parse_collector_response({:ok, %{"return_value" => return_value}}), do: return_value
defp parse_collector_response({:ok, %{"exception" => exception_value}}),
do: handle_exception(exception_value)
defp handle_exception(%{"error_type" => error_type} = exception)
when error_type in [
"NewRelic::Agent::ForceDisconnectException",
"NewRelic::Agent::LicenseException"
] do
NewRelic.log(:error, exception["message"])
NewRelic.log(:error, "Disabling agent harvest")
Application.put_env(:new_relic_agent, :harvest_enabled, false)
{:error, :license_exception}
end
defp handle_exception(%{"error_type" => "NewRelic::Agent::ForceRestartException"} = exception) do
NewRelic.log(:error, exception["message"])
NewRelic.log(:error, "Reconnecting Agent")
Collector.AgentRun.reconnect()
{:error, :force_restart}
end
defp handle_exception(exception), do: exception
defp collector_headers,
do: ["user-agent": "NewRelic-ElixirAgent/#{NewRelic.Config.agent_version()}"]
defp default_collector_params,
do: %{
license_key: NewRelic.Config.license_key(),
marshal_format: "json",
protocol_version: @protocol_version
}
end