@@ -14,12 +14,20 @@ import (
14
14
"github.com/libp2p/go-libp2p/core/peer"
15
15
"github.com/libp2p/go-libp2p/core/protocol"
16
16
"github.com/libp2p/go-libp2p/p2p/net/conngater"
17
+ "go.opentelemetry.io/otel"
18
+ "go.opentelemetry.io/otel/attribute"
19
+ "go.opentelemetry.io/otel/codes"
20
+ "go.opentelemetry.io/otel/trace"
17
21
18
22
"github.com/celestiaorg/go-header"
19
23
p2p_pb "github.com/celestiaorg/go-header/p2p/pb"
20
24
)
21
25
22
- var log = logging .Logger ("header/p2p" )
26
+ var (
27
+ log = logging .Logger ("header/p2p" )
28
+
29
+ tracerClient = otel .Tracer ("header/p2p-client" )
30
+ )
23
31
24
32
// minHeadResponses is the minimum number of headers of the same height
25
33
// received from peers to determine the network head. If all trusted peers
@@ -113,6 +121,8 @@ func (ex *Exchange[H]) Stop(ctx context.Context) error {
113
121
// and return the highest one.
114
122
func (ex * Exchange [H ]) Head (ctx context.Context , opts ... header.HeadOption [H ]) (H , error ) {
115
123
log .Debug ("requesting head" )
124
+ ctx , span := tracerClient .Start (ctx , "head" )
125
+ defer span .End ()
116
126
117
127
reqCtx := ctx
118
128
startTime := time .Now ()
@@ -157,8 +167,15 @@ func (ex *Exchange[H]) Head(ctx context.Context, opts ...header.HeadOption[H]) (
157
167
)
158
168
for _ , from := range peers {
159
169
go func (from peer.ID ) {
170
+ _ , newSpan := tracerClient .Start (
171
+ ctx , "requesting peer" ,
172
+ trace .WithAttributes (attribute .String ("peerID" , from .String ())),
173
+ )
174
+ defer newSpan .End ()
175
+
160
176
headers , err := ex .request (reqCtx , from , headerReq )
161
177
if err != nil {
178
+ newSpan .SetStatus (codes .Error , err .Error ())
162
179
log .Errorw ("head request to peer failed" , "peer" , from , "err" , err )
163
180
headerRespCh <- zero
164
181
return
@@ -171,6 +188,7 @@ func (ex *Exchange[H]) Head(ctx context.Context, opts ...header.HeadOption[H]) (
171
188
if errors .As (err , & verErr ) && verErr .SoftFailure {
172
189
log .Debugw ("received head from tracked peer that soft-failed verification" ,
173
190
"tracked peer" , from , "err" , err )
191
+ newSpan .SetStatus (codes .Error , err .Error ())
174
192
headerRespCh <- headers [0 ]
175
193
return
176
194
}
@@ -180,10 +198,12 @@ func (ex *Exchange[H]) Head(ctx context.Context, opts ...header.HeadOption[H]) (
180
198
}
181
199
logF ("verifying head received from tracked peer" , "tracked peer" , from ,
182
200
"height" , headers [0 ].Height (), "err" , err )
201
+ newSpan .SetStatus (codes .Error , err .Error ())
183
202
headerRespCh <- zero
184
203
return
185
204
}
186
205
}
206
+ newSpan .SetStatus (codes .Ok , "" )
187
207
// request ensures that the result slice will have at least one Header
188
208
headerRespCh <- headers [0 ]
189
209
}(from )
@@ -206,22 +226,25 @@ func (ex *Exchange[H]) Head(ctx context.Context, opts ...header.HeadOption[H]) (
206
226
if errors .Is (ctx .Err (), context .DeadlineExceeded ) {
207
227
status = headStatusTimeout
208
228
}
209
-
229
+ span . SetStatus ( codes . Error , fmt . Sprintf ( "head request %s" , status ))
210
230
ex .metrics .head (ctx , time .Since (startTime ), len (headers ), headType , status )
211
231
return zero , ctx .Err ()
212
232
case <- ex .ctx .Done ():
213
233
ex .metrics .head (ctx , time .Since (startTime ), len (headers ), headType , headStatusCanceled )
234
+ span .SetStatus (codes .Error , "exchange client stopped" )
214
235
return zero , ex .ctx .Err ()
215
236
}
216
237
}
217
238
218
239
head , err := bestHead [H ](headers )
219
240
if err != nil {
220
241
ex .metrics .head (ctx , time .Since (startTime ), len (headers ), headType , headStatusNoHeaders )
242
+ span .SetStatus (codes .Error , headStatusNoHeaders )
221
243
return zero , err
222
244
}
223
245
224
246
ex .metrics .head (ctx , time .Since (startTime ), len (headers ), headType , headStatusOk )
247
+ span .SetStatus (codes .Ok , "" )
225
248
return head , nil
226
249
}
227
250
@@ -230,10 +253,17 @@ func (ex *Exchange[H]) Head(ctx context.Context, opts ...header.HeadOption[H]) (
230
253
// thereafter.
231
254
func (ex * Exchange [H ]) GetByHeight (ctx context.Context , height uint64 ) (H , error ) {
232
255
log .Debugw ("requesting header" , "height" , height )
256
+ ctx , span := tracerClient .Start (ctx , "get-by-height" ,
257
+ trace .WithAttributes (
258
+ attribute .Int64 ("height" , int64 (height )),
259
+ ))
260
+ defer span .End ()
233
261
var zero H
234
262
// sanity check height
235
263
if height == 0 {
236
- return zero , fmt .Errorf ("specified request height must be greater than 0" )
264
+ err := fmt .Errorf ("specified request height must be greater than 0" )
265
+ span .SetStatus (codes .Error , err .Error ())
266
+ return zero , err
237
267
}
238
268
// create request
239
269
req := & p2p_pb.HeaderRequest {
@@ -242,8 +272,10 @@ func (ex *Exchange[H]) GetByHeight(ctx context.Context, height uint64) (H, error
242
272
}
243
273
headers , err := ex .performRequest (ctx , req )
244
274
if err != nil {
275
+ span .SetStatus (codes .Error , err .Error ())
245
276
return zero , err
246
277
}
278
+ span .SetStatus (codes .Ok , "" )
247
279
return headers [0 ], nil
248
280
}
249
281
@@ -254,19 +286,36 @@ func (ex *Exchange[H]) GetRangeByHeight(
254
286
from H ,
255
287
to uint64 ,
256
288
) ([]H , error ) {
289
+ ctx , span := tracerClient .Start (ctx , "get-range-by-height" ,
290
+ trace .WithAttributes (
291
+ attribute .Int64 ("from" , int64 (from .Height ())),
292
+ attribute .Int64 ("to" , int64 (to )),
293
+ ))
294
+ defer span .End ()
257
295
session := newSession [H ](
258
296
ex .ctx , ex .host , ex .peerTracker , ex .protocolID , ex .Params .RangeRequestTimeout , ex .metrics , withValidation (from ),
259
297
)
260
298
defer session .close ()
261
299
// we request the next header height that we don't have: `fromHead`+1
262
300
amount := to - (from .Height () + 1 )
263
- return session .getRangeByHeight (ctx , from .Height ()+ 1 , amount , ex .Params .MaxHeadersPerRangeRequest )
301
+ result , err := session .getRangeByHeight (ctx , from .Height ()+ 1 , amount , ex .Params .MaxHeadersPerRangeRequest )
302
+ if err != nil {
303
+ span .SetStatus (codes .Error , err .Error ())
304
+ return nil , err
305
+ }
306
+ span .SetStatus (codes .Ok , "" )
307
+ return result , nil
264
308
}
265
309
266
310
// Get performs a request for the Header by the given hash corresponding
267
311
// to the RawHeader. Note that the Header must be verified thereafter.
268
312
func (ex * Exchange [H ]) Get (ctx context.Context , hash header.Hash ) (H , error ) {
269
313
log .Debugw ("requesting header" , "hash" , hash .String ())
314
+ ctx , span := tracerClient .Start (ctx , "get-by-hash" ,
315
+ trace .WithAttributes (
316
+ attribute .String ("hash" , hash .String ()),
317
+ ))
318
+ defer span .End ()
270
319
var zero H
271
320
// create request
272
321
req := & p2p_pb.HeaderRequest {
@@ -275,12 +324,16 @@ func (ex *Exchange[H]) Get(ctx context.Context, hash header.Hash) (H, error) {
275
324
}
276
325
headers , err := ex .performRequest (ctx , req )
277
326
if err != nil {
327
+ span .SetStatus (codes .Error , err .Error ())
278
328
return zero , err
279
329
}
280
330
281
331
if ! bytes .Equal (headers [0 ].Hash (), hash ) {
282
- return zero , fmt .Errorf ("incorrect hash in header: expected %x, got %x" , hash , headers [0 ].Hash ())
332
+ err = fmt .Errorf ("incorrect hash in header: expected %x, got %x" , hash , headers [0 ].Hash ())
333
+ span .SetStatus (codes .Error , err .Error ())
334
+ return zero , err
283
335
}
336
+ span .SetStatus (codes .Ok , "" )
284
337
return headers [0 ], nil
285
338
}
286
339
0 commit comments