This is an Elixir Logger backend for forwarding log messages to the ramoops logger on Linux and Nerves systems. Messages sent to this log are written to a special area of DRAM that can be recovered after reboots or very short power outages.
Here's a demo video:
RamoopsLogger uses the Linux pstore
device driver, so it only works on
Linux-based platforms. Most official Nerves Projects systems start the pstore
driver automatically and you can skip the Linux configuration.
The most important part of using the RamoopsLogger is ensuring that the pstore
device driver is enabled and configured in your Linux kernel. The device driver
writes logs to a fixed location in DRAM that is platform-specific. If you are
lucky, someone will have determined a good place to store the logs. The official
Nerves Project systems all have a small amount of memory allocated for use by
the pstore
driver. If you are not using Nerves, it's possible that one of the
device tree files (for ARM platforms) may be helpful.
If you're not using an official Nerves system, here's an example device tree fragment that would need to be updated for your device, but may be helpful as a start.
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
ramoops@88d00000{
compatible = "ramoops";
reg = <0x88d00000 0x100000>;
ecc-size = <16>;
record-size = <0x00020000>;
console-size = <0x00020000>;
ftrace-size = <0>;
pmsg-size = <0x00020000>;
};
};
One way of testing whether the pstore
driver is available is to check whether
the /dev/pmsg0
file exists.
Once you're satisfied with the Linux, add ramoops_logger
to your project's
mix.exs
dependencies list.
def deps do
[
{:ramoops_logger, "~> 0.3.0"}
]
end
Next, update your config.exs
to tell the Elixir Logger to send log messages to
the RamoopsLogger
:
use Mix.Config
# Add the RamoopsLogger backend. If you already have a logger configuration, to add
# RamoopsLogger the only change needed is to add RamoopsLogger to the :backends list.
config :logger, backends: [RamoopsLogger, :console]
To read the last ramoops log to the console run:
iex> RamoopsLogger.dump()
To read the last ramoops log and it to a variable run:
iex> {:ok, contents} = RamoopsLogger.read()
If you want to have your system check if there is an oops log available, and you
are using Nerves, you can add this to your rootfs_overlay/etc/iex.exs
file in
your firmware project:
if RamoopsLogger.available_log?() do
IO.puts("Oops! There's something in the oops log. Check with RamoopsLogger.dump()")
end
Copyright (C) 2020-21 SmartRent
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.