Skip to content

Commit c652338

Browse files
Allow this library to be used as a general parsing library (#268)
* move the tracer-specific logic into a well-marked module and don't run code in global time if not lambda * support ReceiveMessage trigger in sqs parser
1 parent 1b791b6 commit c652338

36 files changed

+720
-566
lines changed

.secrets.baseline

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@
115115
"filename": "src/lumigo_tracer/lumigo_utils.py",
116116
"hashed_secret": "116b0dcbb1dfb3f19c902ebfc29f35d908cec6a4",
117117
"is_verified": false,
118-
"line_number": 69
118+
"line_number": 48
119119
},
120120
{
121121
"type": "Secret Keyword",
122122
"filename": "src/lumigo_tracer/lumigo_utils.py",
123123
"hashed_secret": "2a93870f6e6a2158cb9631b349e75d8f65fd81af",
124124
"is_verified": false,
125-
"line_number": 70
125+
"line_number": 49
126126
}
127127
],
128128
"src/test/unit/event/test_event_dumper.py": [
@@ -168,14 +168,14 @@
168168
"filename": "src/test/unit/event/test_event_trigger.py",
169169
"hashed_secret": "885bb9903f72e004ff2974807b70e7c970d3e6d5",
170170
"is_verified": false,
171-
"line_number": 567
171+
"line_number": 612
172172
},
173173
{
174174
"type": "Hex High Entropy String",
175175
"filename": "src/test/unit/event/test_event_trigger.py",
176176
"hashed_secret": "3fae06dc55a618caed1d794dcd512bfe7e76c9f1",
177177
"is_verified": false,
178-
"line_number": 612
178+
"line_number": 657
179179
}
180180
],
181181
"src/test/unit/test_lumigo_utils.py": [
@@ -184,7 +184,7 @@
184184
"filename": "src/test/unit/test_lumigo_utils.py",
185185
"hashed_secret": "f32b67c7e26342af42efabc674d441dca0a281c5",
186186
"is_verified": false,
187-
"line_number": 263
187+
"line_number": 199
188188
}
189189
],
190190
"src/test/unit/test_tracer.py": [
@@ -220,5 +220,5 @@
220220
}
221221
]
222222
},
223-
"generated_at": "2022-11-08T16:26:37Z"
223+
"generated_at": "2023-01-22T10:15:06Z"
224224
}

src/lumigo_tracer/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .tracer import lumigo_tracer, LumigoChalice # noqa
1+
from lumigo_tracer.lambda_tracer.tracer import lumigo_tracer, LumigoChalice # noqa
22
from .user_utils import ( # noqa
33
report_error,
44
add_execution_tag,
@@ -9,3 +9,6 @@
99
error,
1010
)
1111
from .auto_instrument_handler import _handler # noqa
12+
from .lambda_tracer.global_scope_exec import global_scope_exec
13+
14+
global_scope_exec()

src/lumigo_tracer/auto_instrument_handler.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import os
22

3+
from lumigo_tracer.lumigo_utils import is_aws_environment
4+
35
try:
46
# Try to import AWS's current _get_handler logic
57
from bootstrap import _get_handler as aws_get_handler
@@ -27,8 +29,15 @@ def _handler(*args, **kwargs): # type: ignore[no-untyped-def]
2729
return original_handler(*args, **kwargs)
2830

2931

30-
try:
31-
# import handler during runtime initialization, as usual.
32-
get_original_handler()
33-
except Exception:
34-
pass
32+
def prefetch_handler_import() -> None:
33+
"""
34+
This function imports the handler.
35+
When we call it in the global scope, it will be executed during the lambda initialization,
36+
thus will mimic the usual behavior.
37+
"""
38+
if not is_aws_environment():
39+
return
40+
try:
41+
get_original_handler()
42+
except Exception:
43+
pass

src/lumigo_tracer/event/event_trigger.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from lumigo_tracer.lumigo_utils import Configuration, get_logger
77

88

