1
1
import json
2
2
import time
3
- from datetime import datetime
3
+ from datetime import datetime , timedelta
4
4
5
5
from roboflow .adapters import deploymentapi
6
6
from roboflow .config import load_roboflow_api_key
@@ -19,6 +19,7 @@ def add_deployment_parser(subparsers):
19
19
)
20
20
deployment_list_parser = deployment_subparsers .add_parser ("list" , help = "list dedicated deployments in a workspace" )
21
21
deployment_delete_parser = deployment_subparsers .add_parser ("delete" , help = "delete a dedicated deployment" )
22
+ deployment_log_parser = deployment_subparsers .add_parser ("log" , help = "show log info for a dedicated deployment" )
22
23
23
24
deployment_machine_type_parser .set_defaults (func = list_machine_types )
24
25
deployment_machine_type_parser .add_argument ("-a" , "--api_key" , help = "api key" )
@@ -69,24 +70,35 @@ def add_deployment_parser(subparsers):
69
70
deployment_delete_parser .add_argument ("-a" , "--api_key" , help = "api key" )
70
71
deployment_delete_parser .add_argument ("deployment_name" , help = "deployment name" )
71
72
73
+ deployment_log_parser .set_defaults (func = get_deployment_log )
74
+ deployment_log_parser .add_argument ("-a" , "--api_key" , help = "api key" )
75
+ deployment_log_parser .add_argument ("deployment_name" , help = "deployment name" )
76
+ deployment_log_parser .add_argument (
77
+ "-d" , "--duration" , help = "duration of log (from now) in seconds" , type = int , default = 3600
78
+ )
79
+ deployment_log_parser .add_argument (
80
+ "-n" , "--tail" , help = "number of lines to show from the end of the logs (<= 50)" , type = int , default = 10
81
+ )
82
+ deployment_log_parser .add_argument ("-f" , "--follow" , help = "follow log output" , action = "store_true" )
83
+
72
84
73
85
def list_machine_types (args ):
74
86
api_key = args .api_key or load_roboflow_api_key (None )
75
87
if api_key is None :
76
88
print ("Please provide an api key" )
77
- return
89
+ exit ( 1 )
78
90
status_code , msg = deploymentapi .list_machine_types (api_key )
79
91
if status_code != 200 :
80
92
print (f"{ status_code } : { msg } " )
81
- return
93
+ exit ( status_code )
82
94
print (json .dumps (msg , indent = 2 ))
83
95
84
96
85
97
def add_deployment (args ):
86
98
api_key = args .api_key or load_roboflow_api_key (None )
87
99
if api_key is None :
88
100
print ("Please provide an api key" )
89
- return
101
+ exit ( 1 )
90
102
status_code , msg = deploymentapi .add_deployment (
91
103
api_key ,
92
104
# args.security_level,
@@ -99,7 +111,7 @@ def add_deployment(args):
99
111
100
112
if status_code != 200 :
101
113
print (f"{ status_code } : { msg } " )
102
- return
114
+ exit ( status_code )
103
115
else :
104
116
print (f"Deployment { args .deployment_name } created successfully" )
105
117
print (json .dumps (msg , indent = 2 ))
@@ -112,12 +124,12 @@ def get_deployment(args):
112
124
api_key = args .api_key or load_roboflow_api_key (None )
113
125
if api_key is None :
114
126
print ("Please provide an api key" )
115
- return
127
+ exit ( 1 )
116
128
while True :
117
129
status_code , msg = deploymentapi .get_deployment (api_key , args .deployment_name )
118
130
if status_code != 200 :
119
131
print (f"{ status_code } : { msg } " )
120
- return
132
+ exit ( status_code )
121
133
122
134
if (not args .wait_on_pending ) or msg ["status" ] != "pending" :
123
135
print (json .dumps (msg , indent = 2 ))
@@ -131,21 +143,57 @@ def list_deployment(args):
131
143
api_key = args .api_key or load_roboflow_api_key (None )
132
144
if api_key is None :
133
145
print ("Please provide an api key" )
134
- return
146
+ exit ( 1 )
135
147
status_code , msg = deploymentapi .list_deployment (api_key )
136
148
if status_code != 200 :
137
149
print (f"{ status_code } : { msg } " )
138
- return
150
+ exit ( status_code )
139
151
print (json .dumps (msg , indent = 2 ))
140
152
141
153
142
154
def delete_deployment (args ):
143
155
api_key = args .api_key or load_roboflow_api_key (None )
144
156
if api_key is None :
145
157
print ("Please provide an api key" )
146
- return
158
+ exit ( 1 )
147
159
status_code , msg = deploymentapi .delete_deployment (api_key , args .deployment_name )
148
160
if status_code != 200 :
149
161
print (f"{ status_code } : { msg } " )
150
- return
162
+ exit ( status_code )
151
163
print (json .dumps (msg , indent = 2 ))
164
+
165
+
166
+ def get_deployment_log (args ):
167
+ api_key = args .api_key or load_roboflow_api_key (None )
168
+ if api_key is None :
169
+ print ("Please provide an api key" )
170
+ exit (1 )
171
+
172
+ to_timestamp = datetime .now ()
173
+ from_timestamp = to_timestamp - timedelta (seconds = args .duration )
174
+ last_log_timestamp = from_timestamp
175
+ log_ids = set () # to avoid duplicate logs
176
+ max_entries = args .tail
177
+ while True :
178
+ status_code , msg = deploymentapi .get_deployment_log (
179
+ api_key , args .deployment_name , from_timestamp , to_timestamp , max_entries
180
+ )
181
+ if status_code != 200 :
182
+ print (f"{ status_code } : { msg } " )
183
+ exit (status_code )
184
+
185
+ for log in msg [::- 1 ]: # logs are sorted by reversed timestamp
186
+ log_timestamp = datetime .fromisoformat (log ["timestamp" ]).replace (tzinfo = None )
187
+ if (log ["insert_id" ] in log_ids ) or (log_timestamp < last_log_timestamp ):
188
+ continue
189
+ log_ids .add (log ["insert_id" ])
190
+ last_log_timestamp = log_timestamp
191
+ print (f'[{ log_timestamp .strftime ("%Y-%m-%d %H:%M:%S.%f" )} ] { log ["payload" ]} ' )
192
+
193
+ if not args .follow :
194
+ break
195
+
196
+ time .sleep (10 )
197
+ from_timestamp = last_log_timestamp
198
+ to_timestamp = datetime .now ()
199
+ max_entries = 300 # only set max_entries for the first request
0 commit comments