reimplement logger

This commit is contained in:
Connor Rigby 2017-10-01 19:54:21 -07:00
parent 3cebc51b5e
commit 2c27b8c8db
7 changed files with 130 additions and 13 deletions

View file

@ -11,7 +11,7 @@ config :ssl, protocol_version: :"tlsv1.2"
# I force colors because they are important.
config :logger, :console,
colors: [enabled: true, info: :cyan],
metadata: [:module],
metadata: [],
format: "$time $metadata[$level] $levelpad$message\n"
# Iex needs colors too.

View file

@ -9,6 +9,7 @@ defmodule Farmbot.BotState.Supervisor do
children = [
supervisor(Farmbot.Firmware.Supervisor, [[name: Farmbot.Firmware.Supervisor]]),
worker(Farmbot.BotState, [[name: Farmbot.BotState]]),
worker(Farmbot.Logger, [[name: Farmbot.Logger]]),
supervisor(Farmbot.BotState.Transport.Supervisor, [])
]
supervise(children, strategy: :one_for_one)

View file

@ -18,11 +18,17 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
])
end
@doc "Push a bot state message."
def push_bot_state(client, state) do
GenMQTT.cast(client, {:bot_state, state})
end
def init(device) do
@doc "Push a log message."
def push_bot_log(client, log) do
GenMQTT.cast(client, {:bot_log, log})
end
def init({device, _server}) do
{:ok, %{connected: false, device: device}}
end
@ -53,9 +59,18 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
end
def handle_cast({:bot_state, bs}, state) do
Logger.info "Got bot state update"
json = Poison.encode!(bs)
GenMQTT.publish(self(), status_topic(state.server), json, 0, false)
GenMQTT.publish(self(), status_topic(state.device), json, 0, false)
{:noreply, state}
end
def handle_cast(_, %{connected: false} = state) do
{:noreply, state}
end
def handle_cast({:bot_log, log}, state) do
json = Poison.encode!(log)
GenMQTT.publish(self(), log_topic(state.device), json, 0, false)
{:noreply, state}
end
@ -72,15 +87,29 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
def init([]) do
token = Farmbot.System.ConfigStorage.get_config_value(:string, "authorization", "token")
{:ok, %{bot: device, mqtt: mqtt_server}} = Farmbot.Jwt.decode(token)
IO.puts "Got mqtt server: #{mqtt_server}"
{:ok, client} = Client.start_link(device, token, mqtt_server)
{:consumer, {%{client: client}, nil}, subscribe_to: [Farmbot.BotState]}
{:consumer, {%{client: client}, nil}, subscribe_to: [Farmbot.BotState, Farmbot.Logger]}
end
def handle_events(events, _, {%{client: client} = internal_state, old_bot_state}) do
new_bot_state = Enum.last(events)
def handle_events(events, {pid, _}, state) do
case Process.info(pid)[:registered_name] do
Farmbot.Logger -> handle_log_events(events, state)
Farmbot.BotState -> handle_bot_state_events(events, state)
end
end
def handle_log_events(logs, {%{client: client} = internal_state, old_bot_state}) do
for log <- logs do
Client.push_bot_log(client, log)
end
{:noreply, [], {internal_state, old_bot_state}}
end
def handle_bot_state_events(events, {%{client: client} = internal_state, old_bot_state}) do
new_bot_state = List.last(events)
if new_bot_state != old_bot_state do
Client.push_bot_state client, new_bot_state
Logger.info "State: #{inspect new_bot_state}"
end
{:noreply, [], {internal_state, new_bot_state}}
end

View file

@ -284,7 +284,6 @@ defmodule Farmbot.HTTP do
opts = opts |> Keyword.put(:timeout, :infinity)
#TODO Fix this.
url = "https:" <> Farmbot.Jwt.decode!(tkn).iss <> url
IO.inspect(url)
do_normal_request({method, url, body, headers, opts, from}, nil, state)
end

View file

@ -1,9 +1,15 @@
defmodule Farmbot.Log.Meta do
defstruct [:x, :y, :z]
end
defmodule Farmbot.Log do
@moduledoc "Farmbot Log Object."
alias Farmbot.Log.Meta
defstruct [
:meta,
:message,
:created_at,
:channels
meta: %Meta{x: -1, y: -1, z: -1},
message: nil,
created_at: nil,
channels: []
]
end

37
lib/farmbot/logger.ex Normal file
View file

@ -0,0 +1,37 @@
defmodule Farmbot.Logger do
@moduledoc "Logger."
use GenStage
alias Farmbot.Log
@doc "Start Logging Services."
def start_link(opts \\ []) do
GenStage.start_link(__MODULE__, [], opts)
end
def init([]) do
Logger.add_backend(Logger.Backends.Farmbot, [])
{:producer_consumer, %{meta: %Log.Meta{x: -1, y: -1, z: -1}}, subscribe_to: [Farmbot.Firmware]}
end
def handle_demand(_, state) do
{:noreply, [], state}
end
def handle_events(gcodes, _from, state) do
{x, y, z} = Enum.find_value(gcodes, fn(code) ->
case code do
{:report_current_position, x, y, z} -> {x, y, z}
_ -> false
end
end)
{:noreply, [], %{state | meta: %{state.meta | x: x, y: y, z: z}}}
end
def handle_info({:log, log}, state) do
{:noreply, [%{log | meta: state.meta}], state}
end
def terminate(_, _state) do
Logger.remove_backend(Logger.Backends.Farmbot)
end
end

View file

@ -0,0 +1,45 @@
defmodule Logger.Backends.Farmbot do
@moduledoc "Farmbot Loggerr Backend."
alias Farmbot.Log
def init(_opts) do
{:ok, %{}}
end
def handle_event({_level, gl, {Logger, _, _, _}}, state) when node(gl) != node() do
{:ok, state}
end
def handle_event({level, _gl, {Logger, message, {{year, month, day}, {hour, minute, second, _millisecond}}, metadata}}, state) do
mod_split = (metadata[:module] || Logger) |> Module.split()
case mod_split do
["Farmbot" | _] ->
t = %DateTime{year: year,
month: month,
day: day,
hour: hour,
minute: minute,
calendar: Calendar.ISO,
microsecond: {0, 0},
second: second,
std_offset: 0,
time_zone: "Etc/UTC",
utc_offset: 0,
zone_abbr: "UTC"} |> DateTime.to_iso8601
l = %Log{message: message, channels: [level], created_at: t}
GenStage.async_info(Farmbot.Logger, {:log, l})
_ -> :ok
end
{:ok, state}
end
def handle_event(:flush, state) do
{:ok, state}
end
def handle_info(_, state) do
{:ok, state}
end
end