9-
def _recursive_parse_trigger_by(
10-
message: Dict[Any, Any], parent_id: Optional[str], level: int
9+
def recursive_parse_trigger(
10+
message: Dict[Any, Any], parent_id: Optional[str] = None, level: int = 0
1111
) -> List[TriggerType]:
1212
triggers = []
1313
if level >= Configuration.chained_services_max_depth:
@@ -27,7 +27,7 @@ def _recursive_parse_trigger_by(
2727
if INNER_MESSAGES_MAGIC_PATTERN.search(sub_message):
2828
# We want to load only relevant messages, so first run a quick scan
2929
triggers.extend(
30-
_recursive_parse_trigger_by(
30+
recursive_parse_trigger(
3131
json.loads(sub_message), parent_id=current_trigger_id, level=level + 1
3232
)
3333
)
@@ -36,4 +36,4 @@ def _recursive_parse_trigger_by(
3636

3737

3838
def parse_triggers(event: Dict[Any, Any]) -> List[Dict[Any, Any]]:
39-
return _recursive_parse_trigger_by(event, parent_id=None, level=0)
39+
return recursive_parse_trigger(event, parent_id=None, level=0)

src/lumigo_tracer/event/trigger_parsing/sqs_parser.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,40 @@
1010
class SqsEventTriggerParser(EventTriggerParser):
1111
@staticmethod
1212
def _should_handle(event: Dict[Any, Any]) -> bool:
13-
return bool(event.get("Records", [{}])[0].get("eventSource") == "aws:sqs")
13+
return bool(event.get("Records", [{}])[0].get("eventSource") == "aws:sqs") or bool(
14+
event.get("service_name") == "sqs" and event.get("operation_name") == "ReceiveMessage"
15+
)
16+
17+
@staticmethod
18+
def _get_messages(event: Dict[Any, Any]) -> List[Dict[Any, Any]]:
19+
return event.get("Records", []) + event.get("Messages", []) # type: ignore
1420

1521
@staticmethod
1622
def handle(event: Dict[Any, Any], target_id: Optional[str]) -> TriggerType:
23+
messages = SqsEventTriggerParser._get_messages(event)
1724
message_ids = []
18-
for record in event.get("Records", []):
19-
record_message_id = record.get("messageId")
25+
for record in messages:
26+
record_message_id = record.get("messageId") or record.get("MessageId")
2027
if not record_message_id:
2128
continue
2229
message_ids.append(record_message_id)
2330

31+
arn = event.get("Records", [{}])[0].get("eventSourceARN") or "Unknown"
2432
return EventTriggerParser.build_trigger(
2533
target_id=target_id,
2634
resource_type="sqs",
2735
from_message_ids=message_ids,
2836
extra={
29-
ExtraKeys.ARN: event["Records"][0]["eventSourceARN"],
30-
ExtraKeys.RECORDS_NUM: len(event["Records"]),
37+
ExtraKeys.ARN: arn,
38+
ExtraKeys.RECORDS_NUM: len(messages),
3139
},
3240
)
3341

3442
@staticmethod
3543
def extract_inner(event: Dict[Any, Any]) -> List[str]:
3644
inner_messages = []
37-
for record in event.get("Records", []):
38-
body = record.get("body")
45+
for record in SqsEventTriggerParser._get_messages(event):
46+
body = record.get("body") or record.get("Body")
3947
if isinstance(body, str):
4048
inner_messages.append(body)
4149
return inner_messages

src/lumigo_tracer/extension/extension.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from lumigo_tracer import lumigo_utils
99
from lumigo_tracer.extension.lambda_service import LambdaService
1010
from lumigo_tracer.extension.sampler import Sampler
11+
from lumigo_tracer.lambda_tracer import lambda_reporter
1112
from lumigo_tracer.lumigo_utils import lumigo_safe_execute
1213

1314
SPAN_TYPE = "extensionExecutionEnd"
@@ -74,4 +75,4 @@ def _finish_previous_invocation(self, current_bandwidth: Optional[int]): # type
7475
cpuUsageTime=[s.dump() for s in self.sampler.get_cpu_samples()],
7576
memoryUsage=[s.dump() for s in self.sampler.get_memory_samples()],
7677
)
77-
lumigo_utils.report_json(os.environ.get("AWS_REGION", "us-east-1"), msgs=[asdict(span)])
78+
lambda_reporter.report_json(os.environ.get("AWS_REGION", "us-east-1"), msgs=[asdict(span)])

src/lumigo_tracer/lambda_tracer/__init__.py

Whitespace-only changes.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from lumigo_tracer import auto_instrument_handler
2+
from lumigo_tracer.lambda_tracer import lambda_reporter
3+
from lumigo_tracer.lumigo_utils import is_aws_environment
4+
from lumigo_tracer import wrappers
5+
6+
7+
def global_scope_exec() -> None:
8+
if is_aws_environment():
9+
# Connection to edge: build the session
10+
lambda_reporter.establish_connection_global()
11+
# auto_instrument: import handler during runtime initialization, as usual.
12+
auto_instrument_handler.prefetch_handler_import()
13+
# follow requests to third party services
14+
wrappers.wrap()

0 commit comments

Comments
 (0)