Skip to content

Commit

Permalink
Add feature to send logs to configurator
Browse files Browse the repository at this point in the history
  • Loading branch information
Connor Rigby authored and ConnorRigby committed Jul 11, 2019
1 parent 0d0329d commit 9a4f956
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 1 deletion.
76 changes: 76 additions & 0 deletions farmbot_os/lib/farmbot_os/configurator/logger_socket.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
defmodule FarmbotOS.Configurator.LoggerSocket do
alias FarmbotOS.Configurator.LoggerSocket.LoggerBackend
require Logger

@behaviour :cowboy_websocket
def init(req, state) do
{:cowboy_websocket, req, state}
end

def websocket_init(_state) do
send(self(), :after_connect)
{:ok, %{}}
end

def websocket_handle({:text, message}, state) do
case Jason.decode(message) do
{:ok, json} ->
websocket_handle({:json, json}, state)

_ ->
_ = Logger.debug("discarding info: #{message}")
{:ok, state}
end
end

def websocket_info(:after_connect, state) do
Logger.add_backend(LoggerBackend)
LoggerBackend.register()
{:ok, state}
end

def websocket_info({level, _pid, {Logger, msg, timestamp, metadata}}, state) do
{{year, month, day}, {hour, minute, second, _millisecond}} = timestamp

datetime = %DateTime{
year: year,
month: month,
day: day,
hour: hour,
minute: minute,
second: second,
time_zone: "Etc/UTC",
std_offset: 0,
zone_abbr: "UTC",
utc_offset: 0
}

metadata =
Keyword.take(metadata, [
:module,
:function,
:file,
:line,
:application
])

log =
Jason.encode!(%{
level: level,
message: IO.iodata_to_binary(msg),
datetime: datetime,
metadata: Map.new(metadata)
})

{:reply, {:text, log}, state}
end

def websocket_info(info, state) do
Logger.info("Dropping #{inspect(info)}")
{:ok, state}
end

def terminate(_reason, _req, _state) do
:ok
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
defmodule FarmbotOS.Configurator.LoggerSocket.LoggerBackend do
@behaviour :gen_event

def register() do
{:ok, _} = Registry.register(__MODULE__, :dispatch, self())
:ok
end

@impl :gen_event
def init(_) do
case Registry.start_link(keys: :duplicate, name: __MODULE__) do
{:ok, pid} -> {:ok, pid}
{:error, {:already_started, pid}} -> {:ok, pid}
end

{:ok, %{}}
end

@impl :gen_event
def terminate(_reason, _state) do
:ok
end

@impl :gen_event
def handle_event({_level, _pid, {Logger, _msg, _timestamp, _meta}} = log, state) do
Registry.dispatch(__MODULE__, :dispatch, fn entries ->
for {pid, _} <- entries do
send(pid, log)
end
end)

{:ok, state}
end

def handle_event(_event, state) do
{:ok, state}
end

@impl :gen_event
def handle_info(_, state) do
{:ok, state}
end

@impl :gen_event
def handle_call(_, state) do
{:ok, :ok, state}
end
end
4 changes: 4 additions & 0 deletions farmbot_os/lib/farmbot_os/configurator/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ defmodule FarmbotOS.Configurator.Router do
render_page(conn, "scheduler_debugger")
end

get "/logger" do
render_page(conn, "logger")
end

get "/" do
case load_last_reset_reason() do
reason when is_binary(reason) ->
Expand Down
3 changes: 2 additions & 1 deletion farmbot_os/lib/farmbot_os/configurator/supervisor.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule FarmbotOS.Configurator.Supervisor do
use Supervisor
alias FarmbotOS.Configurator.{Router, SchedulerSocket}
alias FarmbotOS.Configurator.{Router, LoggerSocket, SchedulerSocket}

def start_link(args) do
Supervisor.start_link(__MODULE__, args, name: __MODULE__)
Expand Down Expand Up @@ -37,6 +37,7 @@ defmodule FarmbotOS.Configurator.Supervisor do
[
{:_,
[
{"/logger_socket", LoggerSocket, []},
{"/scheduler_socket", SchedulerSocket, []},
{:_, Plug.Cowboy.Handler, {Router, []}}
]}
Expand Down
29 changes: 29 additions & 0 deletions farmbot_os/priv/static/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
let logger_table;
let thead;

window.onload = function() {
logger_table = document.getElementById("logger_table");
}

const socket = new WebSocket("ws://" + location.host + "/logger_socket");
socket.onopen = function () {
console.log("connected");
}

let add_value_to_row = function(row, value) {
var cell = row.insertCell();
var text = document.createTextNode(value);
cell.appendChild(text);
}

socket.onmessage = function (event) {
let payload = JSON.parse(event.data);
console.log(payload);
let row = logger_table.insertRow();
add_value_to_row(row, payload.level);
add_value_to_row(row, payload.message);
add_value_to_row(row, new Date(payload.datetime));
add_value_to_row(row, payload.metadata.file + ":" + payload.metadata.line);
add_value_to_row(row, payload.metadata.module);
add_value_to_row(row, payload.metadata.function);
}
23 changes: 23 additions & 0 deletions farmbot_os/priv/static/templates/logger.html.eex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Debug Logger</title>
<script src="logger.js"></script>
</head>
<body>
<table border="1" style="width:100%" id="logger_table">
<col width="1%">
<col width="75%">
<col width="17%">
<tr>
<th>Level</th>
<th>Message</th>
<th>DateTime</th>
<th>Src</th>
<th>Module</th>
<th>Function</th>
</tr>
<table/>
</body>
</html>

0 comments on commit 9a4f956

Please sign in to comment.