-
Notifications
You must be signed in to change notification settings - Fork 20
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
Issue #2561: format logs as json (on getgov-ms) #2705
Conversation
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
@Matt-Spence FYI: Looks like the linting check is failing on this one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work on this, very elegant.
I have one comment just regarding local logging (for local dev). Interested in your thoughts on it!
src/registrar/config/settings.py
Outdated
class JsonFormatter(logging.Formatter): | ||
def __init__(self): | ||
super().__init__(datefmt="%d/%b/%Y %H:%M:%S") | ||
|
||
def format(self, record): | ||
log_record = { | ||
"timestamp": self.formatTime(record, self.datefmt), | ||
"level": record.levelname, | ||
"name": record.name, | ||
"lineno": record.lineno, | ||
"message": record.getMessage(), | ||
} | ||
return json.dumps(log_record) | ||
|
||
class JsonServerFormatter(ServerFormatter): | ||
def format(self, record): | ||
formatted_record = super().format(record) | ||
log_entry = { | ||
"server_time": record.server_time, | ||
"level": record.levelname, | ||
"message": formatted_record | ||
} | ||
return json.dumps(log_entry) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Q) Whats the difference between JsonServerFormatter and JsonFormatter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JsonServerFormatter inherits from ServerFormatter which provides access to fields like record.server_time as well as providing messages based on the error code. In practice I don't think it makes all that much difference, but I wanted to keep things in line with how they were done previously, so I split it out into two formatters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense!
@@ -445,6 +448,30 @@ | |||
# logger.error("Can't do this important task. Something is very wrong.") | |||
# logger.critical("Going to crash now.") | |||
|
|||
class JsonFormatter(logging.Formatter): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add some brief class comments to both of these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
src/registrar/config/settings.py
Outdated
class JsonFormatter(logging.Formatter): | ||
def __init__(self): | ||
super().__init__(datefmt="%d/%b/%Y %H:%M:%S") | ||
|
||
def format(self, record): | ||
log_record = { | ||
"timestamp": self.formatTime(record, self.datefmt), | ||
"level": record.levelname, | ||
"name": record.name, | ||
"lineno": record.lineno, | ||
"message": record.getMessage(), | ||
} | ||
return json.dumps(log_record) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I think this level of detail for running the app locally may be a bit much - but I am in total agreement with running this on the server. Just making a guess - but I'd assume that is the distinction between JsonFormatter vs JsonServerFormatter right?
Not at all blocking though if this is the requirement for both. This just makes reading logs harder during local dev for me, though it may just be because messages is the last item in this array
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Matt-Spence / @abroddrick What do you guys think? Personally I am for keeping our old logging in console, but outputting the json for JsonServerFormatter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a fair point, there's no requirement to use JSON in console and looking at it I don't think it's worth it. Plus, using the old console logger eliminates the need for the jsonFormatter which is a nice simplification. I'll go ahead and revert this.
try: | ||
raise Exception("TEST TEST TEST") | ||
except Exception: | ||
logger.error(traceback.format_exc()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remember to remove this before merging!
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
1 similar comment
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
🥳 Successfully deployed to developer sandbox ms. |
Ticket
Changes
Context for reviewers
Right now logs are janky in that multi-line logs get read into kibana as a new log for each new line, which is especially painful for tracebacks. This PR fixes that by formatting all logs as json objects, which kibana is configured to parse correctly.
Setup
Code Review Verification Steps
As the original developer, I have
Satisfied acceptance criteria and met development standards
Ensured code standards are met (Original Developer)
Validated user-facing changes (if applicable)
As a code reviewer, I have
Reviewed, tested, and left feedback about the changes
Ensured code standards are met (Code reviewer)
Validated user-facing changes as a developer
New pages have been added to .pa11yci file so that they will be tested with our automated accessibility testing
Checked keyboard navigability
Meets all designs and user flows provided by design/product
Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)
Tested with multiple browsers, the suggestion is to use ones that the developer didn't (check off which ones were used)
(Rarely needed) Tested as both an analyst and applicant user
Note: Multiple code reviewers can share the checklists above, a second reviewers should not make a duplicate checklist
As a designer reviewer, I have
Verified that the changes match the design intention
Validated user-facing changes as a designer
Checked keyboard navigability
Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)
Tested with multiple browsers (check off which ones were used)
(Rarely needed) Tested as both an analyst and applicant user
Screenshots