Skip to content

Commit c53781c

Browse files
authored
Merge pull request #41 from yxd-hde/fix-log
Fix log
2 parents 2de2a72 + 0e4b5db commit c53781c

File tree

4 files changed

+88
-56
lines changed

4 files changed

+88
-56
lines changed

lambda_local/__init__.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@
1919

2020
def main():
2121
args = parse_args()
22-
23-
p = Process(target=run, args=(args,))
24-
p.start()
25-
p.join()
26-
27-
sys.exit(p.exitcode)
22+
run(args)
2823

2924

3025
def parse_args():

lambda_local/context.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,47 @@
22
Copyright 2015-2018 HDE, Inc.
33
Licensed under MIT.
44
'''
5+
from __future__ import print_function
56

67
from datetime import datetime
78
from datetime import timedelta
9+
import uuid
810

911

1012
class Context(object):
11-
def __init__(self, timeout, arn_string, version_name):
12-
self.function_name = "undefined"
13-
self.function_version = version_name
14-
self.invoked_function_arn = arn_string
15-
self.memory_limit_in_mb = 0
16-
self.aws_request_id = "undefined"
17-
self.log_group_name = "undefined"
18-
self.log_stream_name = "undefined"
19-
self.identity = None
20-
self.client_context = None
21-
self.timeout = timeout
22-
self.duration = timedelta(seconds=timeout)
13+
def __init__(self, timeout_in_seconds,
14+
aws_request_id=uuid.uuid4(),
15+
function_name="undefined",
16+
function_version="$LATEST",
17+
log_group_name="undefined",
18+
log_stream_name="undefined",
19+
invoked_function_arn="undefined",
20+
memory_limit_in_mb='0',
21+
client_context=None,
22+
identity=None):
23+
self.function_name = function_name
24+
self.function_version = function_version
25+
self.invoked_function_arn = invoked_function_arn
26+
self.memory_limit_in_mb = memory_limit_in_mb
27+
self.aws_request_id = aws_request_id
28+
self.log_group_name = log_group_name
29+
self.log_stream_name = log_stream_name
30+
self.identity = identity
31+
self.client_context = client_context
32+
33+
self._timeout_in_seconds = timeout_in_seconds
34+
self._duration = timedelta(seconds=timeout_in_seconds)
2335

2436
def get_remaining_time_in_millis(self):
25-
if self.timelimit is None:
37+
if self._timelimit is None:
2638
raise Exception("Context not activated.")
27-
return millis_interval(datetime.now(), self.timelimit)
39+
return millis_interval(datetime.now(), self._timelimit)
40+
41+
def log(self, msg):
42+
print(msg)
2843

29-
def activate(self):
30-
self.timelimit = datetime.now() + self.duration
44+
def _activate(self):
45+
self._timelimit = datetime.now() + self._duration
3146
return self
3247

3348

lambda_local/main.py

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
import traceback
99
import json
1010
import logging
11-
import uuid
1211
import os
1312
import timeit
1413
from botocore.vendored.requests.packages import urllib3
14+
import multiprocessing
1515

1616
from . import event
1717
from . import context
@@ -31,57 +31,65 @@
3131
EXITCODE_ERR = 1
3232

3333

34-
def call(func, event, timeout, environment_variables={}, arn_string="", version_name="", library=None):
34+
class ContextFilter(logging.Filter):
35+
def __init__(self, context):
36+
super(ContextFilter, self).__init__()
37+
self.context = context
38+
39+
def filter(self, record):
40+
record.aws_request_id = self.context.aws_request_id
41+
return True
42+
43+
44+
def call(func, event, context, environment_variables={}):
3545
export_variables(environment_variables)
36-
e = json.loads(event)
37-
c = context.Context(timeout, arn_string, version_name)
38-
if library is not None:
39-
load_lib(library)
40-
request_id = uuid.uuid4()
4146

42-
return _runner(request_id, e, c, func)
47+
return _runner(func, event, context)
4348

4449

4550
def run(args):
4651
# set env vars if path to json file was given
4752
set_environment_variables(args.environment_variables)
4853

4954
e = event.read_event(args.event)
50-
c = context.Context(args.timeout, args.arn_string, args.version_name)
55+
c = context.Context(
56+
args.timeout,
57+
invoked_function_arn=args.arn_string,
58+
function_version=args.version_name)
5159
if args.library is not None:
5260
load_lib(args.library)
53-
request_id = uuid.uuid4()
54-
func = load(request_id, args.file, args.function)
55-
56-
(result, err_type) = _runner(request_id, e, c, func)
61+
func = load(c.aws_request_id, args.file, args.function)
62+
63+
(result, err_type) = _runner(func, e, c)
5764

5865
if err_type is not None:
5966
sys.exit(EXITCODE_ERR)
6067

6168

62-
def _runner(request_id, event, context, func):
69+
def _runner(func, event, context):
6370
logger = logging.getLogger()
64-
result = None
6571

6672
logger.info("Event: {}".format(event))
67-
68-
logger.info("START RequestId: {}".format(request_id))
69-
70-
start_time = timeit.default_timer()
71-
result, err_type = execute(func, event, context)
72-
end_time = timeit.default_timer()
73-
74-
logger.info("END RequestId: {}".format(request_id))
75-
73+
logger.info("START RequestId: {} Version: {}".format(
74+
context.aws_request_id, context.function_version))
75+
76+
queue = multiprocessing.Queue()
77+
p = multiprocessing.Process(
78+
target=execute_in_process,
79+
args=(queue, func, event, context,))
80+
p.start()
81+
(result, err_type, duration) = queue.get()
82+
p.join()
83+
84+
logger.info("END RequestId: {}".format(context.aws_request_id))
85+
duration = "{0:.2f} ms".format(duration)
86+
logger.info("REPORT RequestId: {}\tDuration: {}".format(
87+
context.aws_request_id, duration))
7688
if type(result) is TimeoutException:
7789
logger.error("RESULT:\n{}".format(result))
7890
else:
7991
logger.info("RESULT:\n{}".format(result))
8092

81-
duration = "{0:.2f} ms".format((end_time - start_time) * 1000)
82-
logger.info("REPORT RequestId: {}\tDuration: {}".format(
83-
request_id, duration))
84-
8593
return (result, err_type)
8694

8795

@@ -104,9 +112,13 @@ def load(request_id, path, function_name):
104112
def execute(func, event, context):
105113
err_type = None
106114

115+
logger = logging.getLogger()
116+
log_filter = ContextFilter(context)
117+
logger.addFilter(log_filter)
118+
107119
try:
108-
with time_limit(context.timeout):
109-
result = func(event, context.activate())
120+
with time_limit(context._timeout_in_seconds):
121+
result = func(event, context._activate())
110122
except TimeoutException as err:
111123
result = err
112124
err_type = ERR_TYPE_TIMEOUT
@@ -120,3 +132,12 @@ def execute(func, event, context):
120132
err_type = ERR_TYPE_EXCEPTION
121133

122134
return result, err_type
135+
136+
137+
def execute_in_process(queue, func, event, context):
138+
start_time = timeit.default_timer()
139+
result, err_type = execute(func, event, context)
140+
end_time = timeit.default_timer()
141+
duration = (end_time - start_time) * 1000
142+
143+
queue.put((result, err_type, duration))

tests/test_direct_invocations.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@
1313
import os
1414
from lambda_local.main import run as lambda_run
1515
from lambda_local.main import call as lambda_call
16+
from lambda_local.context import Context
1617

1718

1819
def my_lambda_function(event, context):
1920
print("Hello World from My Lambda Function!")
2021
return 42
2122

23+
2224
def test_function_call_for_pytest():
23-
request = json.dumps({})
24-
(result, error_type) = lambda_call(func=my_lambda_function, event=request, timeout=1)
25+
(result, error_type) = lambda_call(
26+
my_lambda_function, {}, Context(1))
2527

2628
assert error_type is None
2729

@@ -31,7 +33,7 @@ def test_function_call_for_pytest():
3133
def test_check_command_line():
3234
request = json.dumps({})
3335
request_file = 'check_command_line_event.json'
34-
with open (request_file, "w") as f:
36+
with open(request_file, "w") as f:
3537
f.write(request)
3638

3739
args = argparse.Namespace(event=request_file,
@@ -49,4 +51,3 @@ def test_check_command_line():
4951

5052
os.remove(request_file)
5153
assert p.exitcode == 0
52-

0 commit comments

Comments
 (0)