-
Notifications
You must be signed in to change notification settings - Fork 429
Feature request: Parse exceptions into structured logs #1268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
That's a great idea @Nogginboink! Are you thinking of including We should definitely look into making this a thing after our pause ends (end of the month). We could ping back here after the pause to ask whether you're up to contribute w/ any guidance or for us to schedule it along with our backlog. Thank you! |
Hey @Nogginboink @heitorlessa! I would like to help you guys to implement this feature. Regarding to your conversation, I think we should stick to additional We can add |
Wanted to see if there are some standards. OpenTelemetry came to mind, but they seem to model it as a string under Google only mentions that it should be part of the message key/val (https://cloud.google.com/logging/docs/structured-logging), but I couldn't find how to actually format it. Sentry have a lot richer model (full example in their demo site - https://try.sentry-demo.com/organizations/on-caiman/issues/?project=141374&query=&referrer=issue-list&statsPeriod=14d): ...
"exception": {
"values": [
{
"type": "SSLError",
"value": "('The certificate belonging to https://app.example.com has expired.',)",
"module": "ssl",
"stacktrace": {
"frames": [
{
"function": "<module>",
"module": "__main__",
"filename": "purchase.py",
"abs_path": "/empowerplant/purchase.py",
"lineno": 36,
"pre_context": [
" generate_invoice(status)",
" return 200",
"",
"main(request={",
" \"ccno\": ****************,"
],
"context_line": " \"cart\": [11.69, 4.95, 5.99],",
"post_context": [
"})"
],
"in_app": true,
"vars": {
"__annotations__": {},
"__builtins__": "<module 'builtins' (built-in)>",
"__cached__": "None",
"__doc__": "None",
"__file__": "'purchase.py'",
"__loader__": "<_frozen_importlib_external.SourceFileLoader object at 0x107f5c850>",
"__name__": "'__main__'",
"__package__": "None",
"__spec__": "None",
"init": "<function _init at 0x1088598c0>"
},
"data": {
"orig_in_app": 1
}
},
... This seems to be (at least part of) the code responsible for the frame formatting/extraction: Because there are so many different use cases, it could be a good idea to account for that the users might want to format the tracebacks differently, by allowing to pass a richer set of config options when initializing the logger. E.g. I might want |
I'd like to take this request on. |
Hi @stevrobu! It will be amazing if you can work on this issue. Do you need any help? I can help you with some guidance if needed. Thanks a lot |
@leandrodamascena - Yes. I would appreciate some help. I will connect with you offline. |
Hi @stevrobu! I was playing around with this issue and managed to add a new field with the exception formatted in JSON. The code isn't good yet and missing important things, but I think it's a good starting point. What do you think we talk so I can show you what I did and you can follow? Code example:import requests
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.typing import LambdaContext
ENDPOINT = "http://httpbin.org/status/500"
logger = Logger()
try:
ret = requests.get(ENDPOINT)
ret.raise_for_status()
except requests.HTTPError as e:
logger.exception("Received a HTTP 5xx error")
raise RuntimeError("Unable to fullfil request") from e Output:{
"level":"ERROR",
"location":"<module>:15",
"message":"Received a HTTP 5xx error",
"timestamp":"2023-09-27 23:38:05,190+0100",
"service":"service_undefined",
"exception":"Traceback (most recent call last):\n File \"/tmp/xyz/leo.py\", line 13, in <module>\n ret.raise_for_status()\n File \"/tmp/xyz/.venv/lib64/python3.10/site-packages/requests/models.py\", line 1021, in raise_for_status\n raise HTTPError(http_error_msg, response=self)\nrequests.exceptions.HTTPError: 500 Server Error: INTERNAL SERVER ERROR for url: http://httpbin.org/status/500",
"traceback":[
{
"exc_type":"HTTPError",
"exc_value":"500 Server Error: INTERNAL SERVER ERROR for url: http://httpbin.org/status/500",
"syntax_error":null,
"is_cause":false,
"frames":[
{
"filename":"/tmp/xyz/leo.py",
"lineno":13,
"name":"<module>",
"line":"",
"locals":null
},
{
"filename":"/tmp/xyz/.venv/lib64/python3.10/site-packages/requests/models.py",
"lineno":1021,
"name":"raise_for_status",
"line":"",
"locals":null
}
]
}
],
"exception_name":"HTTPError"
} |
@leandrodamascena - Sure. Let's talk. I have a pull request ready, but let's compare code first. |
I really like the way the Sentry creates exception and we try to add something like that.
I'm not sure if we will have any experience gained if we allow the customer to add/remove fields from the stacktrace. This is a stracktrace, the customer generally wants to know the error that occurred and the frames where the error occurred in order to parse it. If I allowed the customer to remove the line, for example, how will they find the error? I think we should define a standard and use it. What do you think @kbakk and @stevrobu? We have a PR - #3147. In addition to some bugs that we need to fix, I would like to hear your feedback. cc @heitorlessa Thank you. |
|
Use case
When using the logger and logging an exception, the exception traceback appears as a single string that includes the stack trace, each frame of which has a file, a line number, a function name, and the statement on that line. Parsing that line, either with the Mk I eyeball or with code, is difficult
Solution/User Experience
Because logger is all about structured logging, it would be nice if the stack backtrace were structured as well. Something like:
Alternative solutions
Acknowledgment
The text was updated successfully, but these errors were encountered: