40
40
import tempfile
41
41
import textwrap
42
42
import threading
43
+ import time
43
44
import typing
44
45
import urllib
46
+ import uuid
45
47
import zipfile
46
48
import zipimport
47
49
from types import ModuleType
69
71
from ..signature import signature_to_sql
70
72
from ..typing import Masked
71
73
from ..typing import Table
74
+ from .timer import Timer
72
75
73
76
try :
74
77
import cloudpickle
@@ -613,6 +616,16 @@ def cancel_all_tasks(tasks: Iterable[asyncio.Task[Any]]) -> None:
613
616
pass
614
617
615
618
619
+ def start_counter () -> float :
620
+ """Start a timer and return the start time."""
621
+ return time .perf_counter ()
622
+
623
+
624
+ def end_counter (start : float ) -> float :
625
+ """End a timer and return the elapsed time."""
626
+ return time .perf_counter () - start
627
+
628
+
616
629
class Application (object ):
617
630
"""
618
631
Create an external function application.
@@ -939,6 +952,8 @@ async def __call__(
939
952
Function to send response information
940
953
941
954
'''
955
+ timer = Timer (id = str (uuid .uuid4 ()), timestamp = time .time ())
956
+
942
957
assert scope ['type' ] == 'http'
943
958
944
959
method = scope ['method' ]
@@ -964,12 +979,13 @@ async def __call__(
964
979
returns_data_format = func_info ['returns_data_format' ]
965
980
data = []
966
981
more_body = True
967
- while more_body :
968
- request = await receive ()
969
- if request ['type' ] == 'http.disconnect' :
970
- raise RuntimeError ('client disconnected' )
971
- data .append (request ['body' ])
972
- more_body = request .get ('more_body' , False )
982
+ with timer ('receive_data' ):
983
+ while more_body :
984
+ request = await receive ()
985
+ if request ['type' ] == 'http.disconnect' :
986
+ raise RuntimeError ('client disconnected' )
987
+ data .append (request ['body' ])
988
+ more_body = request .get ('more_body' , False )
973
989
974
990
data_version = headers .get (b's2-ef-version' , b'' )
975
991
input_handler = self .handlers [(content_type , data_version , args_data_format )]
@@ -981,17 +997,17 @@ async def __call__(
981
997
982
998
cancel_event = threading .Event ()
983
999
984
- func_args = [
985
- cancel_event ,
986
- * input_handler ['load' ]( # type: ignore
1000
+ with timer ('parse_input' ):
1001
+ inputs = input_handler ['load' ]( # type: ignore
987
1002
func_info ['colspec' ], b'' .join (data ),
988
- ),
989
- ]
1003
+ )
990
1004
991
1005
func_task = asyncio .create_task (
992
- func (* func_args )
1006
+ func (cancel_event , * inputs )
993
1007
if func_info ['is_async' ]
994
- else to_thread (lambda : asyncio .run (func (* func_args ))),
1008
+ else to_thread (
1009
+ lambda : asyncio .run (func (cancel_event , * inputs )),
1010
+ ),
995
1011
)
996
1012
disconnect_task = asyncio .create_task (
997
1013
cancel_on_disconnect (receive ),
@@ -1002,9 +1018,10 @@ async def __call__(
1002
1018
1003
1019
all_tasks += [func_task , disconnect_task , timeout_task ]
1004
1020
1005
- done , pending = await asyncio .wait (
1006
- all_tasks , return_when = asyncio .FIRST_COMPLETED ,
1007
- )
1021
+ with timer ('function_call' ):
1022
+ done , pending = await asyncio .wait (
1023
+ all_tasks , return_when = asyncio .FIRST_COMPLETED ,
1024
+ )
1008
1025
1009
1026
cancel_all_tasks (pending )
1010
1027
@@ -1024,9 +1041,10 @@ async def __call__(
1024
1041
elif task is func_task :
1025
1042
result .extend (task .result ())
1026
1043
1027
- body = output_handler ['dump' ](
1028
- [x [1 ] for x in func_info ['returns' ]], * result , # type: ignore
1029
- )
1044
+ with timer ('format_output' ):
1045
+ body = output_handler ['dump' ](
1046
+ [x [1 ] for x in func_info ['returns' ]], * result , # type: ignore
1047
+ )
1030
1048
1031
1049
await send (output_handler ['response' ])
1032
1050
@@ -1089,9 +1107,14 @@ async def __call__(
1089
1107
await send (self .path_not_found_response_dict )
1090
1108
1091
1109
# Send body
1092
- out = self .body_response_dict .copy ()
1093
- out ['body' ] = body
1094
- await send (out )
1110
+ with timer ('send_response' ):
1111
+ out = self .body_response_dict .copy ()
1112
+ out ['body' ] = body
1113
+ await send (out )
1114
+
1115
+ timer .metadata ['function' ] = func_name .decode ('utf-8' ) if func_name else ''
1116
+ timer .finish ()
1117
+ timer .log_metrics ()
1095
1118
1096
1119
def _create_link (
1097
1120
self ,
0 commit comments