Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add custom console logger. #660

Merged
merged 7 commits into from
Jan 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .credo.exs
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
{Credo.Check.Warning.IExPry, []},
{Credo.Check.Warning.IoInspect, []},
{Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []},
# {Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []}, seems to not support :default_formatter
{Credo.Check.Warning.OperationOnSameValues, []},
{Credo.Check.Warning.OperationWithConstantResult, []},
{Credo.Check.Warning.RaiseInsideRescue, []},
2 changes: 2 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ import Config
# Configure logging
config :logger, level: :info, truncate: :infinity

config :logger, :default_formatter, format: {ConsoleLogger, :format}, metadata: [:slot, :root]

# # Uncomment to log to a file
# # TODO: we might want to enable this with a CLI flag
# config :logger, :default_handler,
8 changes: 0 additions & 8 deletions config/runtime.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Config
require Logger

{args, _remaining_args, _errors} =
OptionParser.parse(System.argv(),
@@ -62,10 +61,3 @@ block_time_ms =

config :lambda_ethereum_consensus, LambdaEthereumConsensus.Telemetry,
block_processing_buckets: [0.5, 1.0, 1.5, 2, 4, 6, 8] |> Enum.map(&(&1 * block_time_ms))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point the logger is not initialized, moved to Application start.

if is_nil(jwt_secret) do
Logger.warning(
"[EngineAPI] A JWT secret is needed for communication with the execution engine. " <>
"Please specify the file to load it from with the --execution-jwt flag."
)
end
13 changes: 13 additions & 0 deletions lib/lambda_ethereum_consensus/application.ex
Original file line number Diff line number Diff line change
@@ -13,6 +13,19 @@ defmodule LambdaEthereumConsensus.Application do
:checkpoint_sync
]

jwt_secret =
Application.fetch_env!(
:lambda_ethereum_consensus,
LambdaEthereumConsensus.Execution.EngineApi
)[:jwt_secret]

if is_nil(jwt_secret) do
Logger.warning(
"[EngineAPI] A JWT secret is needed for communication with the execution engine. " <>
"Please specify the file to load it from with the --execution-jwt flag."
)
end

