Skip to content

Commit e163ec6

Browse files
authored
feat: fork choice metrics (#1232)
1 parent 8c2bb5f commit e163ec6

File tree

6 files changed

+493
-359
lines changed

6 files changed

+493
-359
lines changed

lib/lambda_ethereum_consensus/fork_choice/fork_choice.ex

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,13 @@ defmodule LambdaEthereumConsensus.ForkChoice do
197197
end
198198
end
199199

200-
@spec apply_handler(any(), any(), any()) :: any()
201-
defp apply_handler(iter, state, handler) do
202-
iter
203-
|> Enum.reduce_while({:ok, state}, fn
204-
x, {:ok, st} -> {:cont, handler.(st, x)}
205-
_, {:error, _} = err -> {:halt, err}
200+
defp apply_handler(iter, name, state, handler) do
201+
Metrics.span_operation(name, nil, nil, fn ->
202+
iter
203+
|> Enum.reduce_while({:ok, state}, fn
204+
x, {:ok, st} -> {:cont, handler.(st, x)}
205+
_, {:error, _} = err -> {:halt, err}
206+
end)
206207
end)
207208
end
208209

@@ -212,11 +213,11 @@ defmodule LambdaEthereumConsensus.ForkChoice do
212213
# process block attestations
213214
{:ok, new_store} <-
214215
signed_block.message.body.attestations
215-
|> apply_handler(new_store, &Handlers.on_attestation(&1, &2, true)),
216+
|> apply_handler(:attestations, new_store, &Handlers.on_attestation(&1, &2, true)),
216217
# process block attester slashings
217218
{:ok, new_store} <-
218219
signed_block.message.body.attester_slashings
219-
|> apply_handler(new_store, &Handlers.on_attester_slashing/2) do
220+
|> apply_handler(:attester_slashings, new_store, &Handlers.on_attester_slashing/2) do
220221
Handlers.prune_checkpoint_states(new_store)
221222
{:ok, new_store}
222223
end

lib/lambda_ethereum_consensus/metrics.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ defmodule LambdaEthereumConsensus.Metrics do
120120
end
121121
end
122122

123+
def span_operation(handler, transition, operation, f) do
124+
:telemetry.span([:fork_choice, :latency], %{}, fn ->
125+
{f.(), %{handler: handler, transition: transition, operation: operation}}
126+
end)
127+
end
128+
123129
defp map_color(:transitioned), do: "blue"
124130
defp map_color(:pending), do: "green"
125131
defp map_color(:download_blobs), do: "yellow"

lib/lambda_ethereum_consensus/state_transition/operations.ex

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ defmodule LambdaEthereumConsensus.StateTransition.Operations do
33
This module contains functions for handling state transition
44
"""
55

6+
alias LambdaEthereumConsensus.Metrics
67
alias LambdaEthereumConsensus.StateTransition.Accessors
78
alias LambdaEthereumConsensus.StateTransition.Math
89
alias LambdaEthereumConsensus.StateTransition.Misc
@@ -919,19 +920,31 @@ defmodule LambdaEthereumConsensus.StateTransition.Operations do
919920
# Ensure that outstanding deposits are processed up to the maximum number of deposits
920921
with :ok <- verify_deposits(state, body) do
921922
{:ok, state}
922-
|> for_ops(body.proposer_slashings, &process_proposer_slashing/2)
923-
|> for_ops(body.attester_slashings, &process_attester_slashing/2)
924-
|> Utils.map_ok(&process_attestation_batch(&1, body.attestations))
925-
|> for_ops(body.deposits, &process_deposit/2)
926-
|> for_ops(body.voluntary_exits, &process_voluntary_exit/2)
927-
|> for_ops(body.bls_to_execution_changes, &process_bls_to_execution_change/2)
923+
|> for_ops(:proposer_slashing, body.proposer_slashings, &process_proposer_slashing/2)
924+
|> for_ops(:attester_slashing, body.attester_slashings, &process_attester_slashing/2)
925+
|> apply_op(:attestation_batch, &process_attestation_batch(&1, body.attestations))
926+
|> for_ops(:deposit, body.deposits, &process_deposit/2)
927+
|> for_ops(:voluntary_exit, body.voluntary_exits, &process_voluntary_exit/2)
928+
|> for_ops(
929+
:bls_to_execution_change,
930+
body.bls_to_execution_changes,
931+
&process_bls_to_execution_change/2
932+
)
928933
end
929934
end
930935

931-
defp for_ops(acc, operations, func) do
932-
Enum.reduce_while(operations, acc, fn
933-
operation, {:ok, state} -> {:cont, func.(state, operation)}
934-
_, {:error, reason} -> {:halt, {:error, reason}}
936+
defp apply_op(acc, op_name, func) do
937+
Metrics.span_operation(:on_block, :process_block_operations, op_name, fn ->
938+
Utils.map_ok(acc, func)
939+
end)
940+
end
941+
942+
defp for_ops(acc, op_name, operations, func) do
943+
Metrics.span_operation(:on_block, :process_block_operations, op_name, fn ->
944+
Enum.reduce_while(operations, acc, fn
945+
operation, {:ok, state} -> {:cont, func.(state, operation)}
946+
_, {:error, reason} -> {:halt, {:error, reason}}
947+
end)
935948
end)
936949
end
937950

lib/lambda_ethereum_consensus/state_transition/state_transition.ex

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ defmodule LambdaEthereumConsensus.StateTransition do
44
"""
55

66
require Logger
7+
alias LambdaEthereumConsensus.Metrics
78
alias LambdaEthereumConsensus.StateTransition.Accessors
89
alias LambdaEthereumConsensus.StateTransition.EpochProcessing
910
alias LambdaEthereumConsensus.StateTransition.Misc
@@ -108,17 +109,23 @@ defmodule LambdaEthereumConsensus.StateTransition do
108109

109110
state
110111
|> EpochProcessing.process_justification_and_finalization()
111-
|> map_ok(&EpochProcessing.process_inactivity_updates/1)
112-
|> map_ok(&EpochProcessing.process_rewards_and_penalties/1)
113-
|> map_ok(&EpochProcessing.process_registry_updates/1)
114-
|> map_ok(&EpochProcessing.process_slashings/1)
115-
|> map_ok(&EpochProcessing.process_eth1_data_reset/1)
116-
|> map_ok(&EpochProcessing.process_effective_balance_updates/1)
117-
|> map_ok(&EpochProcessing.process_slashings_reset/1)
118-
|> map_ok(&EpochProcessing.process_randao_mixes_reset/1)
119-
|> map_ok(&EpochProcessing.process_historical_summaries_update/1)
120-
|> map_ok(&EpochProcessing.process_participation_flag_updates/1)
121-
|> map_ok(&EpochProcessing.process_sync_committee_updates/1)
112+
|> epoch_op(:inactivity_updates, &EpochProcessing.process_inactivity_updates/1)
113+
|> epoch_op(:rewards_and_penalties, &EpochProcessing.process_rewards_and_penalties/1)
114+
|> epoch_op(:registry_updates, &EpochProcessing.process_registry_updates/1)
115+
|> epoch_op(:slashings, &EpochProcessing.process_slashings/1)
116+
|> epoch_op(:eth1_data_reset, &EpochProcessing.process_eth1_data_reset/1)
117+
|> epoch_op(:effective_balance_updates, &EpochProcessing.process_effective_balance_updates/1)
118+
|> epoch_op(:slashings_reset, &EpochProcessing.process_slashings_reset/1)
119+
|> epoch_op(:randao_mixes_reset, &EpochProcessing.process_randao_mixes_reset/1)
120+
|> epoch_op(
121+
:historical_summaries_update,
122+
&EpochProcessing.process_historical_summaries_update/1
123+
)
124+
|> epoch_op(
125+
:participation_flag_updates,
126+
&EpochProcessing.process_participation_flag_updates/1
127+
)
128+
|> epoch_op(:sync_committee_updates, &EpochProcessing.process_sync_committee_updates/1)
122129
|> tap(fn _ ->
123130
end_time = System.monotonic_time(:millisecond)
124131
Logger.debug("[Epoch processing] took #{end_time - start_time} ms")
@@ -136,16 +143,26 @@ defmodule LambdaEthereumConsensus.StateTransition do
136143
start_time = System.monotonic_time(:millisecond)
137144

138145
{:ok, state}
139-
|> map_ok(&Operations.process_block_header(&1, block))
140-
|> map_ok(&Operations.process_withdrawals(&1, block.body.execution_payload))
141-
|> map_ok(&Operations.process_execution_payload(&1, block.body))
142-
|> map_ok(&Operations.process_randao(&1, block.body))
143-
|> map_ok(&Operations.process_eth1_data(&1, block.body))
146+
|> block_op(:block_header, &Operations.process_block_header(&1, block))
147+
|> block_op(:withdrawals, &Operations.process_withdrawals(&1, block.body.execution_payload))
148+
|> block_op(:execution_payload, &Operations.process_execution_payload(&1, block.body))
149+
|> block_op(:randao, &Operations.process_randao(&1, block.body))
150+
|> block_op(:eth1_data, &Operations.process_eth1_data(&1, block.body))
144151
|> map_ok(&Operations.process_operations(&1, block.body))
145-
|> map_ok(&Operations.process_sync_aggregate(&1, block.body.sync_aggregate))
152+
|> block_op(
153+
:sync_aggregate,
154+
&Operations.process_sync_aggregate(&1, block.body.sync_aggregate)
155+
)
146156
|> tap(fn _ ->
147157
end_time = System.monotonic_time(:millisecond)
148158
Logger.debug("[Block processing] took #{end_time - start_time} ms")
149159
end)
150160
end
161+
162+
def block_op(state, operation, f), do: apply_op(state, :process_block, operation, f)
163+
def epoch_op(state, operation, f), do: apply_op(state, :epoch, operation, f)
164+
165+
def apply_op(state, transition, operation, f) do
166+
Metrics.span_operation(:on_block, transition, operation, fn -> map_ok(state, f) end)
167+
end
151168
end

lib/lambda_ethereum_consensus/telemetry.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ defmodule LambdaEthereumConsensus.Telemetry do
140140
tags: [:module, :action]
141141
),
142142
counter("db.latency.stop.count", unit: {:native, :millisecond}, tags: [:module, :action]),
143+
last_value("fork_choice.latency.stop.duration",
144+
unit: {:native, :millisecond},
145+
tags: [:handler, :transition, :operation]
146+
),
143147

144148
# ForkChoice Metrics
145149
last_value("fork_choice.recompute_head.stop.duration",

0 commit comments

Comments
 (0)