After earlier defining our logging interface, some readers posed a few questions about how it would work from a consumers perspective. So before we look at implementation details, let’s look at how we’ll instrument our code and what the output might look like.
Each View Model represents a different user activity, so we’ll give each one a different context.
VocabularyBrowserViewModel, the changes are simple.
Aside: You can see both styles of parameter validation here. Sandwiching the
?? throw style into the use of
logger feels too cramped and is significantly harder to read, so I used the older
if ... throw style.
RefreshFromScreen(), when we find our screen has been closed, we need to dispose of the logger to close off the current nested context.
ModifyVocabularyWordViewModel it’s more complicated because we’re reusing the viewmodel for two different activities: both adding and modifying words.
To ensure that our logging is clear, we need to correctly describe our log action. We do this in our constructor by checking which mode we’re using before creating the logger:
At the core of our application, our Redux store is going to be constantly processing messages that change the application state. Capturing these messages in the log should give us a good insight into how the application is operating.
Let’s create a new reducer, one explicitly for logging. At present, it just logs messages on the way through without modifying state - but in the future, we will use it for other processing when we make the log part of our application state.
As a part of our internal plumbing (to be discussed in a later post), we wire things up so that messages logged through the global logger are correctly associated with the current execution context, resulting in a hierarchical log.
For demonstration purposes, we’re sending the output to Visual Studio’s output pane by using
Once we’ve stripped out all the other messages that show up, we end up with output like this:
The indentation clearly shows which messages are related to which activity. We additionally get visibility into the way the application swaps out a new viewmodel for each screen as we navigate around.
As we add additional activities into our application, the diagnostic value of the log will grow, but where it will become most useful is when we start running asynchronous workloads: instead of having all those log messages interleaved, making it hard to decipher what’s going on, we’ll have them showing in separate streams of activity.