1
1
use candid:: { candid_method, Nat , Principal } ;
2
+ use ic_canisters_http_types:: { HttpRequest , HttpResponse , HttpResponseBuilder } ;
2
3
use ic_cdk:: trap;
3
4
use ic_cdk_macros:: { init, post_upgrade, query, update} ;
4
5
use ic_cdk_timers:: TimerId ;
@@ -93,6 +94,9 @@ struct State {
93
94
94
95
/// The maximum number of transactions returned by [get_blocks].
95
96
max_blocks_per_response : u64 ,
97
+
98
+ // Last wait time in nanoseconds.
99
+ pub last_wait_time : Duration ,
96
100
}
97
101
98
102
// NOTE: the default configuration is dysfunctional, but it's convenient to have
@@ -103,6 +107,7 @@ impl Default for State {
103
107
is_build_index_running : false ,
104
108
ledger_id : Principal :: management_canister ( ) ,
105
109
max_blocks_per_response : DEFAULT_MAX_BLOCKS_PER_RESPONSE ,
110
+ last_wait_time : Duration :: from_secs ( 0 ) ,
106
111
}
107
112
}
108
113
}
@@ -312,6 +317,7 @@ pub async fn build_index() -> Result<(), String> {
312
317
append_blocks ( res. blocks ) ;
313
318
let wait_time = compute_wait_time ( tx_indexed_count) ;
314
319
ic_cdk:: eprintln!( "Indexed: {} waiting : {:?}" , tx_indexed_count, wait_time) ;
320
+ change_state ( |mut state| state. last_wait_time = wait_time) ;
315
321
ScopeGuard :: into_inner ( failure_guard) ;
316
322
set_build_index_timer ( wait_time) ;
317
323
Ok ( ( ) )
@@ -640,6 +646,64 @@ fn list_subaccounts(args: ListSubaccountsArgs) -> Vec<Subaccount> {
640
646
} )
641
647
}
642
648
649
+ #[ candid_method( query) ]
650
+ #[ query]
651
+ fn http_request ( req : HttpRequest ) -> HttpResponse {
652
+ if req. path ( ) == "/metrics" {
653
+ let mut writer =
654
+ ic_metrics_encoder:: MetricsEncoder :: new ( vec ! [ ] , ic_cdk:: api:: time ( ) as i64 / 1_000_000 ) ;
655
+
656
+ match encode_metrics ( & mut writer) {
657
+ Ok ( ( ) ) => HttpResponseBuilder :: ok ( )
658
+ . header ( "Content-Type" , "text/plain; version=0.0.4" )
659
+ . with_body_and_content_length ( writer. into_inner ( ) )
660
+ . build ( ) ,
661
+ Err ( err) => {
662
+ HttpResponseBuilder :: server_error ( format ! ( "Failed to encode metrics: {}" , err) )
663
+ . build ( )
664
+ }
665
+ }
666
+ } else {
667
+ HttpResponseBuilder :: not_found ( ) . build ( )
668
+ }
669
+ }
670
+
671
+ pub fn encode_metrics ( w : & mut ic_metrics_encoder:: MetricsEncoder < Vec < u8 > > ) -> std:: io:: Result < ( ) > {
672
+ w. encode_gauge (
673
+ "index_stable_memory_pages" ,
674
+ ic_cdk:: api:: stable:: stable_size ( ) as f64 ,
675
+ "Size of the stable memory allocated by this canister measured in 64K Wasm pages." ,
676
+ ) ?;
677
+ w. encode_gauge (
678
+ "index_stable_memory_bytes" ,
679
+ ( ic_cdk:: api:: stable:: stable_size ( ) * 64 * 1024 ) as f64 ,
680
+ "Size of the stable memory allocated by this canister." ,
681
+ ) ?;
682
+
683
+ let cycle_balance = ic_cdk:: api:: canister_balance128 ( ) as f64 ;
684
+ w. encode_gauge (
685
+ "index_cycle_balance" ,
686
+ cycle_balance,
687
+ "Cycle balance on this canister." ,
688
+ ) ?;
689
+ w. gauge_vec ( "cycle_balance" , "Cycle balance on this canister." ) ?
690
+ . value ( & [ ( "canister" , "icrc1-index" ) ] , cycle_balance) ?;
691
+
692
+ w. encode_gauge (
693
+ "index_number_of_blocks" ,
694
+ with_blocks ( |blocks| blocks. len ( ) ) as f64 ,
695
+ "Total number of blocks stored in the stable memory." ,
696
+ ) ?;
697
+ w. encode_gauge (
698
+ "index_last_wait_time" ,
699
+ with_state ( |state| state. last_wait_time )
700
+ . as_nanos ( )
701
+ . min ( f64:: MAX as u128 ) as f64 ,
702
+ "Last amount of time waited between two transactions fetch." ,
703
+ ) ?;
704
+ Ok ( ( ) )
705
+ }
706
+
643
707
fn main ( ) { }
644
708
645
709
#[ cfg( test) ]
0 commit comments