-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Better gen_stage implementation this time around
- Loading branch information
Showing
8 changed files
with
212 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
alias Experimental.GenStage | ||
|
||
defmodule SlackLoggerBackend.Consumer do | ||
|
||
@moduledoc """ | ||
Consumes logger events and pushes them onto the worker pool to send to Slack. | ||
""" | ||
use GenStage | ||
alias SlackLoggerBackend.{Formatter, Pool} | ||
|
||
@doc false | ||
def start_link(max_demand, min_demand) do | ||
GenStage.start_link(__MODULE__, {max_demand, min_demand}, name: __MODULE__) | ||
end | ||
|
||
@doc false | ||
def init({max_demand, min_demand}) do | ||
{:consumer, %{}, | ||
subscribe_to: [{Formatter, max_demand: max_demand, min_demand: min_demand}]} | ||
end | ||
|
||
@doc false | ||
def handle_events([], _from, interval) do | ||
process_events([], interval) | ||
end | ||
|
||
@doc false | ||
def handle_events(events, _from, state) do | ||
events | ||
|> Enum.filter(fn evt -> evt != :empty end) | ||
|> process_events(state) | ||
end | ||
|
||
defp process_events([], state) do | ||
{:noreply, [], state} | ||
end | ||
|
||
defp process_events([{url, json}|events], state) do | ||
Pool.post(url, json) | ||
process_events(events, state) | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
defmodule SlackLoggerBackend.FormatHelper do | ||
|
||
@moduledoc """ | ||
Simple formatter for Slack messages. | ||
""" | ||
|
||
import Poison, only: [encode: 1] | ||
|
||
@doc """ | ||
Formats a log event for Slack. | ||
""" | ||
def format_event({level, message, module, function, file, line}) do | ||
IO.puts "MESSAGE: #{message}" | ||
{:ok, event} = %{attachments: [%{ | ||
fallback: "An #{level} level event has occurred: #{message}", | ||
pretext: message, | ||
fields: [%{ | ||
title: "Level", | ||
value: level, | ||
short: true | ||
}, %{ | ||
title: "Module", | ||
value: module, | ||
short: true | ||
}, %{ | ||
title: "Function", | ||
value: function, | ||
short: true | ||
}, %{ | ||
title: "File", | ||
value: file, | ||
short: true | ||
}, %{ | ||
title: "Line", | ||
value: line, | ||
short: true | ||
}] | ||
}]} | ||
|> encode | ||
event | ||
end | ||
|
||
@doc """ | ||
Formats a log event for Slack. | ||
""" | ||
def format_event({level, message, application, module, function, file, line}) do | ||
IO.puts "MESSAGE: #{message}" | ||
{:ok, event} = %{attachments: [%{ | ||
fallback: "An #{level} level event has occurred: #{message}", | ||
pretext: message, | ||
fields: [%{ | ||
title: "Level", | ||
value: level, | ||
short: true | ||
}, %{ | ||
title: "Application", | ||
value: application, | ||
short: true | ||
}, %{ | ||
title: "Module", | ||
value: module, | ||
short: true | ||
}, %{ | ||
title: "Function", | ||
value: function, | ||
short: true | ||
}, %{ | ||
title: "File", | ||
value: file, | ||
short: true | ||
}, %{ | ||
title: "Line", | ||
value: line, | ||
short: true | ||
}] | ||
}]} | ||
|> encode | ||
event | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,36 @@ | ||
alias Experimental.GenStage | ||
|
||
defmodule SlackLoggerBackend.Formatter do | ||
|
||
@moduledoc """ | ||
Simple formatter for Slack messages. | ||
Formats log events into pretty Slack messages. | ||
""" | ||
|
||
import Poison, only: [encode: 1] | ||
use GenStage | ||
alias SlackLoggerBackend.{Producer, FormatHelper} | ||
|
||
@doc """ | ||
Formats a log event for Slack. | ||
""" | ||
def format_event({level, message, module, function, file, line}) do | ||
{:ok, event} = %{attachments: [%{ | ||
fallback: "An #{level} level event has occurred: #{message}", | ||
pretext: message, | ||
fields: [%{ | ||
title: "Level", | ||
value: level, | ||
short: true | ||
}, %{ | ||
title: "Module", | ||
value: module, | ||
short: true | ||
}, %{ | ||
title: "Function", | ||
value: function, | ||
short: true | ||
}, %{ | ||
title: "File", | ||
value: file, | ||
short: true | ||
}, %{ | ||
title: "Line", | ||
value: line, | ||
short: true | ||
}] | ||
}]} | ||
|> encode | ||
event | ||
@doc false | ||
def start_link(max_demand, min_demand) do | ||
GenStage.start_link(__MODULE__, {max_demand, min_demand}, name: __MODULE__) | ||
end | ||
|
||
@doc false | ||
def init({max_demand, min_demand}) do | ||
{:producer_consumer, %{}, | ||
subscribe_to: [{Producer, max_demand: max_demand, min_demand: min_demand}]} | ||
end | ||
|
||
@doc false | ||
def handle_events(events, _from, state) do | ||
events = Enum.map(events, &format_event/1) | ||
{:noreply, events, state} | ||
end | ||
|
||
@doc """ | ||
Formats a log event for Slack. | ||
""" | ||
def format_event({level, message, application, module, function, file, line}) do | ||
{:ok, event} = %{attachments: [%{ | ||
fallback: "An #{level} level event has occurred: #{message}", | ||
pretext: message, | ||
fields: [%{ | ||
title: "Level", | ||
value: level, | ||
short: true | ||
}, %{ | ||
title: "Application", | ||
value: application, | ||
short: true | ||
}, %{ | ||
title: "Module", | ||
value: module, | ||
short: true | ||
}, %{ | ||
title: "Function", | ||
value: function, | ||
short: true | ||
}, %{ | ||
title: "File", | ||
value: file, | ||
short: true | ||
}, %{ | ||
title: "Line", | ||
value: line, | ||
short: true | ||
}] | ||
}]} | ||
|> encode | ||
event | ||
def format_event({url, event}) do | ||
{url, FormatHelper.format_event(event)} | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
alias Experimental.GenStage | ||
|
||
defmodule SlackLoggerBackend.Producer do | ||
|
||
@moduledoc """ | ||
Produces logger events to be consumed and send to Slack. | ||
""" | ||
use GenStage | ||
|
||
@doc false | ||
def start_link do | ||
GenStage.start_link(__MODULE__, :ok, name: __MODULE__) | ||
end | ||
|
||
@doc false | ||
def init(:ok) do | ||
{:producer, {:queue.new, 0}} | ||
end | ||
|
||
@doc false | ||
def handle_cast({:add, event}, {queue, demand}) when demand > 0 do | ||
{:noreply, [event], {queue, demand - 1}} | ||
end | ||
|
||
@doc false | ||
def handle_cast({:add, event}, {queue, demand}) do | ||
{:noreply, [], {:queue.in(event, queue), demand}} | ||
end | ||
|
||
@doc false | ||
def handle_demand(incoming_demand, {queue, demand}) when incoming_demand > 0 do | ||
dispatch_events(queue, incoming_demand + demand, []) | ||
end | ||
|
||
@doc """ | ||
Adds a logger event to the queue for sending to Slack. | ||
""" | ||
def add_event(event) do | ||
GenStage.cast(__MODULE__, {:add, event}) | ||
end | ||
|
||
defp dispatch_events(queue, demand, events) when demand > 0 do | ||
case :queue.out(queue) do | ||
{:empty, queue} -> | ||
{:noreply, events, {queue, demand}} | ||
{{:value, event}, queue} -> | ||
dispatch_events(queue, demand - 1, [event|events]) | ||
end | ||
end | ||
|
||
defp dispatch_events(queue, demand, events) do | ||
{:noreply, events, {queue, demand}} | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters