In this video we're going to learn all
about how to add client-side logging with MetroLog to your .NET MAUI app. If you've ever released an app, or
any piece of software into the wild, then you know how
important logging is because the user, users, whenever something is not
working, they try to help you, but it's not really helpful to you if they say
like, I press this button and things don't work. It doesn't really tell you
what's going on, right? So you have to have logging in order to know
what's going on. Ideally have those stack traces, your own log
statements in there and that's exactly what you can do with MetroLog. Now
MetroLog is a library that has existed for a long time. I think it's a drop
in replacement for NLog, which is drop in means that the
method names and all the things are mostly the same, but the
implementation is different. So MetroLog has existed for a long time, built by
other great people. But now my good friend Jean-Marie has created a
new plugin especially for .NET MAUI, compiled against .NET 6 for the same purpose of logging information.
Now in this video we'll see how to implement it, how to do console
logging. Well, trace logging basically console
loggin, write to a file, maybe even touch upon how to attach it
to an App Center kind of crash log thing. So you can
also transport it to outside of your app. A lot to cover here. So let's
just quickly dive in and see how to implement all this goodness. So
here we are in Visual Studio 2022. This is just a File, New .NET MAUI
application. You can see it running here. The .NET bot is waving at
us again. Hello again, my good friend. Let's just close this down,
the running application because what I need to do first is of course install the
MetroLog NuGet. So let's right click on our project
right here. I'm going to say Manage NuGet packages. And then here I can find
MetroLog.Maui. Now like I said, there's also just a .NET 6 variant of it. So you can use it with
other .NET 6 applications as well. It doesn't have
to be MAUI, but we're going to look at MAUI right here. So let's click that
one, let's click install and then it's going to pull down the NuGet
packages. It's going to install that on our .NET MAUI project and
whenever it's installed, we can just start using it. So here you can see all the
original authors. Matt Baxter-Reynolds, Claire
Novotny, Jeano-Marie Alfonsi, who is my great, great friend from
France and he has been creating this. So it's installed right
now and basically you're good to go. So like I said, this very
much connects to the generic host builder and that kind of stuff.
So if we go to our MauiProgram.cs, we have this generic host builder right where we can initialize
all of our stuff. The same is true for logging and if we set it up this way,
it automatically works with the dependency injection and all that kind of stuff.
So if I do here builder logging, we have a dedicated logging section
and I can here say Add... And you can see that it
comes up with a couple of things here. ConsoleLogger,
InMemoryLogger, StreamingFileLogger and a TraceLogger.
And of course you can also add your own provider if you have your
own target. Totally customizable, totally up to you. If you want to
write something in a special format or to a special thing that's totally up
to you, you can do that. But this is like the built-in targets right
here. So the ConsoleLogger; a little note. This
writes to the console of the actual device. So in
case of iOS that they have their dedicated
log thingy. For Android it's logcat and for each
platform there is a dedicated thing, so it's
not going to do it to the Console WriteLine. Basically that's the
important thing for that. You won't want to use the TraceLogger. And whenever we add
one, we have here the ability to specify
some options so we can do options here and then we can
configure more options, which is mostly the
minimum level. So we have a couple of lock levels. Of
course we have the trace, the debug, the information, warning,
error, critical. So you can define all kinds of levels and let
them go to different targets if that's what you want. We also have the
maximum level so that's kind of like whenever you have log statements in your code,
only the ones that are specified here in this Min- and MaxLevel are
going to be put into this Trace Logger right here. And I think we have
something for a ShortCategory where we'll use the short category names
whenever it's outputting something. But I'm fine with the default options so I'm
just going to do this little discard thingy. And now we
have set up the trace logger. Now if we want to
use the dependency injection, of course we also need to add our page to it. So AddTransient so that our page is registered as well
and it can actually receive the dependency injection. If you want to know more
about dependency injection, a video should pop up on your screen right now. So
now we have set up our main page as well. And now I can go
into the MainPage right here and I can specify whatever I want to
receive here for the dependency injection. So let's make this an eye
logger. Now at the time of recording, I'm not sure if this is a bug. A bug
is logged for it an issue on the repository, but you have to use this one. Let me finish typing here first. So
you have to do this ILogger variant using Microsoft.Extensions.Logging. So
make sure to add that. And then you need to do ILogger with the angle
brackets here. And you need to specify the type in here. This will
be used to kind of like categorize the log messages and it
will also show in the log output if you just do the ILogger, I think,
which is totally possible. So you don't get that category information, but it
gets a runtime error at the time of recording at least. So
if that's something that you're interested in, make sure that it's fixed by the
time that you want to implement this. But for now, you can just do this with
the type. But this is probably also what you want because now it gets
nicely categorized in whatever type you are getting these log messages
from, right? So that's probably something you would want. ILogger<MainPage>. Let's
get this in here in a little field _logger. And now we can put this _logger = logger. And now it's ready for use.
Right? Now we can start using this logger everywhere. So if I copy this
and do it to the little, this is the event that happens
whenever we click on the button and we do the count++. So let's
just add here logger, log and we see all these levels,
right? LogCritical, Debug, Error, information, Trace, Warning
I think you can do some custom stuff here as well. But this is
like an information thing, right? This is just informational,
nothing special here. Let me specify something. So a little string
interpolation... Button clicked and maybe you want to also now say... count. And we can incorporate count here, right? So we can see
that it actually counts and does something here as well. So now we have
our first log statement set up. So actually let's just run it. Let's
run it on Windows again. This works on all platforms, of course. So it's
going to deploy to Windows. And whenever we see it come up, I
think we should already see a couple of log output things here in the
application output because it starts logging and
it sets up loggers for different things. But whenever we
click the button, then we also should see our own custom log information coming
up right here. So here we are, the application is
coming up. And let me see the application output here. This is not
the right one. Here we are. See here you can already recognize
these logs right here in the output. So it has even a line
number. It has the date of today new log manager created. It
creates new log managers for different things here.
And whenever I scroll it down and I click the button here, you can see that
there are new lines added here in the background with the click
count that I can see. Come up here. So this is kind of like your basic
logging, but this only goes to your output right here. But it can still be
very valuable whenever you're debugging things, right? So this is in here, but
now let's take it even a step further because one of the cool
things that you can do is actually have this little shake to get a crash report kind of log information. So a
shake to give feedback kind of thing. It's built into this
plug in, which is really cool. Now what we want to do for that is we're going
to have to add a new login target. So I'm going to go over
to my MauiProgram and... What did I do? Here we go. So if you want to use the kind of
like shake to show logs, it will become clear whenever I
actually show you what's happening. We have to add the in-memory target. So the in-memory one will just... Is this right? AddInMemoryLogger... there we are, also here. We can
configure options with how many lines need to be preserved and that kind of
stuff so that it doesn't grow inside of your memory application. But
we need to enable at least this one. And if you also
want to share the log so if you shake, then you will get a
page. You will see kind of like in a text window, the in-memory log
messages. But we can also have the streaming file one
that I just mentioned, right? So let me actually just copy
and paste this line and we can also dot add the StreamingFileLogger. Again, you can configure like the file
path and a couple of other things for that one. But with this one, you could
also get a share button in that same window, you can tap the
Share button and you can send it through email or do all kinds of
things. So I add these, which is fine. And now I need to kind
of enable that page to come up whenever
you shake it, right? So there's a couple of things you need
to do with that. For that we have the log controller. So go into
your App.xaml.cs you can do it somewhere else, if
that makes sense. But I'm going to paste in some code here. And this
LogController is a static thing. And you can say initialize navigation
because this is a page that is built into the MetroLog.Maui
package. So that page is there. You can
customize the page if that's what you want. But we need to tell that page how your
navigation is working inside of your app, right? You can
have different navigation stacks, you can have different navigation frameworks
installed. So you're going to have to tell this lock controller initialize
navigation. And in this case, we have two parameters, the
navigation function. So how should the page come
up here? And we can just say MainPage, which we set here, Navigation.PushModal. So we're going to push it as a modal
and the second one is to pop it again. So we're going to say
PopModal. And then you have a third option with which you can
actually specify like your own shake to show the log page thing. But
we're going to skip that for now. You can find all
about that in the documentation. So we've got this set up. Now, one
thing which personally I find a bit odd, I'm going
to tell Jean-Marie that as well, right after recording this. But you
will have to add the Is shake enable, basically. But the
way you should do that is with a kind of build in view model. So
if I go to my MainPage let's go here. We have to kind of set this binding
context is new and this is the same logger controller. Controller. Was it logger
controller? No, control logger. I don't know. What was
it? LogController. There we are. So, new LogController.
And inside of this LogController, if we
inspect it... var foo = new LogController(), and that's
the easiest way to get all the IntelliSense here, you can see
that it has all these properties, right? It CanGetCompressedLogs. You can
also get compressed logs. It will compress all the locks that it has into a zip
file and you can send it as an attachment to maybe your App
Center logging, right? That's totally something that you can do. ClosePageCommand,
IsShakeEnabled, right? That's the one that we
are after. So you have to enable it through this instance
of LogController, which makes sense if you're going to create kind
of like a settings page. You can put this in here. But it would be nice to
also have these little static options, I
guess, so that you can shake enabled without having this LogController.
So for now, I'm just going to set this binding context. If you
want to know more about data binding and MVVM, something should pop up on the
corner of your screen. So let's get back to the MainPage.xaml
and I'm going to add a little switch here that will switch the toggle the shake to show the actual page. So is toggled
is true? No, I want to set this to binding IsShakeEnabled. All right. So I got that set up. Now,
whenever I run this, of course I can't run this on Windows
because that doesn't really work. I can shake my machine,
but it's not going to show the actual page. So I have my local device, my
physical device, because I found the shake was very hard to mimic whenever I did
it on the emulator. So let's run this on
Android. And while this is running, I should be able to pop up
my screen right here. So I'm going to deploy the app right
here. I have this physical device which I should be able to unlock here.
And whenever the app is deployed, that I should be able to hit that
switch to activate the IsShakeEnabled. And I probably want to tap on the
button to generate a couple of log messages here. So let me just do that.
Click, click, click. It's behind my little camera here. Click. You can see
it come up right here. And then whenever I tap the
switch it's not really visible here in the top, right? I put the switch on and
then whenever I shake it, you can see that a new window comes up
which is built into MetroLog.Maui. And you can see all the log
messages right here. And I can close it or I can do the
share logs and I can share it to someone nearby Bluetooth.
This is just your built in share dialog, right, which will pop up on
iOS, Android, all the things and you can share it to
whatever you want. So whenever, you know, kind of like your customers, you can
instruct them to shake the device, get this little
dialog out, share the logs with you and your goal. So that's how to get
started with MetroLog and .NET MAUI. Now, it's a bit hard to create a video
on this besides just showing you the mechanics and how to implement
this because it really depends. I think if you are working on
a consumer app that goes through the App Store, then you
don't know who is going to download your app, right? So this shake to actually
show this lock screen is very useful. But you can't
really reach your user that downloaded your app through the
App Store and say, hey, okay, try to shake your device and please
send me the locks. That's not something that's realistically going to happen.
So then you would have to tie this in with services like App Center
to actually retrieve those logs. Of course, a very
important note, just don't go logging
everything. Please be sure to check the local laws and whatnot
GDPR that you're not collecting any stuff that you
shouldn't be collecting, which is very easy to do if you're just logging all these
things, right? So please make sure to do that and especially if you're sending
it to App Center and whatnot. But if you're in a more enterprise
environment and you probably do know the actual users that are running your
app, then it totally makes sense to implement this screen, right? You can just maybe
they're tech savvy enough to scroll through the logs and see what's
going on their sales or they can very easily share it with you. You can
enable these things by little feature toggles, if that's
what you want, whenever you're trying to debug a very specific problem on a
specific device. So there is loads and loads of options with this.
But it's so cool that this hooks into like the generic host builder, your
.NET MAUI app. It's just minimal configuration it puts it in there and
you have this logging enabled inside of your application,
which is really, really cool. Thank you so much again for watching
another one of my videos. Please click the like button so that it will spread
through the YouTube algorithm to other people who might be interested in .NET MAUI
.NET, C#, all the things logging, maybe logs, I don't know, it's not
really relevant. But maybe someone likes to chop trees.
And of course, make sure to check out this playlist for more
.NET MAUI content, this recommended video. And click here to make sure that
you're subscribed. So I'll come to you automatically. See you for the next
one.