Skip to content

Commit 0d6b37d

Browse files
authored
Merge pull request #335 from roboflow/dedicated-deployment-add-log
Add log support for dedicated deployment
2 parents 7fe28e5 + c0664b6 commit 0d6b37d

File tree

2 files changed

+73
-11
lines changed

2 files changed

+73
-11
lines changed

roboflow/adapters/deploymentapi.py

+14
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,17 @@ def list_machine_types(api_key):
5555
if response.status_code != 200:
5656
return response.status_code, response.text
5757
return response.status_code, response.json()
58+
59+
60+
def get_deployment_log(api_key, deployment_name, from_timestamp=None, to_timestamp=None, max_entries=-1):
61+
url = f"{DEDICATED_DEPLOYMENT_URL}/get_log?api_key={api_key}&deployment_name={deployment_name}"
62+
if from_timestamp is not None:
63+
url += f"&from_timestamp={from_timestamp.isoformat()}"
64+
if to_timestamp is not None:
65+
url += f"&to_timestamp={to_timestamp.isoformat()}"
66+
if max_entries > 0:
67+
url += f"&max_entries={max_entries}"
68+
response = requests.get(url)
69+
if response.status_code != 200:
70+
return response.status_code, response.text
71+
return response.status_code, response.json()

roboflow/deployment.py

+59-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
import time
3-
from datetime import datetime
3+
from datetime import datetime, timedelta
44

55
from roboflow.adapters import deploymentapi
66
from roboflow.config import load_roboflow_api_key
@@ -19,6 +19,7 @@ def add_deployment_parser(subparsers):
1919
)
2020
deployment_list_parser = deployment_subparsers.add_parser("list", help="list dedicated deployments in a workspace")
2121
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")
2223

2324
deployment_machine_type_parser.set_defaults(func=list_machine_types)
2425
deployment_machine_type_parser.add_argument("-a", "--api_key", help="api key")
@@ -69,24 +70,35 @@ def add_deployment_parser(subparsers):
6970
deployment_delete_parser.add_argument("-a", "--api_key", help="api key")
7071
deployment_delete_parser.add_argument("deployment_name", help="deployment name")
7172

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+
7284

7385
def list_machine_types(args):
7486
api_key = args.api_key or load_roboflow_api_key(None)
7587
if api_key is None:
7688
print("Please provide an api key")
77-
return
89+
exit(1)
7890
status_code, msg = deploymentapi.list_machine_types(api_key)
7991
if status_code != 200:
8092
print(f"{status_code}: {msg}")
81-
return
93+
exit(status_code)
8294
print(json.dumps(msg, indent=2))
8395

8496

8597
def add_deployment(args):
8698
api_key = args.api_key or load_roboflow_api_key(None)
8799
if api_key is None:
88100
print("Please provide an api key")
89-
return
101+
exit(1)
90102
status_code, msg = deploymentapi.add_deployment(
91103
api_key,
92104
# args.security_level,
@@ -99,7 +111,7 @@ def add_deployment(args):
99111

100112
if status_code != 200:
101113
print(f"{status_code}: {msg}")
102-
return
114+
exit(status_code)
103115
else:
104116
print(f"Deployment {args.deployment_name} created successfully")
105117
print(json.dumps(msg, indent=2))
@@ -112,12 +124,12 @@ def get_deployment(args):
112124
api_key = args.api_key or load_roboflow_api_key(None)
113125
if api_key is None:
114126
print("Please provide an api key")
115-
return
127+
exit(1)
116128
while True:
117129
status_code, msg = deploymentapi.get_deployment(api_key, args.deployment_name)
118130
if status_code != 200:
119131
print(f"{status_code}: {msg}")
120-
return
132+
exit(status_code)
121133

122134
if (not args.wait_on_pending) or msg["status"] != "pending":
123135
print(json.dumps(msg, indent=2))
@@ -131,21 +143,57 @@ def list_deployment(args):
131143
api_key = args.api_key or load_roboflow_api_key(None)
132144
if api_key is None:
133145
print("Please provide an api key")
134-
return
146+
exit(1)
135147
status_code, msg = deploymentapi.list_deployment(api_key)
136148
if status_code != 200:
137149
print(f"{status_code}: {msg}")
138-
return
150+
exit(status_code)
139151
print(json.dumps(msg, indent=2))
140152

141153

142154
def delete_deployment(args):
143155
api_key = args.api_key or load_roboflow_api_key(None)
144156
if api_key is None:
145157
print("Please provide an api key")
146-
return
158+
exit(1)
147159
status_code, msg = deploymentapi.delete_deployment(api_key, args.deployment_name)
148160
if status_code != 200:
149161
print(f"{status_code}: {msg}")
150-
return
162+
exit(status_code)
151163
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

Comments
 (0)