@@ -699,9 +699,39 @@ Dash <- R6::R6Class(
699
699
if (is.null(private $ callback_context_ )) {
700
700
warning(" callback_context is undefined; callback_context may only be accessed within a callback." )
701
701
}
702
+
702
703
private $ callback_context_
703
704
},
704
705
706
+ # ------------------------------------------------------------------------
707
+ # request and return callback timing data
708
+ # ------------------------------------------------------------------------
709
+ # ' @description
710
+ # ' Records timing information for a server resource.
711
+ # ' @details
712
+ # ' The `callback_context.record_timing` method permits retrieving the
713
+ # ' duration required to execute a given callback.
714
+ # '
715
+ # ' @param name Character. The name of the resource.
716
+ # ' @param duration Numeric. The time in seconds to report. Internally, this is
717
+ # ' rounded to the nearest millisecond.
718
+ # ' @param description Character. A description of the resource.
719
+ # '
720
+ callback_context.record_timing = function (name ,
721
+ duration = NULL ,
722
+ description = NULL ) {
723
+ timing_information <- self $ server $ get_data(" timing-information" )
724
+
725
+ if (name %in% timing_information ) {
726
+ stop(paste0(" Duplicate resource name " , name , " found." ), call. = FALSE )
727
+ }
728
+
729
+ timing_information [[name ]] <- list (" dur" = round(duration * 1000 ),
730
+ " desc" = description )
731
+
732
+ self $ server $ set_data(" timing-information" , timing_information )
733
+ },
734
+
705
735
# ------------------------------------------------------------------------
706
736
# return asset URLs
707
737
# ------------------------------------------------------------------------
@@ -1056,6 +1086,34 @@ Dash <- R6::R6Class(
1056
1086
self $ config $ silence_routes_logging <- dev_tools_silence_routes_logging
1057
1087
self $ config $ props_check <- dev_tools_props_check
1058
1088
1089
+ if (private $ debug && self $ config $ ui ) {
1090
+ self $ server $ on(' before-request' , function (server , ... ) {
1091
+ self $ server $ set_data(" timing_information" , list (
1092
+ " __dash_server" = list (
1093
+ " dur" = as.numeric(Sys.time()),
1094
+ " desc" = NULL
1095
+ )
1096
+ ))
1097
+ })
1098
+
1099
+ self $ server $ on(' after-request' , function (server , response , ... ) {
1100
+ dash_total <- self $ server $ get_data(" timing-information" )[[" __dash_server" ]]
1101
+ dash_total [[" dur" ]] <- round(as.numeric(Sys.time()- dash_total [[" dur" ]]) * 1000 )
1102
+
1103
+ for (item in seq_along(timing_information )) {
1104
+ id <- names(timing_information [item ])
1105
+
1106
+ if (! is.null(timing_information [[item ]]$ desc )) {
1107
+ response $ append_header(" Server-Timing" , paste0(id , " ;desc=" , timing_information [[item ]]$ desc ))
1108
+ }
1109
+
1110
+ if (! is.null(timing_information [[item ]]$ desc )) {
1111
+ response $ append_header(" Server-Timing" , paste0(id , " ;dur=" , timing_information [[item ]]$ dur ))
1112
+ }
1113
+ }
1114
+ })
1115
+ }
1116
+
1059
1117
if (hot_reload == TRUE & ! (is.null(source_dir ))) {
1060
1118
self $ server $ on(' cycle-end' , function (server , ... ) {
1061
1119
# handle case where assets are not present, since we can still hot reload the app itself
0 commit comments