Logging | Game Engine Series

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up guys my name is China welcome back to my game engine series so last time we took a look at entry points on how we actually had to kind of define an entry point for both our engine and application how old that worked definitely check out that video you can happen already and today we're gonna be taking a look at logging and how we can actually use a logging library in our engine so that we can log things to the console in various like special colors and just everywhere throughout our codebase special tags and anyways gonna be a lot of fun first of all I just want to give a huge thank you as always to all the patrons that make this series possible if you guys aren't supporting the series we've got a patient icon for /the Cherno the surgeons wouldn't be here without you guys so a huge thank you as always and as a as a reward for supporting this series you'll also get things like source code to the actual hazel engine that I've already written as I'm writing it kind of just immediately as well as videos per week early so it's always interesting when I make these videos because in a sense I'm making it for like one group of people a week before the second group of people so by the time this video is actually public for everyone for the whole internet like I've already long forgotten about it because I already made the next video for patrons but anyway let's get into logging so what is logging why do we need it and what are we going to do here today so logging is just a way for us to basically log events right I say events in kind of a liberal sense like because events don't really really be anything like anytime I want to be like hey something happened right I want to essentially have a way of the edge in communicating with us the humans who are both developing it but also possibly using it right so a good example is we started the engine right let's print off the kind of system initialization things that happen maybe even system information information as well say system information information like this information about the system that we're running on whether or not things certain things worked whether or not said files were opened whether or not like the shaders were compiled successfully there's so much information that we need to basically give as feedback because to me at least like a good piece of software is very kind of client-facing in the sense that like when you write a piece of software that is even moderately complicated when things go wrong you want to know what's actually happened right but your computer's running all of this code it's doing all of these complicated operations especially as the code base grows it's gonna be doing all of these complicated operations but it's gonna be kind of keeping it to itself that's not what we want right because if something goes wrong or even if something goes right we have no idea of actually seeing what's happened and I really like to know what is going on right I just have to know what the computer is done and what state is kind of in right and that's where logging comes in logging is a way for us to actually as we write our code as we write our complex code to communicate back to ourselves and basically say okay so I tried to do this this happened this is the status this is what's going on this is what I'm gonna do next well this was an error you know maybe fix this you know so many things like warnings as well there's so many things we want to do so apart from just being able to communicate back to ourselves why like a printf or like standard Z out or something like that we also probably want information about where that message is coming from as well as potentially the severity of that message so instead of just being like you know here's like a bunch of you know text being printed out console we might want to use different colors so like arrows might be red warnings might be yellow normal stuff might be green stuff that's not important might be like gray or something there's the kind of this whole system that we want that really provides us like with the way to just easily be able to like scroll through our running a console and be like oh no I saw a red message there let's investigate there that's probably something wrong well maybe we know yellow is probably not that great we can kind of ignore it there's so many things that we wanting to deal with so because of that what I'm gonna be riding out or in logging library um we could do that that would take a while maybe like a week's worth of excises I mean like a week's worth of work really is what I was gonna say but the idea is that the biggest issue with logging I think is formatting different types right so printing just hollow world or whatever is easy because we can just be like this is my text string that that's kind of that's kind of it that's done right but when we actually have if you actually look at a real kind of engine code base and you want to print stuff you want to print much more than just text right you want to print numbers you want to print objects you want to print pointers you want there's so many things that we want to print and we need a good way to format that string properly and strength formatting writing a good kind of c-sharp style string dot format function is a lot of work and probably about a thousand lines of code right so it's not something that I really want to spend time on in this series I just I'm trying to give you guys I guess there is I'm explaining all this in a way in service writing code it's just because I kind of want to give you guys an idea of what that's going through my head when I decide okay we're not going to write it ourselves were just gonna use a library and for this it's literally because of the fact that I want to be able to support string formatting and probably like you know an undetermined amount of arguments for our actual log message and that's something that it's much easier to just take something good that has been written and reuse it instead of kind of writing everything else else because then this would take over here anyway so we're gonna be using a library called SPD log so if we just open up github over here what I've got here is just to get up a drip and I'll leave this in the description I was just I've also started um so you guys can check this out for yourselves it's very it's quite fast it's even runs an asynchronous mode and there's a really nice usage sample here that you can kind of look at yourself the primary things that I like you know it's stuff like formatting I mean if you look at this these are the different kind of messages that you have warn critical info or whatever we don't have to use we can use any kind of subset of these as we choose but you can say that the way they love messages is very kind of c-sharp style how they've basically got which argument is refers to so that the first one the only one and then different formatting options for kind of that argument and you know you can do like you know arguments in different kind of order and anyway this is just this is just great it's very sharp style which is really good and I really like it and also if you look at a license of course which we need to do for every library that we use it's the MIT license you can see we have all the permissions that we need as long as we actually retain this copyright notice which of course we will inside our engine ok cool so now that we've decided to use this how do we use this now I could make an entire video on the proper way to use third-party libraries in your codebase because guess what there is no proper way basically there is c plus plus C plus laws dealing with kind of modules or like just libraries is just not that there's no real standard way to like people will have different ways people might be like oh you know you see Meg use kind of your own system if you didn't get maybe use sub-modules like it doesn't that there's no kind of language to find a way to actually import libraries and use them so maybe I will make a video on various ways to do it and what I've kind of found throughout my kind of career but a lot of times it basically comes down to pick a build system that you want to use such as semuc or pre make or something like that and then just make sure that every library that you use you kind of rice a you write that into your build system and then for things like this you either can kind of maintain them separately and just update them kind of as updates come out or you can add them like as I get somewhat if you didn't yet you cannot add them as it gets sub-module that's probably the best way to do it for that but there's still kind of noir there's no right way to do things and eventually things will go out of date or eventually like you'll run into a library you want to use that doesn't use the build system you use so you'll have to write your own kind of you know for example I want to use something I'm using semuc as an example I'm not actually in this series and probably warrant but anyway I'm using say make I decided to use this this doesn't have same egg okay I have to write my own say Mac OS this file to make this compile for CA and then I use that in my code that's essentially something that you'll probably end up having to do for libraries unless everything happens to use the build system that you're using and also happens to be for example on year as like on Veron gets kind of version control system so you can just use it as a sub module so anyway the whole thing is a mess and I'm like I don't want to spend too much time talking about it but let's actually just kind of download this into our project so all we could do there's a number of things that we could do we could just clone or download this just download a zip file and unzip it into our directory we could clone this into its own directory and then copy the files or what I'm going to do is actually add it as a sub module to our hazel repository so what this means is that we don't actually kind of have the code base in our code base it's basically like it's basically we're referencing an existing git repository somewhere else there's kind of at a remote address and then when we actually clone hazel and we say also clone all the sub modules it clones that and the reason that that's kind of useful is because it kind of keeps a ver kind of code intact as well as less let's kind of easily like kind of update to new code changes from their repository without kind of having to do anything manually we can just update we can just update that specific sub module because it is a sub module and it's not actually copied and pasted code into our own repository I may actually make kind of a standalone video on get sub modules in the future because using this using it in the context of this properties in the best example but basically all I'm going to do is copy this address here and then come down into hazel I'll open a command prompt window here and I'm going to just type in git sub module add and now I have to I'll paste in the path or sorry the URL to the actual git repository and then what I'm going to do is specify where I want it to actually add this code into now you can say that this is really nice this is really nicely done I mean it's got like include SPT log and that's really kind of the only thing that we need even though there's so much other stuff like what I'm saying is that in kind of into our include path really this is the other thing that we need but that's okay we'll sort that out later so what is where I want to store all these third-party libraries is going to be kind of in the solution directory probably inside hazel itself because I don't think that this will be like we should probably have third-party libraries per project rather than for the entire solution so inside hazel I'm going to make a folder called vendor write which is going to refer to all third party libraries and then the name of this library which is going to be SPD log because obviously I don't want all of these files just in my vendor folder so that's all I'm going to do I'm gonna hit enter and then it's going to actually clone that repository into that project and what you'll also see once it finishes is a file appear in our actual root directory called git modules and if we just kind of open that file I'll just open it with Visual Studio at this point you can see that it's created a new sub module in this path there's a path and there's the URL is company - okay so this is what actually kind of defines that sub module and inside Hazel you'll see vendor s bitty log and then here it is okay so what we need to include in our project to get access to this is include and then well keep this like this so basically this is the path we need so I'm going to copy this path I'm gonna paste it into below right-click properties for our actual hazel project I'm going to go to say service bus and then additional include directories under general for all configurations and our only platform here I'm going to add this okay pretty simple now because this is actual hazel what I'll do is I'll make kind of a universal path that works for all projects because we will have to actually include this in sandbox as well since this is kind of a header library so solution directory and then hazel bender SPG log include okay copy this go to sandbox here yes here and I'll paste this into here now this is going to get a little bit annoying when we switch to using a build system well obviously define this nicely in the build system so we won't have to kind of keep track of it here in these property pages which can get a little bit annoying okay cool that is done now we can actually start using that live so let's make our own wrapper for it so now at this point we could just kind of use SPD log as SPT log but we obviously don't want to kind of have like SPD log log or whatever stuff in our actual client game right this is the hazel engine we should have hazel log or something like that that's important for a number of reasons first of all I want to change the API I don't want it to look like their API because their API is actually quite babos we want something really simple this is a log this has come with a logging system for an engine so really this should be magnified that's kind of like a global macro that we can use log level or something like that we don't want to have to like to start you dealing with namespaces or having like long kind of strings of Texas is like completely unnecessary but also if further down the line we decide to replace this logging library with another log library we should be able to ha swap that kind of out without actually having to change any client code because we want our game code like when people use the hazel engine and start doing things like a logging a message and like if we decide to change something internally we don't want them to have to go through their code base and kind of change the API that they've been using because we've decided to change something as minimal breaking changes as possible is what we kind of want so because of that we're gonna create a log class which kind of wraps a lot of SPD log functionality and just ends up calling kind of static functions I guess that will then forward kind of arguments of whatever to SPD logs so we're basically is putting a wrap up let's just go ahead and do that so over here on the hazel I'm going to right click hit add new item we're going to just create a class then we're gonna call it log ok we're gonna have logged on each level cpp hit OK and there we have our log class so I'm going to type in namespace Hazel this is going to be class Hazel API log will include port or H now this is probably made it in the wrong place let's just move this into the hazel folder here okay so we've got quota H we're going to go into log o CBP also make sure this is the namespace hazel and that looks pretty good to me so far okay so now I'm not sure why this isn't working it's totally in the same directory so we'll just assume that's Visual Studio being weird so now we need to think about how we can actually use SPD logs so the way we're going to do that is really just include SPD log slash SPD log we're gonna have to do this in the header file and you'll see why in a minute but now we just want to kind of define what our at our actual API will kind of look like as well as probably some macro so that we can kind of easily call logging functions as required so SPD log actually has quite a nice example that we're going to kind of steal some code from you can see that we create a new console by just kind of creating this kind of multi-threaded console we give it a name and that names gonna be important later as well because it's going to kind of be appended to the beginning of every message and then we can kind of we have different varying types so what I'm going to do is actually kind of we're gonna make two consoles one for the client one for the actual engine so call one core I guess and one which will actually be kind of our app I guess console and we're going to obviously abstract all this away so that it's not a lot nicer than having to call like member functions like this and then we're also gonna probably set our own formatting option because we can actually use that pattern here to set like I guess like a format for how all log messages will kind of get printed so let's go ahead and do that so the first thing I wanna do is I wanna get out of this I'm gonna make an init function because we definitely need one of those and then I'm going to make an inline static st shared pointer I think it's SPD log SP like lover or something like that yep SPT log logger will check that by reference and this will be kind of out for logger and so we'll have to do it we'll have our core logger which will return our let's just say core logo which will make here and then we'll also have our client logger [Applause] client logo which as you can imagine I'm just going to end up being s or lager and s client's logo also include memory H or just memory so that we can use head pointers okay cool so there we go we've got to kind of loggers set up here and an initialization function let's go over here we'll have to define these two in our actual translation unit here so we'll say log for logger and log client logo that is shed pointers here and we'll have our void in this I'm really kind of getting annoyed about visual studios water formatting not working here let me just try and build this okay so the legal reference to non-static okay yes of course these need to be static compile it again okay good succeeded again I'm not sure with this intellisense or whatever is going on is really annoying sometimes it'll do but whatever okay so now let's kind of create these two loggers that we actually have okay so the first thing that I want to do is actually set the pattern for kind of how we're going to actually log our messages this is like the format so if we go over here and you go to I think the wiki and we go into custom formatting you can see they've actually got examples of kind of how you can use these patterns and a bunch of flags which says like which part of the message it will print and so using this I've kind of prepared a pattern earlier which is basically this so this will kind of color it in the right way then have the time stamp and then have the name of the logo and then have the actual log message okay so we're basically just having kind of the time stamp the name of the logger so whether or not is call or client and then our actual message so it's pretty simple and all of that will be wrapped within the correct color for that that kind of severity of message so now that we've done that we can actually start creating these so if we go back to the wiki or just the repository and laughter example you can see that what they do is they create this kind of STD out color and then mt4 multi-threaded so we're just going to go ahead and say s core logo equals STD sorry equals SPD log STD out color empty and then the name okay so for this we're actually going to call it hazel okay and that's going to be our core log of we're also going to make one for our clients and I'm just gonna call this one app okay maybe tap like that in fact I'm also going to make hazel like this and then I'm also gonna set the level of which we kind of print messages so I think if we just do like set level or something I really wish this would help me out I think that level of the right yep set level and then the actual log level and again Visual Studio has just decided to not work at all so let's just go here and see what it is as we did a lower level level and then we have a level enum which i think is sort of tres is the kind of print everything thing so we'll just do trace like that and then we'll do the same thing for clients okay so now we're printing all messages from both of these loggers probably a good idea to also expose this so that we can actually set our level to whatever we actually want it to be but for now we'll just keep it at trace I'll hit ctrl f7 to compile this file make sure everything is fine okay so we get a city color empty is not a member of SPD log I think what we actually need to do is include another file which is this syncs file so let's go ahead and click this just in LCVP file and there you go everything compiled successfully alright so now I want to actually use this stuff in our client so what we could do right and I will do this kind of as a test for now in log in it this obviously this function obviously needs to get called somewhere so what I got a call I don't really want to call this in our entry point although I guess we will for now we do need to kind of have like a system initialization kind of function or something in which the engine actually is initialized but for now again I will call this in here this remember gets included into sandbox that's an important note to make as well but I'll just say hazel log in it okay and if we go into hazel dot H I will of course include log yeah so we'll do include hazel log so if I build my sandbox project now this should work and if I hit f5 I think it'll just kind of terminate why not let's maybe stick a breakpoint here and hit f5 okay now I need to copy that DLL we really need to make a post build copy step we will do that next time though I'm going to go into bin-debug hazel DLL copy into sandbox for place and f5 okay so it's rotting this exists but I forgot that we had that that while true loop Logan it seems to work so maybe now let's try and use something we'll say get a poor logger and then I guess well it's just to a warm because that should be out yellow will say initialized log ok and then I'm also going to do the same thing but with the client logger and we'll make this just a what's another one infer having that's great so hello so we should get two different kind of messages from two different loggers here ok cool so you can see we got a yellow message it says initialize log and it says that is from hazel and then from app we get a hello printing and we also have the timestamp which is cool all right so how log is basically done now here's the issue I don't want to call this every time right hazel log get get call log on board that's really kind of annoying what I want to do instead is create and mouse macros that make this really easy to kind of use ok so what I'm going to do is outside here I'm gonna make a bunch of defiance and then this basically going to just be define age said for and then the log kind of severity so I don't know why this is already kind of here I'm no idea what else that's can't be coming from anyway I probably just type that close sometime in my life so what we'll say ages ed core and then era for example double dot right because we're gonna have a very a number of arguments and then when it's going to pull hazel log gets poor lager because that's H that core error and then we'll say error and then underscore honest for VA arcs right which is just forwarding our variable arguments that we had in our macro to our actual function okay and that's that we're not going to put a semicolon or anything because we'll do that after we use the macro but that's basically it right and if you wanted to you could wrap this in another macro that only enabled it under certain circumstances maybe well that would be definitely important because we want to strip out all of our log messages in distribution versions obviously we don't want to we don't we don't want to be wasting any kind of performance logging messages to the console that's probably not even going to be visible when we distribute our actual applications okay but we'll deal with that later so we have poor error we'll do probably warn info and trace I think is probably gonna be enough so era warned in fur and a trace okay so trace will be traced this will be inferred there's also a fatal one but what I'm gonna worry about that I think now and one let's kind of organize these in order of severity so we'll do trace info one error and in fact you know what I might as well do fatal because I think I'm going to want to use that for a certain messages or something like that perhaps so fatal okay cool and I will kind of just nicely aligned this that I want to use tabs or anything because that can not work depending on your tab size let's just use the spacebar here to make sure they're nicely aligned and we have all of our kind of core logging I will say or log macros okay and then we're gonna do some client ones so clients log macro so we're gonna copy all of these and the only difference is going to be the fact that they don't say call will actually strip that entirely it'll just be edges at trays and all that stuff going to align these lips align these like that and then instead of core Locker I'm going to just use client logo okay and that's it there we go we've got all of our different ones I hopefully I didn't make any mistakes here tracing for a one-hour fatal for both of these looks great now I'm just going to go back into our entry point and instead of this now you can see this is just going to come aged said core warned okay and then this just becomes H said info okay let's just print like a variable or something just to make sure that works into a equals five okay because that should work as well of course we should have variable messages of rather variable kind of arguments that we can actually pass in here let's hit a five and see what happens and we only modified the header files of course we don't need to copy that DLL okay there we go Mitchell eyes log hello VAR equals five you can see everything works correctly and it was really easy and it looks really nice now and the other obviously the other requirement is being a macro which I forgot to mention but I kind of did just then was that if this isn't a macro it's a function that always gets called but if it's a macro it means we can strip it from distribution bills so if I just basically say you know if this is a disc build I can define this to be nothing just like that and that means that that gets stripped from the actual build and he's not included in the binary which means that we're not running this in distribution bills which is very very important that's probably the main reason not just to make our lives easier but for actually stripping code out when required so anyway that's kind of that we do definitely need some kind of system initialization kind of function so hazel in it or something hazel core in it or something like that we'll talk about that next time for sure because as we start to initialize certain things we definitely don't want to be doing this in the kind of main function that it gets included into our app we want to do that somewhere in the core engine and then also I'm getting really sick of this kind of DLL not being copied so I think we're actually going to switch to using a build system next time so that should be fun anyway hope you guys enjoyed this video if you did give me the like we've now got a great logging library that we can actually use that's going to be really important I wanted to get that in there as soon as possible because now we have a proper way to start giving feedback as to what's going on to the actual console which is gonna be just so useful for pretty much everything huge thank there's always to all the patrons that make this possible patron for such the churner is that link you can help support the series it really does help me kind of make videos wouldn't be here without you guys a huge thank you and you'll get access to much much more source code than you see in these videos because as I'm kind of making these videos I'm also actually writing the hazel engine on the side and kind of as quick as I ride it is as like that's the source code that you get so as I'm writing it and might be commits patrons get that source code immediately so definitely check that out if you're interested next time we're probably going to use finally switched using a build system because first of all I want to start getting this code probably working on Mac and Linux as well because I know there's a fair few of you guys who are using that as I said I am gonna write a kind of Windows only to begin with in terms of the just I'm going to implement the Windows platform only the engine will still be structured in a way that supports multiple platforms but I do want to have like since people have been like oh but I'm using Mac I'm using Linux it is generally speaking a good idea to be able to build this code easily on Mac and Linux so that's why I want to start using a build system and also we can like I mean you know as soon as we start kind of actually modifying our project files by adding so many include parts and also like a post build copy step for example which we need to copy that dll automatically instead of adding that stuff to Visual Studio manually it's better to just finally dump that into an actual build system kind of file essentially a configuration file so that we don't have to then copy everything across later as our engine and project files get more complicated anyway have you guys in this video as always thank you for watching I'll see you next time goodbye you [Music]
Info
Channel: The Cherno
Views: 107,513
Rating: undefined out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, game engine, how to make a game engine, game engine series
Id: dZr-53LAlOw
Channel Id: undefined
Length: 30min 5sec (1805 seconds)
Published: Sun Nov 11 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.