Skip to content

Commit dfd76ac

Browse files
authored
feat(tracing): tracing part 9 sequencer (#2990)
* feat: add sequencer tracing instrumentation Add OpenTelemetry tracing for the core Sequencer interface. This traces all three main operations: - SubmitBatchTxs: tracks tx count and batch size - GetNextBatch: tracks tx count, forced inclusion count, batch size - VerifyBatch: tracks batch data count and verification result The tracing wrapper can be used with any Sequencer implementation (single, based, etc.) via WithTracingSequencer(). * chore: using helper fn instead of having it duplicated
1 parent 12dab2f commit dfd76ac

File tree

10 files changed

+503
-203
lines changed

10 files changed

+503
-203
lines changed

block/components.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/evstack/ev-node/pkg/genesis"
2121
"github.com/evstack/ev-node/pkg/signer"
2222
"github.com/evstack/ev-node/pkg/store"
23+
"github.com/evstack/ev-node/pkg/telemetry"
2324
"github.com/evstack/ev-node/types"
2425
)
2526

@@ -205,6 +206,11 @@ func NewAggregatorComponents(
205206
// error channel for critical failures
206207
errorCh := make(chan error, 1)
207208

209+
// wrap sequencer with tracing if enabled
210+
if config.Instrumentation.IsTracingEnabled() {
211+
sequencer = telemetry.WithTracingSequencer(sequencer)
212+
}
213+
208214
executor, err := executing.NewExecutor(
209215
store,
210216
exec,

block/internal/da/tracing_test.go

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77

88
"github.com/stretchr/testify/require"
99
"go.opentelemetry.io/otel"
10-
"go.opentelemetry.io/otel/attribute"
1110
"go.opentelemetry.io/otel/codes"
1211
sdktrace "go.opentelemetry.io/otel/sdk/trace"
1312
"go.opentelemetry.io/otel/sdk/trace/tracetest"
1413

1514
datypes "github.com/evstack/ev-node/pkg/da/types"
15+
"github.com/evstack/ev-node/pkg/telemetry/testutil"
1616
)
1717

1818
// mockFullClient provides function hooks for testing the tracing decorator.
@@ -87,8 +87,8 @@ func TestTracedDA_Submit_Success(t *testing.T) {
8787
require.Equal(t, codes.Unset, span.Status().Code)
8888

8989
attrs := span.Attributes()
90-
requireAttribute(t, attrs, "blob.count", 2)
91-
requireAttribute(t, attrs, "blob.total_size_bytes", 3)
90+
testutil.RequireAttribute(t, attrs, "blob.count", 2)
91+
testutil.RequireAttribute(t, attrs, "blob.total_size_bytes", 3)
9292
// namespace hex string length assertion
9393
// 2 bytes = 4 hex characters
9494
foundNS := false
@@ -134,8 +134,8 @@ func TestTracedDA_Retrieve_Success(t *testing.T) {
134134
span := spans[0]
135135
require.Equal(t, "DA.Retrieve", span.Name())
136136
attrs := span.Attributes()
137-
requireAttribute(t, attrs, "ns.length", 1)
138-
requireAttribute(t, attrs, "blob.count", 2)
137+
testutil.RequireAttribute(t, attrs, "ns.length", 1)
138+
testutil.RequireAttribute(t, attrs, "blob.count", 2)
139139
}
140140

141141
func TestTracedDA_Retrieve_Error(t *testing.T) {
@@ -174,8 +174,8 @@ func TestTracedDA_Get_Success(t *testing.T) {
174174
span := spans[0]
175175
require.Equal(t, "DA.Get", span.Name())
176176
attrs := span.Attributes()
177-
requireAttribute(t, attrs, "id.count", 2)
178-
requireAttribute(t, attrs, "blob.count", 2)
177+
testutil.RequireAttribute(t, attrs, "id.count", 2)
178+
testutil.RequireAttribute(t, attrs, "blob.count", 2)
179179
}
180180

181181
func TestTracedDA_Get_Error(t *testing.T) {
@@ -197,26 +197,3 @@ func TestTracedDA_Get_Error(t *testing.T) {
197197
require.Equal(t, codes.Error, span.Status().Code)
198198
require.Equal(t, "get failed", span.Status().Description)
199199
}
200-
201-
// helper copied from eth tracing tests
202-
func requireAttribute(t *testing.T, attrs []attribute.KeyValue, key string, expected interface{}) {
203-
t.Helper()
204-
found := false
205-
for _, attr := range attrs {
206-
if string(attr.Key) == key {
207-
found = true
208-
switch v := expected.(type) {
209-
case string:
210-
require.Equal(t, v, attr.Value.AsString())
211-
case int64:
212-
require.Equal(t, v, attr.Value.AsInt64())
213-
case int:
214-
require.Equal(t, int64(v), attr.Value.AsInt64())
215-
default:
216-
t.Fatalf("unsupported attribute type: %T", expected)
217-
}
218-
break
219-
}
220-
}
221-
require.True(t, found, "attribute %s not found", key)
222-
}

block/internal/executing/tracing_test.go

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77

88
"github.com/stretchr/testify/require"
99
"go.opentelemetry.io/otel"
10-
"go.opentelemetry.io/otel/attribute"
1110
"go.opentelemetry.io/otel/codes"
1211
sdktrace "go.opentelemetry.io/otel/sdk/trace"
1312
"go.opentelemetry.io/otel/sdk/trace/tracetest"
1413

1514
coresequencer "github.com/evstack/ev-node/core/sequencer"
15+
"github.com/evstack/ev-node/pkg/telemetry/testutil"
1616
"github.com/evstack/ev-node/types"
1717
)
1818

@@ -131,7 +131,7 @@ func TestTracedBlockProducer_RetrieveBatch_Success(t *testing.T) {
131131
require.Equal(t, codes.Unset, span.Status().Code)
132132

133133
attrs := span.Attributes()
134-
requireAttribute(t, attrs, "batch.tx_count", 2)
134+
testutil.RequireAttribute(t, attrs, "batch.tx_count", 2)
135135
}
136136

137137
func TestTracedBlockProducer_RetrieveBatch_Error(t *testing.T) {
@@ -180,8 +180,8 @@ func TestTracedBlockProducer_CreateBlock_Success(t *testing.T) {
180180
require.Equal(t, codes.Unset, span.Status().Code)
181181

182182
attrs := span.Attributes()
183-
requireAttribute(t, attrs, "block.height", int64(100))
184-
requireAttribute(t, attrs, "tx.count", 3)
183+
testutil.RequireAttribute(t, attrs, "block.height", int64(100))
184+
testutil.RequireAttribute(t, attrs, "tx.count", 3)
185185
}
186186

187187
func TestTracedBlockProducer_CreateBlock_Error(t *testing.T) {
@@ -234,9 +234,9 @@ func TestTracedBlockProducer_ApplyBlock_Success(t *testing.T) {
234234
require.Equal(t, codes.Unset, span.Status().Code)
235235

236236
attrs := span.Attributes()
237-
requireAttribute(t, attrs, "block.height", int64(50))
238-
requireAttribute(t, attrs, "tx.count", 2)
239-
requireAttribute(t, attrs, "state_root", "deadbeef")
237+
testutil.RequireAttribute(t, attrs, "block.height", int64(50))
238+
testutil.RequireAttribute(t, attrs, "tx.count", 2)
239+
testutil.RequireAttribute(t, attrs, "state_root", "deadbeef")
240240
}
241241

242242
func TestTracedBlockProducer_ApplyBlock_Error(t *testing.T) {
@@ -291,7 +291,7 @@ func TestTracedBlockProducer_ValidateBlock_Success(t *testing.T) {
291291
require.Equal(t, codes.Unset, span.Status().Code)
292292

293293
attrs := span.Attributes()
294-
requireAttribute(t, attrs, "block.height", int64(75))
294+
testutil.RequireAttribute(t, attrs, "block.height", int64(75))
295295
}
296296

297297
func TestTracedBlockProducer_ValidateBlock_Error(t *testing.T) {
@@ -320,25 +320,3 @@ func TestTracedBlockProducer_ValidateBlock_Error(t *testing.T) {
320320
require.Equal(t, codes.Error, span.Status().Code)
321321
require.Equal(t, "validation failed", span.Status().Description)
322322
}
323-
324-
func requireAttribute(t *testing.T, attrs []attribute.KeyValue, key string, expected interface{}) {
325-
t.Helper()
326-
found := false
327-
for _, attr := range attrs {
328-
if string(attr.Key) == key {
329-
found = true
330-
switch v := expected.(type) {
331-
case string:
332-
require.Equal(t, v, attr.Value.AsString())
333-
case int64:
334-
require.Equal(t, v, attr.Value.AsInt64())
335-
case int:
336-
require.Equal(t, int64(v), attr.Value.AsInt64())
337-
default:
338-
t.Fatalf("unsupported attribute type: %T", expected)
339-
}
340-
break
341-
}
342-
}
343-
require.True(t, found, "attribute %s not found", key)
344-
}

block/internal/syncing/tracing_test.go

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77

88
"github.com/stretchr/testify/require"
99
"go.opentelemetry.io/otel"
10-
"go.opentelemetry.io/otel/attribute"
1110
"go.opentelemetry.io/otel/codes"
1211
sdktrace "go.opentelemetry.io/otel/sdk/trace"
1312
"go.opentelemetry.io/otel/sdk/trace/tracetest"
1413

1514
"github.com/evstack/ev-node/block/internal/common"
15+
"github.com/evstack/ev-node/pkg/telemetry/testutil"
1616
"github.com/evstack/ev-node/types"
1717
)
1818

@@ -92,9 +92,9 @@ func TestTracedBlockSyncer_TrySyncNextBlock_Success(t *testing.T) {
9292
require.Equal(t, codes.Unset, span.Status().Code)
9393

9494
attrs := span.Attributes()
95-
requireAttribute(t, attrs, "block.height", int64(100))
96-
requireAttribute(t, attrs, "da.height", int64(50))
97-
requireAttribute(t, attrs, "source", string(common.SourceDA))
95+
testutil.RequireAttribute(t, attrs, "block.height", int64(100))
96+
testutil.RequireAttribute(t, attrs, "da.height", int64(50))
97+
testutil.RequireAttribute(t, attrs, "source", string(common.SourceDA))
9898
}
9999

100100
func TestTracedBlockSyncer_TrySyncNextBlock_Error(t *testing.T) {
@@ -159,9 +159,9 @@ func TestTracedBlockSyncer_ApplyBlock_Success(t *testing.T) {
159159
require.Equal(t, codes.Unset, span.Status().Code)
160160

161161
attrs := span.Attributes()
162-
requireAttribute(t, attrs, "block.height", int64(50))
163-
requireAttribute(t, attrs, "tx.count", 2)
164-
requireAttribute(t, attrs, "state_root", "deadbeef")
162+
testutil.RequireAttribute(t, attrs, "block.height", int64(50))
163+
testutil.RequireAttribute(t, attrs, "tx.count", 2)
164+
testutil.RequireAttribute(t, attrs, "state_root", "deadbeef")
165165
}
166166

167167
func TestTracedBlockSyncer_ApplyBlock_Error(t *testing.T) {
@@ -216,7 +216,7 @@ func TestTracedBlockSyncer_ValidateBlock_Success(t *testing.T) {
216216
require.Equal(t, codes.Unset, span.Status().Code)
217217

218218
attrs := span.Attributes()
219-
requireAttribute(t, attrs, "block.height", int64(75))
219+
testutil.RequireAttribute(t, attrs, "block.height", int64(75))
220220
}
221221

222222
func TestTracedBlockSyncer_ValidateBlock_Error(t *testing.T) {
@@ -274,8 +274,8 @@ func TestTracedBlockSyncer_VerifyForcedInclusionTxs_Success(t *testing.T) {
274274
require.Equal(t, codes.Unset, span.Status().Code)
275275

276276
attrs := span.Attributes()
277-
requireAttribute(t, attrs, "block.height", int64(100))
278-
requireAttribute(t, attrs, "da.height", int64(50))
277+
testutil.RequireAttribute(t, attrs, "block.height", int64(100))
278+
testutil.RequireAttribute(t, attrs, "da.height", int64(50))
279279
}
280280

281281
func TestTracedBlockSyncer_VerifyForcedInclusionTxs_Error(t *testing.T) {
@@ -305,25 +305,3 @@ func TestTracedBlockSyncer_VerifyForcedInclusionTxs_Error(t *testing.T) {
305305
require.Equal(t, codes.Error, span.Status().Code)
306306
require.Equal(t, "forced inclusion verification failed", span.Status().Description)
307307
}
308-
309-
func requireAttribute(t *testing.T, attrs []attribute.KeyValue, key string, expected interface{}) {
310-
t.Helper()
311-
found := false
312-
for _, attr := range attrs {
313-
if string(attr.Key) == key {
314-
found = true
315-
switch v := expected.(type) {
316-
case string:
317-
require.Equal(t, v, attr.Value.AsString())
318-
case int64:
319-
require.Equal(t, v, attr.Value.AsInt64())
320-
case int:
321-
require.Equal(t, int64(v), attr.Value.AsInt64())
322-
default:
323-
t.Fatalf("unsupported attribute type: %T", expected)
324-
}
325-
break
326-
}
327-
}
328-
require.True(t, found, "attribute %s not found", key)
329-
}

execution/evm/eth_rpc_tracing_test.go

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import (
99
"github.com/ethereum/go-ethereum/core/types"
1010
"github.com/stretchr/testify/require"
1111
"go.opentelemetry.io/otel"
12-
"go.opentelemetry.io/otel/attribute"
1312
"go.opentelemetry.io/otel/codes"
1413
"go.opentelemetry.io/otel/sdk/trace"
1514
"go.opentelemetry.io/otel/sdk/trace/tracetest"
15+
16+
"github.com/evstack/ev-node/pkg/telemetry/testutil"
1617
)
1718

1819
// setupTestEthRPCTracing creates a traced eth RPC client with an in-memory span recorder
@@ -90,13 +91,13 @@ func TestTracedEthRPCClient_HeaderByNumber_Success(t *testing.T) {
9091

9192
// verify attributes
9293
attrs := span.Attributes()
93-
requireAttribute(t, attrs, "method", "eth_getBlockByNumber")
94-
requireAttribute(t, attrs, "block_number", "100")
95-
requireAttribute(t, attrs, "block_hash", expectedHeader.Hash().Hex())
96-
requireAttribute(t, attrs, "state_root", expectedHeader.Root.Hex())
97-
requireAttribute(t, attrs, "gas_limit", int64(expectedHeader.GasLimit))
98-
requireAttribute(t, attrs, "gas_used", int64(expectedHeader.GasUsed))
99-
requireAttribute(t, attrs, "timestamp", int64(expectedHeader.Time))
94+
testutil.RequireAttribute(t, attrs, "method", "eth_getBlockByNumber")
95+
testutil.RequireAttribute(t, attrs, "block_number", "100")
96+
testutil.RequireAttribute(t, attrs, "block_hash", expectedHeader.Hash().Hex())
97+
testutil.RequireAttribute(t, attrs, "state_root", expectedHeader.Root.Hex())
98+
testutil.RequireAttribute(t, attrs, "gas_limit", int64(expectedHeader.GasLimit))
99+
testutil.RequireAttribute(t, attrs, "gas_used", int64(expectedHeader.GasUsed))
100+
testutil.RequireAttribute(t, attrs, "timestamp", int64(expectedHeader.Time))
100101
}
101102

102103
func TestTracedEthRPCClient_HeaderByNumber_Latest(t *testing.T) {
@@ -131,7 +132,7 @@ func TestTracedEthRPCClient_HeaderByNumber_Latest(t *testing.T) {
131132

132133
// verify block_number is "latest" when nil
133134
attrs := span.Attributes()
134-
requireAttribute(t, attrs, "block_number", "latest")
135+
testutil.RequireAttribute(t, attrs, "block_number", "latest")
135136
}
136137

137138
func TestTracedEthRPCClient_HeaderByNumber_Error(t *testing.T) {
@@ -206,8 +207,8 @@ func TestTracedEthRPCClient_GetTxs_Success(t *testing.T) {
206207

207208
// verify attributes
208209
attrs := span.Attributes()
209-
requireAttribute(t, attrs, "method", "txpoolExt_getTxs")
210-
requireAttribute(t, attrs, "tx_count", len(expectedTxs))
210+
testutil.RequireAttribute(t, attrs, "method", "txpoolExt_getTxs")
211+
testutil.RequireAttribute(t, attrs, "tx_count", len(expectedTxs))
211212
}
212213

213214
func TestTracedEthRPCClient_GetTxs_EmptyPool(t *testing.T) {
@@ -235,7 +236,7 @@ func TestTracedEthRPCClient_GetTxs_EmptyPool(t *testing.T) {
235236

236237
// verify tx_count is 0
237238
attrs := span.Attributes()
238-
requireAttribute(t, attrs, "tx_count", 0)
239+
testutil.RequireAttribute(t, attrs, "tx_count", 0)
239240
}
240241

241242
func TestTracedEthRPCClient_GetTxs_Error(t *testing.T) {
@@ -276,26 +277,3 @@ func TestTracedEthRPCClient_GetTxs_Error(t *testing.T) {
276277
require.NotEqual(t, "tx_count", string(attr.Key))
277278
}
278279
}
279-
280-
// requireAttribute is a helper to check span attributes
281-
func requireAttribute(t *testing.T, attrs []attribute.KeyValue, key string, expected interface{}) {
282-
t.Helper()
283-
found := false
284-
for _, attr := range attrs {
285-
if string(attr.Key) == key {
286-
found = true
287-
switch v := expected.(type) {
288-
case string:
289-
require.Equal(t, v, attr.Value.AsString())
290-
case int64:
291-
require.Equal(t, v, attr.Value.AsInt64())
292-
case int:
293-
require.Equal(t, int64(v), attr.Value.AsInt64())
294-
default:
295-
t.Fatalf("unsupported attribute type: %T", expected)
296-
}
297-
break
298-
}
299-
}
300-
require.True(t, found, "attribute %s not found", key)
301-
}

0 commit comments

Comments
 (0)