Current section

22 Versions

Jump to

Compare versions

7 files changed
+99 additions
-50 deletions
  @@ -1,6 +1,8 @@
1 1 # 📜 DiscoLog
2 2
3 3 <a title="GitHub CI" href="https://github.com/mrdotb/disco-log/actions"><img src="https://github.com/mrdotb/disco-log/workflows/Tests/badge.svg" alt="GitHub CI" /></a>
4 + <a title="Latest release" href="https://hex.pm/packages/disco_log"><img src="https://img.shields.io/hexpm/v/disco_log.svg" alt="Latest release" /></a>
5 + <a title="View documentation" href="https://hexdocs.pm/disco_log"><img src="https://img.shields.io/badge/hex.pm-docs-blue.svg" alt="View documentation" /></a>
4 6
5 7 > Use Discord as a logging service and error tracking solution
  @@ -1,6 +1,6 @@
1 1 {<<"links">>,[{<<"Github">>,<<"https://github.com/mrdotb/disco-log">>}]}.
2 2 {<<"name">>,<<"disco_log">>}.
3 - {<<"version">>,<<"0.1.0">>}.
3 + {<<"version">>,<<"0.2.0">>}.
4 4 {<<"description">>,
5 5 <<"Use Discord as a logging service and error tracking solution">>}.
6 6 {<<"elixir">>,<<"~> 1.17">>}.
  @@ -17,8 +17,9 @@
17 17 <<"lib/disco_log/logger_handler.ex">>,<<"lib/disco_log/storage.ex">>,
18 18 <<"lib/disco_log/integrations">>,<<"lib/disco_log/integrations/oban.ex">>,
19 19 <<"lib/disco_log/integrations/plug.ex">>,
20 - <<"lib/disco_log/integrations/phoenix.ex">>,<<"lib/disco_log/utils.ex">>,
21 - <<"lib/mix">>,<<"lib/mix/tasks">>,<<"lib/mix/tasks/disco_log.drop.ex">>,
20 + <<"lib/disco_log/integrations/tesla.ex">>,
21 + <<"lib/disco_log/integrations/phoenix.ex">>,<<"lib/mix">>,
22 + <<"lib/mix/tasks">>,<<"lib/mix/tasks/disco_log.drop.ex">>,
22 23 <<"lib/mix/tasks/disco_log.cleanup.ex">>,
23 24 <<"lib/mix/tasks/disco_log.create.ex">>,<<"lib/disco_log.ex">>,
24 25 <<"LICENSE">>,<<"mix.exs">>,<<"README.md">>,<<".formatter.exs">>]}.
  @@ -36,14 +36,15 @@ defmodule DiscoLog.Integrations.Oban do
36 36 ]
37 37
38 38 @doc false
39 - def attach do
40 - if DiscoLog.Utils.application_spec(:oban) do
39 + def attach(force_attachment \\ false) do
40 + if Application.spec(:oban) || force_attachment do
41 41 :telemetry.attach_many(__MODULE__, @events, &__MODULE__.handle_event/4, :no_config)
42 42 end
43 43 end
44 44
45 45 def handle_event([:oban, :job, :exception], _measurements, metadata, :no_config) do
46 46 %{reason: exception, stacktrace: stacktrace, job: job} = metadata
47 + state = Map.get(metadata, :state, :failure)
47 48
48 49 context = %{
49 50 "oban" => %{
  @@ -52,7 +53,8 @@ defmodule DiscoLog.Integrations.Oban do
52 53 "id" => job.id,
53 54 "priority" => job.priority,
54 55 "queue" => job.queue,
55 - "worker" => job.worker
56 + "worker" => job.worker,
57 + "state" => state
56 58 }
57 59 }
  @@ -0,0 +1,42 @@
