@@ -258,7 +258,7 @@ may suggest that your encoder is misconfigured or that the streamer internet
258
258
connection isn't as strong as it should be to deliver high-quality streams to
259
259
your viewers.
260
260
261
- ## Monitoring Stream Health Using The Dashboard
261
+ ### Monitoring in the Dashboard
262
262
263
263
In the dashboard, there will be a ` health ` tab on the right side:
264
264
@@ -283,336 +283,9 @@ At the bottom of the page, a chart will show the ingest rate of a livestream:
283
283
![ image] ( https://user-images.githubusercontent.com/79172645/135467197-08ec63ab-4c44-4cad-a0d5-95a76b80e5c5.png )
284
284
</Frame >
285
285
286
- ## Monitor Stream Health Using The API
286
+ ### Monitor with the API
287
287
288
- The health information about a stream can also be queried using a separate
289
- Stream Health API resides on a different root path ` /data ` . To use it, you need
290
- to include the same API key as the one used for the regular API. The API
291
- consists of the following endpoints:
292
-
293
- - Health Status (` /data/stream/{streamId}/health ` ): Grabs the latest health
294
- status info about a given stream, referenced by its Stream ID. This API powers
295
- the dashboard health checks and multistream status.
296
- - Events (` /data/stream/{streamId}/events ` ): Provides direct access to the
297
- low-level events sent by Livepeer video-processing services. It also allows
298
- subscribing via SSE to receive new events and is useful for debugging. This
299
- API powers the log feed in the dashboard.
300
-
301
- Now let's go into more detail about each of the mentioned API endpoints.
302
-
303
- ## Health Status
304
-
305
- The stream ID is the same one as used in the Livestream API.
306
-
307
- ` GET livepeer.studio/data/stream/{id}/health `
308
-
309
- <Tabs >
310
- <Tab title = " Node.js" >
311
- ``` javascript
312
- import { Livepeer } from " livepeer" ;
313
-
314
- const apiKey = ' YOUR_API_KEY' ;
315
- const streamId = ' STREAM_ID' ;
316
-
317
- const livepeer = new Livepeer ({apiKey});
318
-
319
- livepeer
320
- .getStreamHealth (streamId)
321
- .then ((response ) => {
322
- console .log (" Stream health:" , response);
323
- })
324
- .catch ((error ) => {
325
- console .error (" Error fetching stream health:" , error);
326
- });
327
- ```
328
-
329
- </Tab >
330
-
331
- <Tab title = " Python" >
332
- ``` python
333
- from livepeer import Livepeer
334
-
335
- # Initialize the Livepeer client with your API key
336
- api_key = " YOUR_API_KEY"
337
- livepeer = Livepeer(api_key)
338
-
339
- # Define the stream ID for which you want to check health
340
- stream_id = " STREAM_ID"
341
-
342
- try :
343
- # Get stream health by stream ID
344
- response = livepeer.get_stream_health(stream_id)
345
- print (" Stream health:" , response)
346
- except Exception as e:
347
- print (" Error fetching stream health:" , e)
348
- ```
349
-
350
- </Tab >
351
-
352
- <Tab title = " Go" >
353
- ``` go
354
- package main
355
-
356
- import (
357
- " fmt"
358
- " os"
359
-
360
- " github.com/livepeer/livepeer-go"
361
- )
362
-
363
- func main () {
364
- // Initialize the Livepeer client with your API key
365
- apiKey := " YOUR_API_KEY"
366
- client := livepeer.NewLivepeerClient (apiKey)
367
-
368
- // Define the stream ID for which you want to check health
369
- streamID := " STREAM_ID"
370
-
371
- // Get stream health by stream ID
372
- response , err := client.GetStreamHealth (streamID)
373
- if err != nil {
374
- fmt.Printf (" Error fetching stream health: %v \n " , err)
375
- os.Exit (1 )
376
- }
377
-
378
- fmt.Printf (" Stream health: %+v \n " , response)
379
- }
380
- ```
381
-
382
- </Tab >
383
- </Tabs >
384
-
385
- ### Response
386
-
387
- Returns an object with a ` 200 OK ` response
388
-
389
- ``` json
390
- {
391
- "id" : " {id}" ,
392
- "healthy" : {
393
- "status" : true ,
394
- "frequency" : { "1m" : 1 , "10m" : 0.9655 , "60m" : 0.9655 },
395
- "lastProbeTime" : 1635993921603 ,
396
- "lastTransitionsTime" : 1635993751824
397
- },
398
- "conditions" : [
399
- {
400
- "type" : " Active" ,
401
- "status" : true ,
402
- "extraData" : {
403
- "nodeId" : " prod-mist-blue-server-1" ,
404
- "region" : " lon"
405
- },
406
- "frequency" : { "1m" : 1 , "10m" : 1 , "60m" : 1 },
407
- "lastProbeTime" : 1635993739354 ,
408
- "lastTransitionsTime" : 1635993739354
409
- },
410
- {
411
- "type" : " Transcoding" ,
412
- "status" : true ,
413
- "frequency" : { "1m" : 1 , "10m" : 1 , "60m" : 1 },
414
- "lastProbeTime" : 1635993920641 ,
415
- "lastTransitionsTime" : 1635993751824
416
- },
417
- {
418
- "type" : " TranscodeRealTime" ,
419
- "status" : true ,
420
- "frequency" : { "1m" : 1 , "10m" : 1 , "60m" : 1 },
421
- "lastProbeTime" : 1635993920641 ,
422
- "lastTransitionsTime" : 1635993751824
423
- },
424
- {
425
- "type" : " TranscodeNoErrors" ,
426
- "status" : true ,
427
- "frequency" : { "1m" : 1 , "10m" : 1 , "60m" : 1 },
428
- "lastProbeTime" : 1635993920641 ,
429
- "lastTransitionsTime" : 1635993751824
430
- },
431
- {
432
- "type" : " Multistreaming" ,
433
- "status" : null ,
434
- "lastProbeTime" : null ,
435
- "lastTransitionsTime" : null
436
- }
437
- ],
438
- "metrics" : {
439
- "MediaTimeMillis" : [
440
- {
441
- "name" : " MediaTimeMillis" ,
442
- "dimensions" : { "nodeId" : " prod-mist-blue-server-1" },
443
- "last" : [1635993921603 , 182528 ]
444
- }
445
- ],
446
- "TranscodeRealtimeRatio" : [
447
- {
448
- "name" : " TranscodeRealtimeRatio" ,
449
- "dimensions" : {
450
- "nodeId" : " prod-livepeer-broadcaster-6emu-97d8bf496-7zh9f"
451
- },
452
- "last" : [1635993920641 , 3.088169642857143 ]
453
- }
454
- ]
455
- }
456
- }
457
- ```
458
-
459
- In the above response payload:
460
-
461
- - All ` timestamps ` are represented in milliseconds since the Unix epoch, which
462
- is the default representation of timestamps across all the Livepeer API.
463
- - The ` healthy ` top-level ` condition ` is a computed state based on some specific
464
- stream conditions. As of writing this doc, a stream is ` healthy ` if it's both
465
- ` Active ` , ` Transcoding ` in realtime (` TranscodeRealTime ` ), and if multistream
466
- targets are configured, they are also healthy (` Multistreaming ` ).
467
- - The ` conditions ` array contains more specific information about the stream
468
- health state, with the ` type ` field specifying what the condition means.
469
- - More generally, a ` Condition ` represents a specific state of the stream
470
- health.
471
- - The ` status ` field represents the value of the last reading for that
472
- condition, and the ` lastProbeTime ` specified when that was.
473
- - The ` lastTransitionsTime ` and the ` frequency ` fields provide some insight
474
- into how it's changing over time.
475
- - The ` lastTransitionTime ` is the timestamp of the last time where the
476
- condition status changed, and;
477
- - The ` frequency ` is the ratio of successful probes (` status: true ` ) in the
478
- specified time ranges preceding ` lastProbeTime ` .
479
- - The ` metrics ` are still an experimental API and are not recommended for
480
- production systems. But the ` last ` field is a tuple containing the ` timestamp `
481
- and the ` value ` of the last reading for that metric.
482
-
483
- ## Events
484
-
485
- ### Request
486
-
487
- The stream ID is the same one used in the Livestream API.
488
-
489
- ` GET livepeer.studio/data/stream/{id}/events `
490
-
491
- <Tabs >
492
- <Tab title = " Node.js" >
493
- ``` javascript
494
- import { Livepeer } from " livepeer" ;
495
-
496
- const apiKey = ' YOUR_API_KEY' ;
497
- const streamId = ' STREAM_ID' ;
498
-
499
- const livepeer = new Livepeer ({apiKey});
500
-
501
- livepeer
502
- .getStreamEvents (streamId)
503
- .then ((response ) => {
504
- console .log (" Stream events:" , response);
505
- })
506
- .catch ((error ) => {
507
- console .error (" Error fetching stream events:" , error);
508
- });
509
- ```
510
-
511
- </Tab >
512
-
513
- <Tab title = " Python" >
514
- ``` python
515
- from livepeer import Livepeer
516
-
517
- # Initialize the Livepeer client with your API key
518
- api_key = " YOUR_API_KEY"
519
- livepeer = Livepeer(api_key)
520
-
521
- # Define the stream ID for which you want to fetch events
522
- stream_id = " STREAM_ID"
523
-
524
- try :
525
- # Get stream events by stream ID
526
- response = livepeer.get_stream_events(stream_id)
527
- print (" Stream events:" , response)
528
- except Exception as e:
529
- print (" Error fetching stream events:" , e)
530
- ```
531
-
532
- </Tab >
533
-
534
- <Tab title = " Go" >
535
- ``` go
536
- package main
537
-
538
- import (
539
- " fmt"
540
- " os"
541
-
542
- " github.com/livepeer/livepeer-go"
543
- )
544
-
545
- func main () {
546
- // Initialize the Livepeer client with your API key
547
- apiKey := " YOUR_API_KEY"
548
- client := livepeer.NewLivepeerClient (apiKey)
549
-
550
- // Define the stream ID for which you want to fetch events
551
- streamID := " STREAM_ID"
552
-
553
- // Get stream events by stream ID
554
- response , err := client.GetStreamEvents (streamID)
555
- if err != nil {
556
- fmt.Printf (" Error fetching stream events: %v \n " , err)
557
- os.Exit (1 )
558
- }
559
-
560
- fmt.Printf (" Stream events: %+v \n " , response)
561
- }
562
- ```
563
-
564
- </Tab >
565
- </Tabs >
566
-
567
- ### Response
568
-
569
- Returns an object with a ` 200 OK ` response
570
-
571
- ```
572
- retry: 10000
573
-
574
- id: b6e0d6a4-0718-4db4-b2ec-31bb23a9fde0
575
- event: lp_event
576
- data: {"type":"media_server_metrics","id":"b6e0d6a4-0718-4db4-b2ec-31bb23a9fde0","timestamp":1635994871604,"streamId":"{id}","nodeId":"prod-mist-blue-server-1","region":"lon","stats":{"mediaTimeMs":1132566},"multistream":[]}
577
-
578
- id: 7a0e6f9e-baa1-42c4-a92f-4dfa2f50ac05
579
- event: lp_event
580
- data: {"type":"transcode","id":"7a0e6f9e-baa1-42c4-a92f-4dfa2f50ac05","timestamp":1635994875678,"streamId":"{id}","nodeId":"prod-livepeer-broadcaster-6emu-97d8bf496-7zh9f","segment":{"name":"","seqNo":292,"duration":8.334,"byteSize":2270100},"startTime":1635994874469,"latencyMs":1209,"success":true,"attempts":[{"orchestrator":{"address":"0x1cd98ad89a7d143847f62d2249e4005d09e10648","transcodeUri":"https://vno2-prod-livepeer-orchestrator-7.livepeer.studio:443"},"latencyMs":1209,"error":null}]}
581
-
582
- id: fd782a49-4986-4b3c-b3b4-9088ae76c152
583
- event: lp_event
584
- data:
585
- {"type":"media_server_metrics","id":"fd782a49-4986-4b3c-b3b4-9088ae76c152","timestamp":1635994881604,"streamId":"{id}","nodeId":"prod-mist-blue-server-1","region":"lon","stats":{"mediaTimeMs":1142550},"multistream":[]}
586
- ...
587
- ```
588
-
589
- The ` /events ` API response implements the
590
- [ Server-Sent Events] ( https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events )
591
- protocol using any SSE client. On JavaScript, we recommend using the
592
- [ ` eventsource ` ] ( https://www.npmjs.com/package/eventsource ) NPM package to be
593
- able to add an ` Authorization ` header to the API request.
594
-
595
- The individual events sent over the SSE stream are all JSON objects and are
596
- precisely the same low-level objects as published by the services running in the
597
- Livepeer infrastructure. Some fields are always present, specifically:
598
-
599
- - ` type ` : the unique type of the event, which defines the structure of the rest
600
- of the JSON object.
601
- - ` id ` : a unique identifier for the event, which SSE clients automatically use
602
- to recover a connection without losing events.
603
- - ` timestamp ` : the timestamp of the event in milliseconds since the Unix epoch.
604
-
605
- You can also get historical events within a time range by specifying the ` from `
606
- and ` to ` query parameters with Unix millis timestamps. For example:
607
-
608
- - ` /data/stream/{id}/events?from=1635437394000 ` to get all events since
609
- ` Oct 28 16:09:54Z 2021 ` (exclusively) and stay connected for live events.
610
- - ` /data/stream/{id}/events?from=1635437394000&to=1635447394000 ` to get all
611
- events between ` Oct 28 16:09:54Z 2021 ` (exclusively) and
612
- ` Oct 28 18:56:34Z 2021 ` (inclusively).
613
-
614
- Finally, we recommend using the events API primarily for debugging purposes, for
615
- example, to get all available information about a livestream to find any issues.
616
- The specific events that are published and
617
- [ their respective schemas] ( https://github.com/livepeer/livepeer-data/tree/main/pkg/data )
618
- will keep evolving, so they are still subject to changes.
288
+ <Info >
289
+ We are working on building a first-class solution to monitor stream health
290
+ using the API. Please reach out to us on Discord if you have any input.
291
+ </Info >
0 commit comments