From 7afbb254a16962b1299035cb8200b1b6f3d46c4d Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Sun, 15 Jun 2025 10:50:16 +0200 Subject: [PATCH] EVM Node: Add OpenTelemetry attributes for blocks and transactions * What This patch introduces OpenTelemetry attributes to enhance tracing for block processing and transaction-related RPC calls. These attributes provide crucial context directly within the telemetry traces. * Why By adding specific attributes such as block numbers, transaction hashes, transaction counts, and execution gas, we make the telemetry data more actionable and informative. This greatly assists in debugging, performance analysis, and overall observability of the Etherlink node's operations. * How New functions in `Telemetry.Attributes` are defined to create `key_value` pairs for block numbers, transaction counts, execution gas, and transaction hashes. Calls to `Octez_telemetry.Trace.add_attrs` have been strategically placed in `evm_context.ml` (for block application), `evm_store.ml` (for transaction insertion), and `services.ml` (for various transaction-related RPCs like `eth_getTransactionReceipt`, `eth_getTransactionByHash`, and transaction submission) to attach these new attributes to the current trace spans. --- etherlink/bin_node/lib_dev/evm_context.ml | 9 +++++++++ etherlink/bin_node/lib_dev/evm_store.ml | 2 ++ etherlink/bin_node/lib_dev/services.ml | 16 ++++++++++++++++ etherlink/bin_node/lib_dev/telemetry.ml | 18 ++++++++++++++++++ etherlink/bin_node/lib_dev/telemetry.mli | 22 ++++++++++++++++++++++ etherlink/bin_node/lib_dev/tx_queue.ml | 11 ++++++++++- src/lib_telemetry/trace.ml | 12 ++++++++++++ src/lib_telemetry/trace.mli | 8 ++++++++ 8 files changed, 97 insertions(+), 1 deletion(-) diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 05e5753c0422..e0ed7627f3a8 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -879,6 +879,15 @@ module State = struct let* context, split_info = commit_next_head ctxt conn timestamp evm_state in + + Octez_telemetry.Trace.add_attrs (fun () -> + Telemetry.Attributes. + [ + Block.number ctxt.session.next_blueprint_number; + Block.transaction_count (List.length receipts); + Block.execution_gas execution_gas; + ]) ; + return ( evm_state, context, diff --git a/etherlink/bin_node/lib_dev/evm_store.ml b/etherlink/bin_node/lib_dev/evm_store.ml index 69321b55ae61..02a0bfb0de60 100644 --- a/etherlink/bin_node/lib_dev/evm_store.ml +++ b/etherlink/bin_node/lib_dev/evm_store.ml @@ -697,6 +697,8 @@ DO UPDATE SET value = excluded.value ->. unit) ~name:__FUNCTION__ ~table + ~attrs:(fun (_, _, _, hash, _, _, _, _) -> + [Telemetry.Attributes.Transaction.hash hash]) @@ {eos|INSERT INTO transactions (block_hash, block_number, index_, hash, from_, to_, receipt_fields, object_fields) VALUES (?, ?, ?, ?, ?, ?, ?, ?)|eos} let select_receipt = diff --git a/etherlink/bin_node/lib_dev/services.ml b/etherlink/bin_node/lib_dev/services.ml index ca58e552a4f6..311bd6fe8bb5 100644 --- a/etherlink/bin_node/lib_dev/services.ml +++ b/etherlink/bin_node/lib_dev/services.ml @@ -709,6 +709,9 @@ let dispatch_request (type f) ~websocket build_with_input ~f module_ parameters | Get_transaction_receipt.Method -> let f tx_hash = + Octez_telemetry.Trace.add_attrs (fun () -> + Telemetry.Attributes.[Transaction.hash tx_hash]) ; + let* receipt = Backend_rpc.Etherlink_block_storage.transaction_receipt tx_hash in @@ -768,6 +771,10 @@ let dispatch_request (type f) ~websocket build_with_input ~f module_ parameters | Get_transaction_by_hash.Method -> let f tx_hash = + Octez_telemetry.Trace.( + add_attrs (fun () -> + Telemetry.Attributes.[Transaction.hash tx_hash])) ; + let* (module Tx_container) = match tx_container with | Evm_tx_container m -> return m @@ -861,6 +868,11 @@ let dispatch_request (type f) ~websocket in rpc_error (Rpc_errors.transaction_rejected err None) | Ok (next_nonce, transaction_object) -> ( + Octez_telemetry.Trace.( + add_attrs (fun () -> + Telemetry.Attributes. + [Transaction.hash transaction_object.hash])) ; + let* (module Tx_container) = match tx_container with | Evm_tx_container m -> return m @@ -1125,6 +1137,10 @@ let dispatch_private_request (type f) ~websocket let f ( (transaction_object : Ethereum_types.legacy_transaction_object), raw_txn ) = + Octez_telemetry.Trace.( + add_attrs (fun () -> + Telemetry.Attributes.[Transaction.hash transaction_object.hash])) ; + let* is_valid = let get_nonce () = let* next_nonce = diff --git a/etherlink/bin_node/lib_dev/telemetry.ml b/etherlink/bin_node/lib_dev/telemetry.ml index c16d58624823..40c00d5d7afd 100644 --- a/etherlink/bin_node/lib_dev/telemetry.ml +++ b/etherlink/bin_node/lib_dev/telemetry.ml @@ -57,3 +57,21 @@ module Jsonrpc = struct | None -> ()) ; Lwt.return_error err end + +module Attributes = struct + module Transaction = struct + let hash hash = + ( "etherlink.transaction.hash", + `String (Ethereum_types.hash_to_string hash) ) + end + + module Block = struct + let number (Ethereum_types.Qty number) = + ("etherlink.block.number", `Int (Z.to_int number)) + + let execution_gas qty = + ("etherlink.block.execution_gas", `Int (Z.to_int qty)) + + let transaction_count qty = ("etherlink.block.transactions_count", `Int qty) + end +end diff --git a/etherlink/bin_node/lib_dev/telemetry.mli b/etherlink/bin_node/lib_dev/telemetry.mli index 018103ce28d3..3b42c364dc56 100644 --- a/etherlink/bin_node/lib_dev/telemetry.mli +++ b/etherlink/bin_node/lib_dev/telemetry.mli @@ -33,3 +33,25 @@ module Jsonrpc : sig related to [err]. *) val return_error : JSONRPC.error -> ('a, JSONRPC.error) result Lwt.t end + +(** OpenTelemetry Etherlink-specific semantics conventions *) +module Attributes : sig + module Transaction : sig + (** Hex-encoded hash of the transaction being processed *) + val hash : Ethereum_types.hash -> Opentelemetry.key_value + end + + (** Tags to add to a span or event handling a given block. *) + module Block : sig + (** Integer representation of the block number being processed *) + val number : Ethereum_types.quantity -> Opentelemetry.key_value + + (** Integer representation of the amount of gas units necessary to process + the block *) + val execution_gas : Z.t -> Opentelemetry.key_value + + (** Integer representation of the number of transactions included in the + block being processed *) + val transaction_count : int -> Opentelemetry.key_value + end +end diff --git a/etherlink/bin_node/lib_dev/tx_queue.ml b/etherlink/bin_node/lib_dev/tx_queue.ml index 9cc7f479b2cd..54986554c127 100644 --- a/etherlink/bin_node/lib_dev/tx_queue.ml +++ b/etherlink/bin_node/lib_dev/tx_queue.ml @@ -540,6 +540,11 @@ module Worker = Worker.MakeSingle (Name) (Request) (Types) type worker = Worker.infinite Worker.queue Worker.t +let tx_queue_event ?attrs name = + Opentelemetry_lwt.Event.make + ?attrs + Format.(sprintf "%s/%s" (String.concat "." Name.base) name) + module Handlers = struct open Request @@ -555,7 +560,11 @@ module Handlers = struct else let rev_batch, callbacks = Seq.fold_left - (fun (rev_batch, callbacks) {hash = _; payload; queue_callback} -> + (fun (rev_batch, callbacks) {hash; payload; queue_callback} -> + Octez_telemetry.Trace.add_event (fun () -> + tx_queue_event + ~attrs:Telemetry.Attributes.[Transaction.hash hash] + "selected_transaction") ; let req_id = Uuidm.(v4_gen uuid_seed () |> to_string ~upper:false) in diff --git a/src/lib_telemetry/trace.ml b/src/lib_telemetry/trace.ml index edc905eb4714..d18aee21da27 100644 --- a/src/lib_telemetry/trace.ml +++ b/src/lib_telemetry/trace.ml @@ -40,3 +40,15 @@ let with_result ?(message_on_success = Fun.const "Success") | res -> Lwt.return res let with_tzresult = with_result ~message_on_error:message_on_tztrace + +let add_attrs f = + if Opentelemetry.Collector.has_backend () then + match Opentelemetry.Scope.get_ambient_scope () with + | Some scope -> Opentelemetry_lwt.Trace.add_attrs scope @@ f + | None -> () + +let add_event f = + if Opentelemetry.Collector.has_backend () then + match Opentelemetry.Scope.get_ambient_scope () with + | Some scope -> Opentelemetry_lwt.Trace.add_event scope @@ f + | None -> () diff --git a/src/lib_telemetry/trace.mli b/src/lib_telemetry/trace.mli index 65f00192b9f6..c24d6048f0e4 100644 --- a/src/lib_telemetry/trace.mli +++ b/src/lib_telemetry/trace.mli @@ -21,3 +21,11 @@ val with_tzresult : string -> (Opentelemetry.Scope.t -> 'a tzresult Lwt.t) -> 'a tzresult Lwt.t + +(** [add_attrs f] adds the attributes generated by [f] to the current trace + being recorded, if any. Does nothing otherwise. *) +val add_attrs : (unit -> Opentelemetry.key_value list) -> unit + +(** [add_attrs f] adds the event generated by [f] to the current trace being + recorded, if any. Does nothing otherwise. *) +val add_event : (unit -> Opentelemetry.Event.t) -> unit -- GitLab