LoggerBackendSqlite
What is it?
LoggerBackendSqlite will allow you to save all of your logs to an sqlite3 database.
Why is it?
This is very helpful for Nerves devices which don’t always have network access, or console access.
Usage is it?
Add logger backend ecto to your deps:
def deps do
[
{:logger_backend_sqlite, "~> 2.0"},
]
end
Configure :logger:
use Mix.Config
config :logger, [
utc_log: true,
handle_otp_reports: true,
handle_sasl_reports: true,
backends: [:console, LoggerBackendSqlite]
]
config :logger, LoggerBackendSqlite,
database: 'debug_logs.sqlite3',
max_logs: 9000, # defaults to 1000You can also add the backend at runtime.
iex()> {:ok, _} = Logger.add_backend(LoggerBackendSqlite)
iex()> :ok = Logger.configure_backend(LoggerBackendSqlite, database: ":memory:", max_logs: 20)Seeing logs:
iex(1)> require Logger
Logger
iex(2)> Logger.debug "hey!!"
:ok
iex(3)>
01:33:16.341 [debug] hey!!
iex(4)> LoggerBackendSqlite.all_logs
[
%LoggerBackendSqlite.Log{
application: nil,
file: "iex",
function: nil,
group_leader_node: "nonode@nohost",
id: 1,
inserted_at: "2018-09-12 01:33:16.341631",
level: "debug",
line: 8,
logged_at_dt: "2018-09-12 01:33:16Z",
logged_at_ndt: "2018-09-12 01:33:16",
message: "hey!!",
module: nil,
registered_name: nil,
updated_at: "2018-09-12 01:33:16.341661"
}
]Nerves is it?
Using this on Nerves is pretty straightforward, but there is a gotcha. Nerves devices use a read only filesystem, so you need to ensure you store the database on a writable filesystem. You have two options.
/tmp
/tmp is read write, but will be cleared every boot and has a pretty
small size constraint. This can be useful if you only want a few logs from
a specific time.
/root
/root is the default location for your application data. There is another
gotcha on this one, that on first boot, this partition will not be ready yet.
A simple work can be found below:
in your config.exs
use Mix.Config
config :logger, LoggerBackendSqlite, [
database: "/tmp/logs.sqlite"
]then in your application code somewhere:
defmodule MyApp.FileSystemCheckup do
@database "/root/logs.sqlite"
@check_file "/root/check"
require Logger
def checkup do
case File.write(@check_file, "any ole data") do
:ok -> Logger.configure_backend(LoggerBackendSqlite, [database: @database])
{:error, _} ->
Logger.warn "Application data partition not ready yet"
Proess.sleep(2000)
checkup()
end
end
endWhy 2.0 is it?
This is a hard fork of logger_backend_ecto. It is 1.0, and I didn’t want any confusion that these are not the same thing, even tho they share the same public API.