Skip to content
Open
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
3 changes: 3 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
inputs: ["mix.exs", "{config,lib,test}**/*.{ex,exs}"]
]
14 changes: 8 additions & 6 deletions lib/raygun.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defmodule Raygun do
exception.
"""
def report_exception(exception, opts \\ []) do
System.stacktrace |> report_stacktrace(exception, opts)
System.stacktrace() |> report_stacktrace(exception, opts)
end

@doc """
Expand All @@ -48,16 +48,18 @@ defmodule Raygun do
defp send_report(error) do
headers = %{
"Content-Type": "application/json; charset=utf-8",
"Accept": "application/json",
Accept: "application/json",
"User-Agent": "Elixir Client",
"X-ApiKey": Raygun.Util.get_env(:raygun, :api_key)
}

opts = Application.get_env(:raygun, :httpoison_opts, [])

case HTTPoison.post(@api_endpoint, Poison.encode!(error), headers, opts) do
{ :ok, %HTTPoison.Response{status_code: 202} } -> :ok
{ :ok, %HTTPoison.Response{status_code: 400} } -> {:error, :bad_message}
{ :ok, %HTTPoison.Response{status_code: 403} } -> {:error, :invalid_api_key}
{ :error, _} -> {:error, :unexpected}
{:ok, %HTTPoison.Response{status_code: 202}} -> :ok
{:ok, %HTTPoison.Response{status_code: 400}} -> {:error, :bad_message}
{:ok, %HTTPoison.Response{status_code: 403}} -> {:error, :invalid_api_key}
{:error, _} -> {:error, :unexpected}
end
end
end
95 changes: 53 additions & 42 deletions lib/raygun/format.ex
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
defmodule Raygun.Format do

@moduledoc """
This module builds payloads of error messages that Raygun will understand.
These functions return maps of data which will be encoding as JSON prior
to submission to Raygun.
"""

@raygun_version Mix.Project.config[:version]
@raygun_version Mix.Project.config()[:version]

@doc """
Builds an error payload that Raygun will understand for a string.
Expand All @@ -15,15 +14,16 @@ defmodule Raygun.Format do
msg_as_string = List.to_string(msg)
message_payload(msg_as_string, opts)
end

def message_payload(msg, opts) do
%{
occurredOn: now,
occurredOn: now(),
details:
details
|> Map.merge( environment )
|> Map.merge( user(opts) )
|> Map.merge( custom(opts) )
|> Map.merge( %{error: %{ message: msg } } )
details()
|> Map.merge(environment())
|> Map.merge(user(opts))
|> Map.merge(custom(opts))
|> Map.merge(%{error: %{message: msg}})
}
end

Expand All @@ -33,13 +33,13 @@ defmodule Raygun.Format do
"""
def stacktrace_payload(stacktrace, exception, opts) do
%{
occurredOn: now,
occurredOn: now(),
details:
details
|> Map.merge( err(stacktrace, exception) )
|> Map.merge( environment )
|> Map.merge( user(opts) )
|> Map.merge( custom(opts) )
details()
|> Map.merge(err(stacktrace, exception))
|> Map.merge(environment())
|> Map.merge(user(opts))
|> Map.merge(custom(opts))
}
end

Expand All @@ -49,15 +49,15 @@ defmodule Raygun.Format do
"""
def conn_payload(conn, stacktrace, exception, opts) do
%{
occurredOn: now,
occurredOn: now(),
details:
details(opts)
|> Map.merge( err(stacktrace, exception) )
|> Map.merge( environment )
|> Map.merge( request(conn) )
|> Map.merge( response(conn) )
|> Map.merge( user(opts) )
|> Map.merge( custom(opts) )
|> Map.merge(err(stacktrace, exception))
|> Map.merge(environment())
|> Map.merge(request(conn))
|> Map.merge(response(conn))
|> Map.merge(user(opts))
|> Map.merge(custom(opts))
}
end

Expand All @@ -67,7 +67,7 @@ defmodule Raygun.Format do
"""
def custom(opts) do
%{
tags: Raygun.Util.get_env(:raygun,:tags),
tags: Raygun.Util.get_env(:raygun, :tags),
userCustomData: Enum.into(opts |> Keyword.delete(:user), %{})
}
end
Expand All @@ -78,7 +78,7 @@ defmodule Raygun.Format do
"""
def user(opts) do
if Keyword.has_key?(opts, :user) and Keyword.get(opts, :user) do
%{user: Keyword.get(opts,:user)}
%{user: Keyword.get(opts, :user)}
else
if Raygun.Util.get_env(:raygun, :system_user) do
%{user: Raygun.Util.get_env(:raygun, :system_user)}
Expand All @@ -94,22 +94,24 @@ defmodule Raygun.Format do
def environment do
disk_free_spaces = []

{:ok, hostname} = :inet.gethostname
hostname = hostname |> List.to_string
{os_type, os_flavor} = :os.type
{:ok, hostname} = :inet.gethostname()
hostname = hostname |> List.to_string()
{os_type, os_flavor} = :os.type()
os_version = "#{os_type} - #{os_flavor}"
architecture = :erlang.system_info(:system_architecture) |> List.to_string
sys_version = :erlang.system_info(:system_version) |> List.to_string
architecture = :erlang.system_info(:system_architecture) |> List.to_string()
sys_version = :erlang.system_info(:system_version) |> List.to_string()
processor_count = :erlang.system_info(:logical_processors_online)
memory_used = :erlang.memory(:total)
%{environment: %{

%{
environment: %{
osVersion: os_version,
architecture: architecture,
packageVersion: sys_version,
processorCount: processor_count,
totalPhysicalMemory: memory_used,
deviceName: hostname,
diskSpaceFree: disk_free_spaces,
diskSpaceFree: disk_free_spaces
}
}
end
Expand All @@ -118,33 +120,39 @@ defmodule Raygun.Format do
Returns deatils about the client and server machine.
"""
def details(opts \\ []) do
{:ok, hostname} = :inet.gethostname
hostname = hostname |> List.to_string
{:ok, hostname} = :inet.gethostname()
hostname = hostname |> List.to_string()