children = [
LambdaEthereumConsensus.Telemetry,
LambdaEthereumConsensus.Store.Db,
9 changes: 5 additions & 4 deletions lib/lambda_ethereum_consensus/beacon/beacon_node.ex
Original file line number Diff line number Diff line change
@@ -25,26 +25,27 @@ defmodule LambdaEthereumConsensus.Beacon.BeaconNode do

:not_found ->
Logger.error(
"[Sync] No initial state or block found. Please specify the URL to fetch them from via the --checkpoint-sync flag."
"[Sync] No initial state or block found. Please specify the URL to fetch them from via the --checkpoint-sync flag"
)

System.stop(1)
end
end

def init([checkpoint_url]) do
Logger.info("[Checkpoint sync] Initiating checkpoint sync.")
Logger.info("[Checkpoint sync] Initiating checkpoint sync")

case CheckpointSync.get_finalized_block_and_state(checkpoint_url) do
{:ok, {anchor_state, anchor_block}} ->
Logger.info(
"[Checkpoint sync] Received beacon state and block at slot #{anchor_state.slot}."
"[Checkpoint sync] Received beacon state and block",
slot: anchor_state.slot
)

init_children(anchor_state, anchor_block)

_ ->
Logger.error("[Checkpoint sync] Failed to fetch the latest finalized state and block.")
Logger.error("[Checkpoint sync] Failed to fetch the latest finalized state and block")

System.stop(1)
end
4 changes: 2 additions & 2 deletions lib/lambda_ethereum_consensus/beacon/checkpoint_sync.ex
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ defmodule LambdaEthereumConsensus.Beacon.CheckpointSync do
def get_state(url) do
with {:error, err} <-
get_from_url(url, "/eth/v2/debug/beacon/states/finalized", Types.BeaconState) do
Logger.error("There has been an error retrieving the last finalized state.")
Logger.error("There has been an error retrieving the last finalized state")
{:error, err}
end
end
@@ -49,7 +49,7 @@ defmodule LambdaEthereumConsensus.Beacon.CheckpointSync do
def get_block(url, id \\ "finalized") do
with {:error, err} <-
get_from_url(url, "/eth/v2/beacon/blocks/#{id}", Types.SignedBeaconBlock) do
Logger.error("There has been an error retrieving the last finalized block.")
Logger.error("There has been an error retrieving the last finalized block")
{:error, err}
end
end
12 changes: 6 additions & 6 deletions lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ defmodule LambdaEthereumConsensus.ForkChoice do
def init({anchor_state = %BeaconState{}, signed_anchor_block = %SignedBeaconBlock{}, time}) do
case Store.get_forkchoice_store(anchor_state, signed_anchor_block, true) do
{:ok, %Store{} = store} ->
Logger.info("[Fork choice] Initialized store.")
Logger.info("[Fork choice] Initialized store")

slot = signed_anchor_block.message.slot
:telemetry.execute([:sync, :store], %{slot: slot})
@@ -113,21 +113,21 @@ defmodule LambdaEthereumConsensus.ForkChoice do
case result do
{:ok, new_store} ->
:telemetry.execute([:sync, :on_block], %{slot: slot})
Logger.info("[Fork choice] Block #{slot} added to the store.")
Logger.info("[Fork choice] New block added", slot: slot, root: block_root)

Task.async(__MODULE__, :recompute_head, [new_store])
{:reply, :ok, new_store}

{:error, reason} ->
Logger.error("[Fork choice] Failed to add block #{slot} to the store: #{reason}")
Logger.error("[Fork choice] Failed to add block: #{reason}", slot: slot)
{:reply, :error, store}
end
end

@impl GenServer
def handle_cast({:on_attestation, %Attestation{} = attestation}, %Types.Store{} = state) do
id = attestation.signature |> Base.encode16() |> String.slice(0, 8)
Logger.debug("[Fork choice] Adding attestation #{id} to the store.")
Logger.debug("[Fork choice] Adding attestation #{id} to the store")

state =
case Handlers.on_attestation(state, attestation, false) do
@@ -140,15 +140,15 @@ defmodule LambdaEthereumConsensus.ForkChoice do

@impl GenServer
def handle_cast({:attester_slashing, attester_slashing}, state) do
Logger.info("[Fork choice] Adding attester slashing to the store.")
Logger.info("[Fork choice] Adding attester slashing to the store")

state =
case Handlers.on_attester_slashing(state, attester_slashing) do
{:ok, new_state} ->
new_state

_ ->
Logger.error("[Fork choice] Failed to add attester slashing to the store.")
Logger.error("[Fork choice] Failed to add attester slashing to the store")
state
end

53 changes: 53 additions & 0 deletions lib/lambda_ethereum_consensus/logger/console_logger.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
defmodule ConsoleLogger do
@moduledoc """
Custom logger formatter for console output.
"""

@pattern Logger.Formatter.compile(" $time $message ")

def format(level, message, timestamp, metadata) do
formatted_metadata = format_metadata(metadata)

[format_level(level)] ++
[Logger.Formatter.format(@pattern, level, message, timestamp, [])] ++
[formatted_metadata] ++ ["\n"]
rescue
err ->
inspect(err)
MegaRedHand marked this conversation as resolved.
Show resolved Hide resolved
end

defp level_color(:info), do: :green
defp level_color(:warning), do: :yellow
defp level_color(:error), do: :red
defp level_color(_), do: :default

defp format_level(level) do
upcased = level |> Atom.to_string() |> String.upcase()
IO.ANSI.format([level_color(level), upcased])
end

def format_metadata(metadata) do
Enum.map_join(
metadata,
" ",
fn {key, value} ->
IO.ANSI.format([
:bright,
Atom.to_string(key),
:reset,
"=" <> format_metadata_value(key, value)
])
end
)
end

def format_metadata_value(:root, root) do
encoded = root |> Base.encode16(case: :lower)
# get the first 3 and last 4 characters
"0x#{String.slice(encoded, 0, 3)}..#{String.slice(encoded, -4, 4)}"
end

def format_metadata_value(:slot, slot) do
Integer.to_string(slot)
end
end
6 changes: 3 additions & 3 deletions lib/lambda_ethereum_consensus/p2p/block_downloader.ex
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ defmodule LambdaEthereumConsensus.P2P.BlockDownloader do
@spec request_blocks_by_slot(Types.slot(), integer(), integer()) ::
{:ok, [Types.SignedBeaconBlock.t()]} | {:error, any()}
def request_blocks_by_slot(slot, count, retries \\ @default_retries) do
Logger.debug("requesting block for slot #{slot}")
Logger.debug("Requesting block", slot: slot)

# TODO: handle no-peers asynchronously?
peer_id = get_some_peer()
@@ -58,7 +58,7 @@ defmodule LambdaEthereumConsensus.P2P.BlockDownloader do
tags = %{type: "by_slot", reason: parse_reason(reason)}
P2P.Peerbook.penalize_peer(peer_id)
:telemetry.execute([:network, :request], %{blocks: 0}, Map.put(tags, :result, "retry"))
Logger.debug("Retrying request for block with slot #{slot}")
Logger.debug("Retrying request for block", slot: slot)
request_blocks_by_slot(slot, count, retries - 1)

{:error, reason} when retries == 0 ->
@@ -80,7 +80,7 @@ defmodule LambdaEthereumConsensus.P2P.BlockDownloader do
@spec request_blocks_by_root([Types.root()], integer()) ::
{:ok, [Types.SignedBeaconBlock.t()]} | {:error, binary()}
def request_blocks_by_root(roots, retries \\ @default_retries) do
Logger.debug("requesting block for roots #{Enum.map_join(roots, ", ", &Base.encode16/1)}")
Logger.debug("Requesting block for roots #{Enum.map_join(roots, ", ", &Base.encode16/1)}")

peer_id = get_some_peer()

6 changes: 4 additions & 2 deletions lib/lambda_ethereum_consensus/p2p/gossip/handler.ex
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ defmodule LambdaEthereumConsensus.P2P.Gossip.Handler do
current_slot = BeaconChain.get_current_slot()

if block.slot > current_slot - ChainSpec.get("SLOTS_PER_EPOCH") do
Logger.info("[Gossip] Block decoded for slot #{block.slot}")
Logger.info("[Gossip] Block decoded", slot: block.slot)

PendingBlocks.add_block(signed_block)
end
@@ -33,7 +33,9 @@ defmodule LambdaEthereumConsensus.P2P.Gossip.Handler do
# Store.on_attestation(aggregate)

Logger.debug(
"[Gossip] Aggregate decoded for slot #{slot}. Root: #{root}. Total attestations: #{votes}"
"[Gossip] Aggregate decoded. Total attestations: #{votes}",
slot: slot,
root: root
)
end
end
5 changes: 4 additions & 1 deletion lib/lambda_ethereum_consensus/store/db.ex
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ defmodule LambdaEthereumConsensus.Store.Db do
@moduledoc """
Module that handles the key-value store.
"""
require Logger
# TODO: replace GenServer with :ets
use GenServer

@@ -40,7 +41,9 @@ defmodule LambdaEthereumConsensus.Store.Db do

@impl true
def init(db_location) do
{:ok, ref} = Exleveldb.open(db_location, create_if_missing: true)
db_full_path = Path.join(File.cwd!(), db_location)
{:ok, ref} = Exleveldb.open(db_full_path, create_if_missing: true)
Logger.info("Opened database: #{db_full_path}")
{:ok, %{ref: ref}}
end

2 changes: 1 addition & 1 deletion lib/mix/tasks/generate_spec_tests.ex
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ defmodule Mix.Tasks.GenerateSpecTests do
cases = SpecTestUtils.cases_for(fork: fork, config: config, runner: runner)

if cases != [] do
Logger.info("Generating tests for #{config}-#{fork}-#{runner}.")
Logger.info("Generating tests for #{config}-#{fork}-#{runner}")

# Create the parent dir if not present.
dirname = Path.join(["test", "generated", config, fork])
Loading