-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Refactor logging squashed rebased #16779
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
Refactor logging squashed rebased #16779
Conversation
First pass at huge Actionlog refactor Yank observers from AppServiceProvider Only 3 tests left to go! All but one test passing All tests now pass. Cleanups, renames, clearing out unneeded changes, unused log messages Cleanup, removing unnecessary log types on restores Added some comments and switched main Loggable interface method
Just starting to dive in but I'm not liking the
What if the API changed from (using $asset->setLogTarget(auth()->user());
$asset->setLogLocationOverride($user->location_id);
$asset->logAndSaveIfNeeded(ActionType::RequestCanceled); to something like this: $asset->withLogging(function () use ($asset, $user) {
$asset->setLogAction(ActionType::RequestCanceled);
$asset->setLogTarget(auth()->user());
$asset->setLogLocationOverride($user->location_id);
})->save(); It feels better to me to bundle that operation together in the callback and continue to use the native
FWIW, the following hits the $asset = Asset::factory()->make();
$asset->save();
$asset->save(); Gonna dig deeper but wanted to drop an initial thought here first. |
A couple more thoughts before really diving into the code...
All three of these are wins in my book and I'd really like to push towards that goal. The last one I completely agree with. I'm going to hold off on a full review until we talk more about my initial response since that would touch a lot of the files changed here. |
Thank you for your comments! I feel similarly about So you get: $asset->setLogTarget(auth()->user());
$asset->setLogLocationOverride($user->location_id);
$asset->setLogAction(ActionType::RequestCanceled);
$asset->save(); I did like the way the save + Action stuff happened all in one line, but I am not married to that. This looks more 'standard' and should work. We might want to mess around a little bit with the implementation so a "blank save" doesn't create a 'pointless log entry'. The logic there could be something like - if there's no custom ActionType (in other words, it's about to be a simple If you're okay with this new approach, I can throw in a chunk of fixes for this stuff - basically, finding every call to |
Just FYI - I also have two more 'stacked' PR's against this PR. They're here: uberbrady#7 It's weird that they have to be on my version of the Snipe-IT repo, but, well, that's GitHub for you, I guess. |
Am I right in thinking that these I prefer the codeblock you wrote above instead of the original $asset->withLogging(function () use ($asset, $user) {
$asset->setLogAction(ActionType::RequestCanceled);
$asset->setLogTarget(auth()->user());
$asset->setLogLocationOverride($user->location_id);
})->save(); In my mind you would only need to call
$asset->withoutLogging()->save(); I imagine I'm not super-invested in this idea but just wanted to express my viewpoint. |
I'd agree that I do like the aesthetic look of the anonymous function/callback format, but I don't think it actually gains us anything. And honestly, the The way it works now is that, if you create a new thing, the log entry gets added as I'm proposing that any As a side note, I did notice that in the ActionType I'm using different parts of speech - "created" versus "restore", "note added" vs. "audit" - I should probably clean that up too. |
I cleaned this up the way I mentioned in my last comment over in #16839 - I decided against fixing the "parts-of-speech" problem in |
I see where you're coming from and since we don't need the Going to move comments to the new PR. |
(This has conflicts, which I will fix, but I wanted to get this up so we can look at it and talk about it).This is my latest attempt at re-doing the actionlog system.
The most important changes are to the Loggable trait, which has been moved into the Traits directory. (I also moved Requestable there too; but that's not really related).
Loggable now hooks into the various Eloquent lifecycle events and ensures that actionlogs are written whenever an object is created, updated, deleted, or restored. Additionally, we can do other tasks that may or may not change the object in question, to create action logs for Requests, Checkins, checkouts, etc. This is powered by a bunch of Setters usually named "setLogSomething", and the actual log entry is created when we call "logAndSaveIfNeeded()" which takes an ActionType. That method is named like that because sometimes actions like Checkin and Checkout will actually modify the object itself, but sometimes they may not - and we need to make sure the log is inserted regardless. It's possible that a regular
save()
method-call will still fire thesaving
andsaved
events, even if the object is not dirty, which might mean we can simplify some of these method names, which could be nicer. These changes mean that, in general, you should not ever have to create anew ActionLog()
and save it directly - the helpers and "logAndSaveIfNeeded()" methods should be enough.ActionType is now an Enum, so we can avoid accidentally typo'ing an
action_type
- and in fact there was one such typo that was already in there which @snipe caught and I've fixed.The individual Observers for the First Class objects are no longer needed since the Loggable Trait now handles many of those cases. In the cases where the Observer was also implementing some parts of the First Class Object's behavior (such as auto_increment on assets, etc), that functionality has been added to the appropriate First Class Object's
boot()
method. I prefer this locality-of-reference because it means when you're looking at, say,Asset
, you can see the functionality that powers it all right there - without having to remember to look at another file somewhere else.Additionally, we were powering many log entries by emitting an event, which was hard to trace through. Now, setting appropriate values and firing the
logAndSaveIfNeeded()
method has to be done explicitly, at the cost of a few extra lines of code. I feel like this is worth it and is more clear and explicit.There were some spots in the code where we needed to disable the event dispatcher in order to avoid multiple log events; I think that's not needed anymore so I've removed those parts, but testing should help show if I'm right or not on this.
There were some parts of the code where we set a non-Eloquent value -
checkout_qty
andcheckout_to
- on things like Accessory (which don't have those values), specifically for the purpose of reporting those quantities to event listeners that fire off emails and other notifications. That has an unintended side-effect of making those objects, once modified, un-savable (a call tosave()
fails with "no such field checkout_qty"). I've replaced those with a->setLogQuantity()
method which sets private values. This will dovetail into better quantity management in a later PR.In order to keep this change (which is pretty big!) as small as I could, there are still some bits of code powered by events, and still some direct action log manipulation. We should be able to fix those as well
TODO
setLocation
in app/Http/Controllers/ViewAssetsController.php - what is that, is it doing what it's supposed to?Log::error()
statements that I had during troubleshooting.action_date
is actually being set, and set correctly, for all log entries. I'm pretty sure I wrote this but I'm not sure.log_meta
and object-changes are all still workingif ($this instanceof Asset) { ...
to make sure that we're not putting secure information unencrypted (or, even encrypted) in the action_logs