app_version = if opts[:version] do opts[:version] else Raygun.Util.get_env(:raygun, :client_version) end
app_version =
if opts[:version] do
opts[:version]
else
Raygun.Util.get_env(:raygun, :client_version)
end

%{
machineName: hostname,
version: app_version,
client: %{
name: Raygun.Util.get_env(:raygun, :client_name),
version: @raygun_version,
clientUrl: Raygun.Util.get_env(:raygun, :url),
clientUrl: Raygun.Util.get_env(:raygun, :url)
}
}
end

defp now, do: DateTime.utc_now |> DateTime.to_iso8601
defp now, do: DateTime.utc_now() |> DateTime.to_iso8601()

@doc """
Given a Plug Conn return a map containing information about the request.
"""
def request(conn) do
%{request: %{
%{
request: %{
hostName: conn.host,
url: conn.request_path,
httpMethod: conn.method,
iPAddress: conn.remote_ip |> :inet.ntoa |> List.to_string,
iPAddress: conn.remote_ip |> :inet.ntoa() |> List.to_string(),
queryString: Plug.Conn.fetch_query_params(conn).query_params,
form: Plug.Parsers.call(conn, []).params,
headers: Raygun.Util.format_headers(conn.req_headers),
Expand All @@ -157,7 +165,8 @@ defmodule Raygun.Format do
Given a Plug Conn return a map containing information about the response.
"""
def response(conn) do
%{response: %{
%{
response: %{
statusCode: conn.status
}
}
Expand All @@ -168,7 +177,9 @@ defmodule Raygun.Format do
"""
def err(stacktrace, error) do
s0 = Enum.at(stacktrace, 0) |> stacktrace_entry
%{error: %{

%{
error: %{
innerError: nil,
data: %{fileName: s0.fileName, lineNumber: s0.lineNumber, function: s0.methodName},
className: s0.className,
Expand All @@ -190,15 +201,15 @@ defmodule Raygun.Format do
that Raygun will understand.
"""
def stacktrace_entry({function, arity_or_args, location}) do
stacktrace_entry {__MODULE__, function, arity_or_args, location}
stacktrace_entry({__MODULE__, function, arity_or_args, location})
end

def stacktrace_entry({module, function, arity_or_args, location}) do
%{
lineNumber: Raygun.Util.line_from(location),
className: Raygun.Util.mod_for(module),
fileName: Raygun.Util.file_from(location),
methodName: Raygun.Util.function_and_arity(function,arity_or_args)
methodName: Raygun.Util.function_and_arity(function, arity_or_args)
}
end

end
8 changes: 5 additions & 3 deletions lib/raygun/logger.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ defmodule Raygun.Logger do
Match any errors that are logged. Send them on to Raygun.
"""
def handle_event({:error, gl, {Logger, msg, _ts, _md}}, state) when node(gl) == node() do
if Exception.exception? msg do
Raygun.report_exception msg
if Exception.exception?(msg) do
Raygun.report_exception(msg)
else
Raygun.report_message msg
Raygun.report_message(msg)
end

{:ok, state}
end

def handle_event(_data, state) do
{:ok, state}
end
Expand Down
23 changes: 13 additions & 10 deletions lib/raygun/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ defmodule Raygun.Plug.State do
end

def set(value) do
Agent.update(__MODULE__, fn (_x) -> value end)
Agent.update(__MODULE__, fn _x -> value end)
end

def get do
Agent.get(__MODULE__, fn(x) -> x end)
Agent.get(__MODULE__, fn x -> x end)
end

end

defmodule Raygun.Plug do
Expand All @@ -27,8 +26,9 @@ defmodule Raygun.Plug do
"""

defmacro __using__(opts) do
Raygun.Plug.State.start_link
Raygun.Plug.State.start_link()
Raygun.Plug.State.set(opts)

quote location: :keep do
@before_compile Raygun.Plug
end
Expand All @@ -45,20 +45,23 @@ defmodule Raygun.Plug do
"""
defmacro __before_compile__(_env) do
quote location: :keep do
defoverridable [call: 2]
defoverridable call: 2

@app_using_raygun_version Mix.Project.config[:version]
@app_using_raygun_version Mix.Project.config()[:version]

def call(conn, opts) do
try do
super(conn, opts)
rescue
exception ->
stacktrace = System.stacktrace
stacktrace = System.stacktrace()

Raygun.report_plug(conn, stacktrace, exception,
vsn: Raygun.Util.get_key(:raygun, :vsn) |> List.to_string,
version: @app_using_raygun_version,
user: Raygun.Plug.get_user(conn, unquote(Raygun.Plug.State.get)))
vsn: Raygun.Util.get_key(:raygun, :vsn) |> List.to_string(),
version: @app_using_raygun_version,
user: Raygun.Plug.get_user(conn, unquote(Raygun.Plug.State.get()))
)

reraise exception, stacktrace
end
end
Expand Down
Loading