1 + defmodule DiscoLog.Integrations.Tesla do
2 + @moduledoc """
3 + Integration with Tesla
4 +
5 + ## How to use it
6 +
7 + Your tesla client must be configured to use the Tesla.Middleware.Telemetry
8 +
9 + ### How it works
10 +
11 + It works using Tesla's Telemetry events
12 +
13 + ### Default context
14 +
15 + The Tesla.Env struct is converted to a map and passed as context to the error report.
16 +
17 + read more on https://hexdocs.pm/tesla/Tesla.Middleware.Telemetry.html#module-telemetry-events
18 + """
19 +
20 + require Logger
21 +
22 + @events [
23 + [:tesla, :request, :exception]
24 + ]
25 +
26 + @doc false
27 + def attach(force_attachment \\ false) do
28 + if Application.spec(:tesla) || force_attachment do
29 + :telemetry.attach_many(__MODULE__, @events, &__MODULE__.handle_event/4, :no_config)
30 + end
31 + end
32 +
33 + def handle_event([:tesla, :request, :exception], _measurements, metadata, :no_config) do
34 + %{kind: kind, reason: reason, stacktrace: stacktrace, env: env} = metadata
35 +
36 + context = %{
37 + "tesla" => Map.from_struct(env)
38 + }
39 +
40 + DiscoLog.report({kind, reason}, stacktrace, context)
41 + end
42 + end
  @@ -82,14 +82,13 @@ defmodule DiscoLog.LoggerHandler do
82 82 :ok
83 83 end
84 84
85 - # "report" here is of type logger:report/0, which is a map or keyword list.
85 + # "report" here is of type logger:report/0, which is a struct, map or keyword list.
86 86 defp log_info(
87 87 %{msg: {:report, report}, meta: meta},
88 88 %LoggerHandler{} = config
89 89 ) do
90 90 metadata = take_metadata(meta, config.metadata)
91 - message = Map.new(report)
92 - Client.log_info(message, metadata)
91 + log_info_report(report, metadata)
93 92 :ok
94 93 end
95 94
  @@ -119,30 +118,14 @@ defmodule DiscoLog.LoggerHandler do
119 118 log_from_crash_reason(meta[:crash_reason], unicode_chardata, metadata)
120 119 end
121 120
122 - # "report" here is of type logger:report/0, which is a map or keyword list.
121 + # "report" here is of type logger:report/0, which is a struct, map or keyword list.
123 122 defp log_error(
124 123 %{msg: {:report, report}, meta: meta},
125 124 %LoggerHandler{} = config
126 125 ) do
127 126 metadata = take_metadata(meta, config.metadata)
128 -
129 - case Map.new(report) do
130 - %{reason: {exception, stacktrace}} when is_exception(exception) and is_list(stacktrace) ->
131 - context = Map.put(Context.get(), :metadata, metadata)
132 - error = Error.new(exception, stacktrace, context)
133 - Client.send_error(error)
134 -
135 - %{reason: {reason, stacktrace}} when is_list(stacktrace) ->
136 - context = Map.put(Context.get(), :metadata, metadata)
137 - error = Error.new(reason, stacktrace, context)
138 - Client.send_error(error)
139 -
140 - %{reason: reason} ->
141 - Client.log_error(reason, metadata)
142 -
143 - _ ->
144 - Client.log_error(report, metadata)
145 - end
127 + log_error_report(report, metadata)
128 + :ok
146 129 end
147 130
148 131 # erlang `:logger` support this format ex `:logger.error("Hello ~s", ["world"])`
  @@ -339,4 +322,44 @@ defmodule DiscoLog.LoggerHandler do
339 322 end
340 323 end)
341 324 end
325 +
326 + defp log_info_report(report, metadata) when is_struct(report) do
327 + report
328 + |> Map.from_struct()
329 + |> Map.put(:__struct__, report.__struct__)
330 + |> Client.log_info(metadata)
331 + end
332 +
333 + defp log_info_report(report, metadata) do
334 + report
335 + |> Map.new()
336 + |> Client.log_info(metadata)
337 + end
338 +
339 + defp log_error_report(report, metadata) when is_struct(report) do
340 + report
341 + |> Map.from_struct()
342 + |> Map.put(:__struct__, report.__struct__)
343 + |> Client.log_error(metadata)
344 + end
345 +
346 + defp log_error_report(report, metadata) do
347 + case Map.new(report) do
348 + %{reason: {exception, stacktrace}} when is_exception(exception) and is_list(stacktrace) ->
349 + context = Map.put(Context.get(), :metadata, metadata)
350 + error = Error.new(exception, stacktrace, context)
351 + Client.send_error(error)
352 +
353 + %{reason: {reason, stacktrace}} when is_list(stacktrace) ->
354 + context = Map.put(Context.get(), :metadata, metadata)
355 + error = Error.new(reason, stacktrace, context)
356 + Client.send_error(error)
357 +
358 + %{reason: reason} ->
359 + Client.log_error(reason, metadata)
360 +
361 + _ ->
362 + Client.log_error(report, metadata)
363 + end
364 + end
342 365 end
Loading more files…