-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
[#10950] Add logging functionality to backend #10984
[#10950] Add logging functionality to backend #10984
Conversation
Hi @halfwhole, these parts of your pull request do not appear to follow our contributing guidelines:
|
6aff23b
to
eeea9c2
Compare
} | ||
String payload = "Feedback session log: courseId=" + courseId + " email=" + email; | ||
String type = isAccess ? LOG_TYPE_ACCESS : LOG_TYPE_SUBMIT; | ||
LogEntry entry = LogEntry.newBuilder(StringPayload.of(payload)) |
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.
Actually do we need the payload since we have the labels already?
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'm also wondering what the payload should be! We don't strictly need it, but it seems a bit strange to have logs with no description to them in the console. Since we shouldn't be exceeding the log storage limit, it might be helpful to have some form of payload
For actual logging, the severe log should be okay. But for filtering/retrieval of logs, probably best to return Exception with error message to frontend for display |
Hmm, one of the use cases for this is to allow instructors to verify student's claims. If this occurs (logging fails), does this then mean the student may actually be correct and the instructor thinks that the student is bluffing? This seems dangerous. The instructor could ask the admin (Prof. in this case) but it will likely end up being very bothersome if instructors have to ask admin to verify each time they can't find a corresponding log entry. |
If the logging fails and we throw an error to the frontend, then the students can still continue submitting the session but we display a message/toast stating that the student is not being tracked for their actions and any dispute on submission times are not guaranteed. or we could disable the submission but that seems overkill and inconvenient @damithc What should the expected experience for students be if the logging fails on the backend and we are not able to track the student? |
I think it is OK to save but caution the user as disputes usually happens for cases of non-saving. But we (i.e., admin) want to know if this happens at all. A more important question is, how to notify admin if logging fails? Right now, logging is used to notify admin of failures (i.e., any error logs are emailed to the admin). |
This is a problem we don't really have a solution to as yet. Might be worthwhile to start an issue on it. Relevant discussion: #10930 (comment) |
eeea9c2
to
f15d748
Compare
In view of the discussion above, if we fail to create a feedback session log using the Cloud Logging API, would it be good to both throw an error to the frontend (for the student's sake), and use the standard error logging format with |
I like the idea of returning an error to the frontend. The user can try refreshing the page or contact the admin. I don't think additional error logging would be helpful because like you pointed out, it wouldn't go through anyway. |
src/main/java/teammates/ui/webapi/CreateFeedbackSessionLogAction.java
Outdated
Show resolved
Hide resolved
6d6061d
to
f7df937
Compare
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.
See comments below. I think it might be worthwhile to at least get the test skeletons up for the logic
and webapi
components. Can put a TODO
in them and handle the actual writing of tests in a separate PR
/** | ||
* Handles the logic related to logging. | ||
*/ | ||
public final class LoggingLogic { |
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 LogsLogic
might be more appropriate, as it's the logic for managing logs (the noun). Just an opinion though so willing to hear what others might think
* Exception thrown when the logging service fails to create or retrieve logs. | ||
*/ | ||
@SuppressWarnings("serial") | ||
public class LoggingServiceException extends Exception { |
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.
LogsServiceException
though similar to other comment
/** | ||
* Gets the feedback session logs as filtered by the given parameters. | ||
*/ | ||
// TODO: decide on a return data format; this will likely be determined by our API |
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 it might be worthwhile to decide on the data format first, considering that the logic might change because of data needs. I'd rather put this PR on hold until the data format / API is settled
@halfwhole let us know when this PR is ready to be merged in - I think we can do a more thorough review once we have a MVP up |
cea1666
to
0306f6d
Compare
PR is ready to be merged/reviewed -- it's been integrated with the changes in #10978 to support both creating logs and retrieving logs |
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.
LGTM
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.
Alright took a look, progress is there 👍
However, it is definitely a little over-engineered at the moment. This is a simple feature and I feel it does not need to spam so many files.
I have put my comments below for discussion.
* | ||
* @see <a href="https://cloud.google.com/logging/docs">https://cloud.google.com/logging/docs</a> | ||
*/ | ||
public class LogsService { |
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.
There is already a GoogleCloudLoggingService
we can use from master - can merge with that
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.
Yep, rebased this branch to take in these newer changes from master. Can work with those instead
Most parts have now been shifted to the newer GoogleCloudLoggingService
and LogsProcessor
files
* Exception thrown when the logs service fails to create or retrieve logs. | ||
*/ | ||
@SuppressWarnings("serial") | ||
public class LogsServiceException extends Exception { |
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.
Why are we creating our own Exception for this?
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.
Originally I had intended to use RuntimeException
for this, but the linter complains when such raw exceptions are thrown. It also does not fit into any other exception class we have currently defined in teammates.common.exception
, so I decided to create a new one here
@@ -0,0 +1,108 @@ | |||
package teammates.logic.core; |
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 don't think there is a need for this file at all - just update the service class with the below methods
} | ||
|
||
try { | ||
logic.createFeedbackSessionLog(courseId, studentEmail, fsName, fslType); |
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.
better to use LogsProcessor
here instead of logic layer
src/main/java/teammates/ui/webapi/CreateFeedbackSessionLogAction.java
Outdated
Show resolved
Hide resolved
src/main/java/teammates/ui/webapi/CreateFeedbackSessionLogAction.java
Outdated
Show resolved
Hide resolved
src/main/java/teammates/ui/webapi/CreateFeedbackSessionLogAction.java
Outdated
Show resolved
Hide resolved
7d4ffa1
to
5082124
Compare
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 happen to notice this. Just leaving two minor observations, will not comment any further. No need to involve me for any subsequent review.
return fsLogEntries; | ||
} | ||
|
||
private List<LogEntry> getLogEntries(LogSearchParams s) throws LogServiceException { |
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.
You can probably refactor the existing getRecentErrorLogs
method to also make use of this.
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.
Should this be done separately on the master branch instead? It can be done here too, but was a bit hesitant cos this branch is specifically for the audit logs feature
for (LogEntry entry : entries.iterateAll()) { | ||
logEntries.add(entry); | ||
} | ||
logging.close(); |
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.
You should not need this. The fact that logging
is wrapped within try-with-resources tells that this will be automatically 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, removed
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.
Let's add in
SESSION_LOGS(ResourceURIs.SESSION_LOGS);
to ResourceEndpoints.java
. Otherwise frontend will miss out on this endpoint
/** | ||
* Returns the enum value of a log type given its label. | ||
*/ | ||
public static LogType valueOfLabel(String label) { |
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.
Just a question here:
If you pass in values like
"access", "submission",
this method returns
"FEEDBACK_SESSION_ACCESS", "FEEDBACK_SESSION_SUBMISSION"
so the latter strings get returned to the frontend, but the frontend currently just expects former. Is there any reason to have the valueOfLabel
? Since the generateTypes
command just generates
export enum LogType {
FEEDBACK_SESSION_ACCESS = "access",
FEEDBACK_SESSION_SUBMISSION = "submission",
}
so the comparison is with the "access" and "submission"
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.
valueOfLabel
here should have no effect on the frontend, it's mainly for the backend to be able to convert a given string such as "access"
to the appropriate LogType
(such as in the constructor of FeedbackSessionLogEntryData
)
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.
Right. But in the logic of sending back the results, the constructor of FeedbackSessionLogEntryData
is called so the logType field in that data becomes the name of the label instead of "access"/"submission"
. So when the response is sent back to frontend, "FEEDBACK_SESSION_ACCESSS" is sent instead of "access". Was thinking that we can just simply send "access" instead of the label name since frontend will(probably) use the "access". Avoids having to do double work of checking for the label instead
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.
Would that mean that our API should return a string
instead of a LogType
(thus this file can be removed entirely)?
It seems useful though for LogType
to exist as part of an interface that guarantees our log types are one of only several enumerated options (such as FEEDBACK_SESSION_ACCESS
or FEEDBACK_SESSION_SUBMISSION
), rather than a string
that implies something more open-ended
@@ -20,7 +20,7 @@ export class LogService { | |||
courseId: string, | |||
feedbackSessionName: string, | |||
studentEmail: string, | |||
logType: LogTypes }): Observable<string> { | |||
logType: LogType }): Observable<string> { | |||
const paramMap: Record<string, string> = { | |||
courseid: queryParams.courseId, | |||
fsname: queryParams.feedbackSessionName, |
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.
Since the endpoint was changed to post, the method for this method should change too
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.
👍
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.
LGTM 👍
Let's refactor getLogEntries
and getRecentErrorLogs
from the GoogleCloudLoggingService
in a separate PR.
* Add logging functionality to backend * Make changes to feedback session log logic * Add non null for student email * Rename logging to logs and add test skeletons * Add ability to retrieve logs via API * Fix frontend naming * Shift audit log functionality to logging service * Remove closing of logger * Change frontend components
* Add logging functionality to backend * Make changes to feedback session log logic * Add non null for student email * Rename logging to logs and add test skeletons * Add ability to retrieve logs via API * Fix frontend naming * Shift audit log functionality to logging service * Remove closing of logger * Change frontend components
* Add logging functionality to backend * Make changes to feedback session log logic * Add non null for student email * Rename logging to logs and add test skeletons * Add ability to retrieve logs via API * Fix frontend naming * Shift audit log functionality to logging service * Remove closing of logger * Change frontend components
* Add logging functionality to backend * Make changes to feedback session log logic * Add non null for student email * Rename logging to logs and add test skeletons * Add ability to retrieve logs via API * Fix frontend naming * Shift audit log functionality to logging service * Remove closing of logger * Change frontend components
* Add logging functionality to backend * Make changes to feedback session log logic * Add non null for student email * Rename logging to logs and add test skeletons * Add ability to retrieve logs via API * Fix frontend naming * Shift audit log functionality to logging service * Remove closing of logger * Change frontend components
Part of #10950
Adds the ability to create and search for feedback session logs. When a student accesses the feedback session page, it'll create a log with the student's details, which might look something like this in the Logs Explorer:
LoggingService
will throw an exception if they fail. In the case of the student failing to create a feedback session log entry, it will also log a severe warning for admin purposesgetLogEntries
, can probably only do so after we finalise the API types