Skip to content

Commit 2a21c66

Browse files
vishalbolludeliahu
authored andcommitted
Refresh logger after loading user module (#563)
* Refresh logs after loading modules and calling init functions * Fix ONNX import * Create loggers at nanotime (cherry picked from commit 01808ed)
1 parent 4672ead commit 2a21c66

File tree

8 files changed

+89
-82
lines changed

8 files changed

+89
-82
lines changed

pkg/workloads/cortex/downloader/download.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919

2020
from cortex.lib import util
2121
from cortex.lib.storage import S3
22-
from cortex.lib.log import get_logger
23-
24-
logger = get_logger()
22+
from cortex.lib.log import cx_logger
2523

2624

2725
def start(args):
@@ -34,12 +32,12 @@ def start(args):
3432
s3_client = S3(bucket_name, client_config={})
3533

3634
if item_name != "":
37-
logger.info("downloading {} from {}".format(item_name, from_path))
35+
cx_logger().info("downloading {} from {}".format(item_name, from_path))
3836
s3_client.download(prefix, to_path)
3937

4038
if download_arg.get("unzip", False):
4139
if item_name != "":
42-
logger.info("unzipping {}".format(item_name))
40+
cx_logger().info("unzipping {}".format(item_name))
4341
util.extract_zip(
4442
os.path.join(to_path, os.path.basename(from_path)), delete_zip_file=True
4543
)

pkg/workloads/cortex/lib/api_utils.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818
import time
1919

2020
from cortex.lib.exceptions import UserException, CortexException
21-
from cortex.lib.log import get_logger
22-
23-
logger = get_logger()
21+
from cortex.lib.log import cx_logger
2422

2523

2624
def get_classes(ctx, api_name):
@@ -157,10 +155,10 @@ def post_request_metrics(ctx, api, response, prediction_payload, start_time, cla
157155

158156
metrics_list += prediction_metrics(api_dimensions, api, prediction)
159157
except Exception as e:
160-
logger.warn("unable to record prediction metric", exc_info=True)
158+
cx_logger().warn("unable to record prediction metric", exc_info=True)
161159

162160
metrics_list += latency_metric(api_dimensions, start_time)
163161
try:
164162
ctx.publish_metrics(metrics_list)
165163
except Exception as e:
166-
logger.warn("failure encountered while publishing metrics", exc_info=True)
164+
cx_logger().warn("failure encountered while publishing metrics", exc_info=True)

pkg/workloads/cortex/lib/context.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,10 @@
2222

2323
from cortex import consts
2424
from cortex.lib import util
25+
from cortex.lib.log import refresh_logger
2526
from cortex.lib.storage import S3, LocalStorage
2627
from cortex.lib.exceptions import CortexException, UserException
2728
from cortex.lib.resources import ResourceMap
28-
from cortex.lib.log import get_logger
29-
30-
logger = get_logger()
3129

3230

3331
class Context:
@@ -149,6 +147,8 @@ def get_request_handler_impl(self, api_name, project_dir):
149147
except CortexException as e:
150148
e.wrap("api " + api_name, "failed to load request_handler", request_handler_path)
151149
raise
150+
finally:
151+
refresh_logger()
152152

153153
try:
154154
_validate_impl(impl, REQUEST_HANDLER_IMPL_VALIDATION)
@@ -163,9 +163,12 @@ def get_predictor_impl(self, api_name, project_dir):
163163
impl = self.load_module(
164164
"predictor", api["name"], os.path.join(project_dir, api["predictor"]["path"])
165165
)
166+
166167
except CortexException as e:
167168
e.wrap("api " + api_name, "failed to load predictor", api["predictor"]["path"])
168169
raise
170+
finally:
171+
refresh_logger()
169172

170173
try:
171174
_validate_impl(impl, PREDICTOR_IMPL_VALIDATION)

pkg/workloads/cortex/lib/log.py

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import logging
1616
import sys
17+
import time
1718

1819
from cortex.lib import stringify
1920
import datetime as dt
@@ -28,23 +29,39 @@ def formatTime(self, record, datefmt):
2829
return s
2930

3031

31-
logger = logging.getLogger("cortex")
32-
handler = logging.StreamHandler(stream=sys.stdout)
33-
formatter = MyFormatter(
34-
fmt="%(asctime)s:%(name)s:%(levelname)s:%(message)s", datefmt="%Y-%m-%d %H:%M:%S.%f"
35-
)
36-
handler.setFormatter(formatter)
32+
current_logger = None
3733

38-
logger.addHandler(handler)
39-
logger.setLevel(logging.DEBUG)
34+
35+
def register_logger(name):
36+
logger = logging.getLogger(name)
37+
handler = logging.StreamHandler(stream=sys.stdout)
38+
formatter = MyFormatter(
39+
fmt="%(asctime)s:cortex:%(levelname)s:%(message)s", datefmt="%Y-%m-%d %H:%M:%S.%f"
40+
)
41+
handler.setFormatter(formatter)
42+
43+
logger.propagate = False
44+
logger.addHandler(handler)
45+
logger.setLevel(logging.DEBUG)
46+
return logger
47+
48+
49+
def refresh_logger():
50+
global current_logger
51+
if current_logger is not None:
52+
current_logger.disabled = True
53+
current_logger = register_logger("{}-cortex".format(int(time.time() * 1000000)))
54+
55+
56+
def cx_logger():
57+
return current_logger
4058

4159

4260
def debug_obj(name, sample, debug):
4361
if not debug:
4462
return
4563

46-
logger.info("{}: {}".format(name, stringify.truncate(sample)))
64+
cx_logger().info("{}: {}".format(name, stringify.truncate(sample)))
4765

4866

49-
def get_logger():
50-
return logging.getLogger("cortex")
67+
refresh_logger()

pkg/workloads/cortex/lib/util.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,10 @@
2727
from copy import deepcopy
2828
from datetime import datetime
2929

30-
from cortex.lib.log import get_logger
3130
from cortex.lib import stringify
3231
import json_tricks
3332

3433

35-
logger = get_logger()
36-
37-
3834
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
3935
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
4036

pkg/workloads/cortex/onnx_serve/api.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@
2424
import numpy as np
2525

2626
from cortex.lib import util, Context, api_utils
27-
from cortex.lib.log import get_logger, debug_obj
27+
from cortex.lib.log import cx_logger, debug_obj
2828
from cortex.lib.exceptions import CortexException, UserRuntimeException, UserException
2929
from cortex.lib.stringify import truncate
3030

31-
logger = get_logger()
32-
logger.propagate = False # prevent double logging (flask modifies root logger)
33-
3431
app = Flask(__name__)
3532

3633
app.json_encoder = util.json_tricks_encoder
@@ -79,7 +76,7 @@ def after_request(response):
7976
api = local_cache["api"]
8077
ctx = local_cache["ctx"]
8178

82-
logger.info(response.status)
79+
cx_logger().info(response.status)
8380

8481
prediction = None
8582
if "prediction" in g:
@@ -94,7 +91,7 @@ def after_request(response):
9491

9592
def prediction_failed(reason):
9693
message = "prediction failed: {}".format(reason)
97-
logger.error(message)
94+
cx_logger().error(message)
9895
return message, status.HTTP_406_NOT_ACCEPTABLE
9996

10097

@@ -215,7 +212,7 @@ def predict():
215212

216213
debug_obj("post_inference", result, debug)
217214
except Exception as e:
218-
logger.exception("prediction failed")
215+
cx_logger().exception("prediction failed")
219216
return prediction_failed(str(e))
220217

221218
g.prediction = result
@@ -238,7 +235,7 @@ def get_signature():
238235

239236
@app.errorhandler(Exception)
240237
def exceptions(e):
241-
logger.exception(e)
238+
cx_logger().exception(e)
242239
return jsonify(error=str(e)), 500
243240

244241

@@ -262,45 +259,45 @@ def start(args):
262259
request_handler = local_cache.get("request_handler")
263260

264261
if request_handler is not None and util.has_function(request_handler, "pre_inference"):
265-
logger.info(
262+
cx_logger().info(
266263
"using pre_inference request handler provided in {}".format(
267264
api["onnx"]["request_handler"]
268265
)
269266
)
270267
else:
271-
logger.info("pre_inference request handler not found")
268+
cx_logger().info("pre_inference request handler not found")
272269

273270
if request_handler is not None and util.has_function(request_handler, "post_inference"):
274-
logger.info(
271+
cx_logger().info(
275272
"using post_inference request handler provided in {}".format(
276273
api["onnx"]["request_handler"]
277274
)
278275
)
279276
else:
280-
logger.info("post_inference request handler not found")
277+
cx_logger().info("post_inference request handler not found")
281278

282279
sess = rt.InferenceSession(model_path)
283280
local_cache["sess"] = sess
284281
local_cache["input_metadata"] = sess.get_inputs()
285-
logger.info(
282+
cx_logger().info(
286283
"input_metadata: {}".format(truncate(extract_signature(local_cache["input_metadata"])))
287284
)
288285
local_cache["output_metadata"] = sess.get_outputs()
289-
logger.info(
286+
cx_logger().info(
290287
"output_metadata: {}".format(
291288
truncate(extract_signature(local_cache["output_metadata"]))
292289
)
293290
)
294291

295292
except Exception as e:
296-
logger.exception("failed to start api")
293+
cx_logger().exception("failed to start api")
297294
sys.exit(1)
298295

299296
if api.get("tracker") is not None and api["tracker"].get("model_type") == "classification":
300297
try:
301298
local_cache["class_set"] = api_utils.get_classes(ctx, api["name"])
302299
except Exception as e:
303-
logger.warn("an error occurred while attempting to load classes", exc_info=True)
300+
cx_logger().warn("an error occurred while attempting to load classes", exc_info=True)
304301

305302
serve(app, listen="*:{}".format(args.port))
306303

pkg/workloads/cortex/predictor_serve/api.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,9 @@
2222
from waitress import serve
2323

2424
from cortex.lib import util, Context, api_utils
25-
from cortex.lib.log import get_logger, debug_obj
25+
from cortex.lib.log import cx_logger, debug_obj, refresh_logger
2626
from cortex.lib.exceptions import CortexException, UserRuntimeException
2727

28-
logger = get_logger()
29-
logger.propagate = False # prevent double logging (flask modifies root logger)
30-
3128
app = Flask(__name__)
3229

3330
app.json_encoder = util.json_tricks_encoder
@@ -51,7 +48,7 @@ def after_request(response):
5148
api = local_cache["api"]
5249
ctx = local_cache["ctx"]
5350

54-
logger.info(response.status)
51+
cx_logger().info(response.status)
5552

5653
prediction = None
5754
if "prediction" in g:
@@ -66,7 +63,7 @@ def after_request(response):
6663

6764
def prediction_failed(reason):
6865
message = "prediction failed: {}".format(reason)
69-
logger.error(message)
66+
cx_logger().error(message)
7067
return message, status.HTTP_406_NOT_ACCEPTABLE
7168

7269

@@ -95,7 +92,7 @@ def predict():
9592
except Exception as e:
9693
raise UserRuntimeException(api["predictor"]["path"], "predict", str(e)) from e
9794
except Exception as e:
98-
logger.exception("prediction failed")
95+
cx_logger().exception("prediction failed")
9996
return prediction_failed(str(e))
10097

10198
g.prediction = output
@@ -104,7 +101,7 @@ def predict():
104101

105102
@app.errorhandler(Exception)
106103
def exceptions(e):
107-
logger.exception(e)
104+
cx_logger().exception(e)
108105
return jsonify(error=str(e)), 500
109106

110107

@@ -133,16 +130,18 @@ def start(args):
133130
local_cache["predictor"].init(model_path, api["predictor"]["metadata"])
134131
except Exception as e:
135132
raise UserRuntimeException(api["predictor"]["path"], "init", str(e)) from e
136-
logger.info("init ran successfully")
133+
finally:
134+
refresh_logger()
137135
except:
138-
logger.exception("failed to start api")
136+
cx_logger().exception("failed to start api")
139137
sys.exit(1)
140138

139+
cx_logger().info("init ran successfully")
141140
if api.get("tracker") is not None and api["tracker"].get("model_type") == "classification":
142141
try:
143142
local_cache["class_set"] = api_utils.get_classes(ctx, api["name"])
144143
except Exception as e:
145-
logger.warn("an error occurred while attempting to load classes", exc_info=True)
144+
cx_logger().warn("an error occurred while attempting to load classes", exc_info=True)
146145

147146
serve(app, listen="*:{}".format(args.port))
148147

0 commit comments

Comments
 (0)