From 000fe9b64820a1fedf1149304e7b207f80a457b7 Mon Sep 17 00:00:00 2001 From: Uygar Yilmaz Date: Mon, 10 Aug 2026 12:41:31 -0400 Subject: [PATCH 1/3] Adding a Debugging section. Starting with adding basic information and examples about logging. Minor improvements. --- articles/getting_started/debugging.md | 76 +++++++++++++++++++ articles/getting_started/index.md | 1 + .../snippets/debug_logging_simple.cs | 14 ++++ .../snippets/debug_output_type.csproj | 2 + .../snippets/default_game_platform.csproj | 33 ++++++++ .../snippets/default_output_type.csproj | 1 + .../snippets/default_program.cs | 4 + .../program_with_consoletracelistener.cs | 7 ++ .../program_with_textwritertracelistener.cs | 40 ++++++++++ articles/toc.yml | 4 +- pdf/articles/toc.yml | 2 + 11 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 articles/getting_started/debugging.md create mode 100644 articles/getting_started/snippets/debug_logging_simple.cs create mode 100644 articles/getting_started/snippets/debug_output_type.csproj create mode 100644 articles/getting_started/snippets/default_game_platform.csproj create mode 100644 articles/getting_started/snippets/default_output_type.csproj create mode 100644 articles/getting_started/snippets/default_program.cs create mode 100644 articles/getting_started/snippets/program_with_consoletracelistener.cs create mode 100644 articles/getting_started/snippets/program_with_textwritertracelistener.cs diff --git a/articles/getting_started/debugging.md b/articles/getting_started/debugging.md new file mode 100644 index 00000000..337ad6f8 --- /dev/null +++ b/articles/getting_started/debugging.md @@ -0,0 +1,76 @@ +--- +title: Debugging +description: During development, debugging a MonoGame project is essentially no different than debugging any other .NET project for the most cases, although graphics related debugging or troubleshooting can require the use of external tools. +--- + +When a game is under development, the developer usually needs some logging or tracing capabilities in order to troubbleshoot or debug the game. In addition to some basic logs output by the MonoGame framework itself, developers will likely need additional logging while they work on their games. + +## Enabling Console Window During Debugging + +When a MonoGame solution is created via one of the available templates, the project file or files that host the main game window are set up to use `WinExe` as the `OutputType`. This simply means the application has its own window that will display the game contents, with non interaction with the console or shell the underlying operating system provides. + +The default platform project (`SolutionName.DesktopVK.csproj`, `SolutionName.WindowsDX12.csproj`, etc.) as it is created by the template would look like this: + +[!code-xml[](./snippets/default_game_platform.csproj)] + +Locate this line that sets the `OutputType` property in the project file: + +[!code-xml[](./snippets/default_output_type.csproj)] + +If we replace this line with a couple of conditional lines that set the `OutputType` property based on the build configuration, we can have a console window appear when debugging, while not having one when creating a release build. + +[!code-xml[](./snippets/debug_output_type.csproj)] + +In the example above, when the game is run in `Debug` mode, a console window will appear before the actual game window, with all the logging visible to the developer. When the game is run in `Release` mode, the game is built + +> [!NOTE] +> *Leaving the `OutputType` as `WinExe` for a release build is generally a bad idea. This will cause the game to open up a console window in addition to the actual game window, which is generally not a wanted behavior for most games from the perspective of the player. This is why, the default behavior for any `Release` build should be to set it to `WinExe`.* + +## Adding Additional Logging + +The developers can add logging/tracing capabilities to their games using a number of open source libraries that are widely available across the .NET ecosystem, or by building their custom logging implementations. +One easy way of having basic logging/tracing facilities in your game would be to rely on the standard methods in the `System.Diagnostics` namespace that comes with the .NET runtime as part of the base class library. The example below shows how this can be done: + +[!code-csharp[](./snippets/debug_logging_simple.cs)] + +In the example above, we're using this method to log information: `Debug.WriteLine()`
+We could also use this method to have a similar result: `Trace.TraceInformation()` +But we should generally avoid this for the reasons we will explain in a bit. + +But it is important to know the difference between the methods on the `Debug` and `Trace` classes: +* The methods on the `Debug` class will not be compiled into a Release build. This means, logs coming through these methods will not be output in a `Release` build, and all `Debug.Write()`, `Debug.WriteLine()` and similar calls will be stripped from the final executable, which makes them a good way of having logs when working on your game. +* The methods on the `Trace` class will be compiled into ***both** `Debug` and `Release` builds*, and that will allow you to have logs in the games you have shipped. + +However, simply calling these methods will not be enough to actually display these log entries in the console window you enable in your MonoGame project through the changes in the project file. By default, the output of these methods will be directed to the output of the IDE you're using for development (e.g. Visual Studio), but they will not be directed to the console window. +In order to have them displayed in a console window, you will need to register a custom `TraceListener` in your game. The default `Program.cs` file for a MonoGame project doesn't include this, but it's very easy to add. This is how a default `Program.cs` file looks like: + +[!code-csharp[](./snippets/default_program.cs)] + +Using the example below, we will now register a `ConsoleTraceListener`in the `Program.cs` to direct the output of the logging methods to the console window: + +[!code-csharp[](./snippets/program_with_consoletracelistener.cs)] + +Once this is done, any logs you write with methods like `Debug.WriteLine()`, `Trace.TraceInformation()`, `Trace.TraceError()`, etc. will be visible in the console window, as long as you are running the game in the `Debug` mode. + +> [!NOTE] +> *The code example above uses top-level statements which is the default for MonoGame project templates. If you are using an older template, you might need to add the code to the `Main` method of your `Program.cs` file instead.* + +> [!WARNING] +> *Having logs in hot-paths like the `Update()` method will generate a significant overhead and will decrease your game's performance, in addition to causing pressure on the garbage collector, which in turn can end up causing stutter. +> +> Thus, make sure to add logging in the relevant methods that only get called when certain things happen in-game. +> And for the same reason, always prefer using `Debug.WriteLine()` over `Trace.TraceInformation()` unless you actually need that particular log in the release builds. +> +> Because even if there is no console window to direct these logs to, `Trace.TraceInformation()` and similar methods will still incur a performance penalty in the release builds.* + +## Advanced Logging + +So far we have only considered a basic logging scenario where the logs will be visible in the console window. This is also why we rely exclusively on `Debug.WriteLine()`, since the console window is not visible in the Release builds. +But there can be scenarios when the developers might need more advanced logging capabilities for their games that are already shipped. For example, we may want to write a log file when the game crashes with an exception, which can be used by the players to report the issue to us. + +For this purpose, we can register a `TextWriterTraceListener` or a custom other trace listener implementation that suits our needs. Here's how we can modify the `Program.cs` file to write logs to a file on the disk: + +[!code-csharp[](./snippets/program_with_textwritertracelistener.cs)] + +In this example, any exception that is not handled in the game itself through a `try/catch` block bubbles up to the top-level `Main` method where it's caught and logged to a file on the disk. +We can then ask players to send us these log files if they encounter crashes during gameplay. \ No newline at end of file diff --git a/articles/getting_started/index.md b/articles/getting_started/index.md index bfc747ee..627c3881 100644 --- a/articles/getting_started/index.md +++ b/articles/getting_started/index.md @@ -47,5 +47,6 @@ By the end of this tutorial set, you will have a working project to build for yo ### 4. Advanced Topics +- [Debugging](debugging.md) - [Preparing for Consoles](preparing_for_consoles.md) - [Using Development Nuget Packages](using_development_nuget_packages.md) diff --git a/articles/getting_started/snippets/debug_logging_simple.cs b/articles/getting_started/snippets/debug_logging_simple.cs new file mode 100644 index 00000000..e2ba4b3f --- /dev/null +++ b/articles/getting_started/snippets/debug_logging_simple.cs @@ -0,0 +1,14 @@ +protected void ConnectToHost() +{ + Debug.WriteLine($"{DateTime.UtcNow:s}::User {_user.Id} is connecting to host..."); + + var connectionResult = _networkService.ConnectToHost(_user); + if (connectionResult.State == ConnectionState.Success) + { + Debug.WriteLine($"{DateTime.UtcNow:s}::User connected to host {connectionResult.Host}."); + } + else + { + Debug.WriteLine($"{DateTime.UtcNow:s}::User failed to connect to host {connectionResult.Host}.\nConnection state: {connectionResult.State}\nState: {connectionResult.State}, Exception: {connectionResult.Exception}"); + } +} \ No newline at end of file diff --git a/articles/getting_started/snippets/debug_output_type.csproj b/articles/getting_started/snippets/debug_output_type.csproj new file mode 100644 index 00000000..973d0294 --- /dev/null +++ b/articles/getting_started/snippets/debug_output_type.csproj @@ -0,0 +1,2 @@ +Exe +WinExe \ No newline at end of file diff --git a/articles/getting_started/snippets/default_game_platform.csproj b/articles/getting_started/snippets/default_game_platform.csproj new file mode 100644 index 00000000..53126c64 --- /dev/null +++ b/articles/getting_started/snippets/default_game_platform.csproj @@ -0,0 +1,33 @@ + + + WinExe + net10.0 + Major + false + false + DesktopVK + + + app.manifest + Icon.ico + + + + + + + + Icon.ico + + + Icon.bmp + + + + + + + + + + \ No newline at end of file diff --git a/articles/getting_started/snippets/default_output_type.csproj b/articles/getting_started/snippets/default_output_type.csproj new file mode 100644 index 00000000..bd9d5588 --- /dev/null +++ b/articles/getting_started/snippets/default_output_type.csproj @@ -0,0 +1 @@ +WinExe \ No newline at end of file diff --git a/articles/getting_started/snippets/default_program.cs b/articles/getting_started/snippets/default_program.cs new file mode 100644 index 00000000..2128ee7f --- /dev/null +++ b/articles/getting_started/snippets/default_program.cs @@ -0,0 +1,4 @@ +using FooBar.Game; + +using var game = new GameClass(); +game.Run(); diff --git a/articles/getting_started/snippets/program_with_consoletracelistener.cs b/articles/getting_started/snippets/program_with_consoletracelistener.cs new file mode 100644 index 00000000..9f454575 --- /dev/null +++ b/articles/getting_started/snippets/program_with_consoletracelistener.cs @@ -0,0 +1,7 @@ +using System.Diagnostics; +using FooBar.Game; + +Trace.Listeners.Add(new ConsoleTraceListener()); + +using var game = new GameClass(); +game.Run(); diff --git a/articles/getting_started/snippets/program_with_textwritertracelistener.cs b/articles/getting_started/snippets/program_with_textwritertracelistener.cs new file mode 100644 index 00000000..da1b29f7 --- /dev/null +++ b/articles/getting_started/snippets/program_with_textwritertracelistener.cs @@ -0,0 +1,40 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using FooBar.Game; + +namespace FooBar; +public class Program +{ + public static void Main(string[] args) + { + Trace.Listeners.Add(new ConsoleTraceListener()); + Trace.Listeners.Add(new TextWriterTraceListener($"FooBar_CrashLog_{DateTime.UtcNow:yyyy-MM-dd_HH-mm-ss}.log") + { + Name = "CrashLogger", + Filter = new EventTypeFilter(SourceLevels.Critical | SourceLevels.Error), + }); + Trace.AutoFlush = true; + + // Catch exceptions on the main thread. + AppDomain.CurrentDomain.UnhandledException += (sender, exArgs) => + { + var ex = exArgs.ExceptionObject as Exception; + LogFatalException($"Unhandled Exception from sender: {sender}\nException: {ex?.Message}\n{ex?.StackTrace}"); + }; + + // Catch exceptions from background tasks/threads. + TaskScheduler.UnobservedTaskException += (sender, exArgs) => + { + LogFatalException($"Unobserved Task Exception from sender: {sender}\nException: {exArgs.Exception.Message}\n{exArgs.Exception.StackTrace}"); + }; + + using var game = new GameClass(); + game.Run(); + } + + private static void LogFatalException(string errorMessage) + { + Trace.TraceError(errorMessage); + } +} diff --git a/articles/toc.yml b/articles/toc.yml index afffdb73..e85c3263 100644 --- a/articles/toc.yml +++ b/articles/toc.yml @@ -59,6 +59,8 @@ items: href: getting_to_know/howto/input/index.md - name: Advanced Topics items: + - name: Debugging + href: getting_started/debugging.md - name: Packaging href: getting_started/packaging_games.md - name: Preparing for consoles @@ -187,7 +189,7 @@ items: - name: "09: Shadow Effect" href: tutorials/advanced/2d_shaders/09_shadows_effect/index.md - name: "10: Next Steps" - href: tutorials/advanced/2d_shaders/10_next_steps/index.md + href: tutorials/advanced/2d_shaders/10_next_steps/index.md - name: Console Access href: console_access.md - name: Help and Support diff --git a/pdf/articles/toc.yml b/pdf/articles/toc.yml index be6ce2e9..d7c5966d 100644 --- a/pdf/articles/toc.yml +++ b/pdf/articles/toc.yml @@ -53,6 +53,8 @@ items: href: ../../articles/getting_to_know/howto/input/index.md - name: Advanced Topics items: + - name: Debugging + href: ../../articles/getting_started/debugging.md - name: Packaging href: ../../articles/getting_started/packaging_games.md - name: Preparing for consoles From b6560ce79f0006597453de58c059b613c287121e Mon Sep 17 00:00:00 2001 From: Uygar Yilmaz Date: Mon, 10 Aug 2026 13:20:47 -0400 Subject: [PATCH 2/3] Adding optional port argument for the serve scripts. 8080 is already in use in my env, and I suspect there will be more folks who are in a similar situation. --- serve.ps1 | 12 +++++++++++- serve.sh | 6 +++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/serve.ps1 b/serve.ps1 index 56d27fe0..d48b473f 100644 --- a/serve.ps1 +++ b/serve.ps1 @@ -1,3 +1,8 @@ +param ( + # Accepts an optional port number as the first argument. + [int]$Port +) + # Exit on any error $ErrorActionPreference = "Stop" @@ -5,4 +10,9 @@ $ErrorActionPreference = "Stop" .\build.ps1 # Start DocFx serve -dotnet docfx serve .\_site \ No newline at end of file +if ($Port) { + dotnet docfx serve .\_site -p $Port +} +else { + dotnet docfx serve .\_site +} \ No newline at end of file diff --git a/serve.sh b/serve.sh index 75a0d906..eddd7b9a 100755 --- a/serve.sh +++ b/serve.sh @@ -6,4 +6,8 @@ set -e ./build.sh # Start DocFx serve -dotnet docfx serve _site \ No newline at end of file +if [ -n "$1" ]; then + dotnet docfx serve _site -p "$1" +else + dotnet docfx serve _site +fi \ No newline at end of file From 20cb9d4d38eb2971d10a38c648898709623ecda7 Mon Sep 17 00:00:00 2001 From: Uygar Yilmaz Date: Mon, 10 Aug 2026 13:21:54 -0400 Subject: [PATCH 3/3] Cleanup. Further cleanup. Fixing type and clarifying reason. Cleanup. Fixing and clarifying things. Further clarification. Yet more clarification. Cleanup. Neverending cleanups. Yet another typo fixed. Making Debugging a category. Will add further content in this category. Updating summary. Fixing typo. Adding some warnings. Further clarification. --- articles/getting_started/index.md | 2 +- .../{debugging.md => logging.md} | 36 ++++++++++++------- .../snippets/debug_logging_simple.cs | 2 +- .../program_with_textwritertracelistener.cs | 9 ++--- articles/toc.yml | 4 ++- pdf/articles/toc.yml | 4 ++- 6 files changed, 33 insertions(+), 24 deletions(-) rename articles/getting_started/{debugging.md => logging.md} (60%) diff --git a/articles/getting_started/index.md b/articles/getting_started/index.md index 627c3881..506826b6 100644 --- a/articles/getting_started/index.md +++ b/articles/getting_started/index.md @@ -47,6 +47,6 @@ By the end of this tutorial set, you will have a working project to build for yo ### 4. Advanced Topics -- [Debugging](debugging.md) +- [Debugging](logging.md) - [Preparing for Consoles](preparing_for_consoles.md) - [Using Development Nuget Packages](using_development_nuget_packages.md) diff --git a/articles/getting_started/debugging.md b/articles/getting_started/logging.md similarity index 60% rename from articles/getting_started/debugging.md rename to articles/getting_started/logging.md index 337ad6f8..e281e878 100644 --- a/articles/getting_started/debugging.md +++ b/articles/getting_started/logging.md @@ -1,13 +1,14 @@ --- -title: Debugging -description: During development, debugging a MonoGame project is essentially no different than debugging any other .NET project for the most cases, although graphics related debugging or troubleshooting can require the use of external tools. +title: Logging +description: During development, debugging a MonoGame project is essentially no different than debugging any other .NET project for the most cases, although graphics related debugging or troubleshooting can require the use of external tools. Logging can be a very useful tool during this process. --- -When a game is under development, the developer usually needs some logging or tracing capabilities in order to troubbleshoot or debug the game. In addition to some basic logs output by the MonoGame framework itself, developers will likely need additional logging while they work on their games. +When a game is under development, the developer usually needs some logging or tracing capabilities in order to troubleshoot or debug the game. In addition to some basic logs output by the MonoGame framework itself, developers will likely need additional logging while they work on their games. ## Enabling Console Window During Debugging -When a MonoGame solution is created via one of the available templates, the project file or files that host the main game window are set up to use `WinExe` as the `OutputType`. This simply means the application has its own window that will display the game contents, with non interaction with the console or shell the underlying operating system provides. +When a MonoGame solution is created via one of the available templates, the project file or files that host the main game window are set up to use `WinExe` as the `OutputType`. This simply means the application has its own window that will display the game contents, with no interaction with the console or shell the underlying operating system provides.
+This means even when the game is launched from a console instance, it will not display any output in said console. A side effect of this is that when the game outputs logs to the console, it will not be visible to the developer outside the IDE integration. The default platform project (`SolutionName.DesktopVK.csproj`, `SolutionName.WindowsDX12.csproj`, etc.) as it is created by the template would look like this: @@ -21,10 +22,13 @@ If we replace this line with a couple of conditional lines that set the `OutputT [!code-xml[](./snippets/debug_output_type.csproj)] -In the example above, when the game is run in `Debug` mode, a console window will appear before the actual game window, with all the logging visible to the developer. When the game is run in `Release` mode, the game is built +With this change, the game will start interacting with the OS console: +* In the example above, when the game is run in `Debug` mode, a console window will appear before the actual game window, with all the logging visible to the developer.
+In this more, if the game is launched from an existing console window, no new console window will be instantiated, and the interaction with the game will stay in said console instead. +* When the game is run in `Release` mode, the game window will be the only window that opens up, and no iteraction with the console will take place. > [!NOTE] -> *Leaving the `OutputType` as `WinExe` for a release build is generally a bad idea. This will cause the game to open up a console window in addition to the actual game window, which is generally not a wanted behavior for most games from the perspective of the player. This is why, the default behavior for any `Release` build should be to set it to `WinExe`.* +> Leaving the `OutputType` as `WinExe` for a release build is generally a bad idea. This will cause the game to open up a console window in addition to the actual game window, which is generally not a wanted behavior for most games from the perspective of the player. This is why, the default behavior for any `Release` build should be to set it to `WinExe`. ## Adding Additional Logging @@ -35,7 +39,6 @@ One easy way of having basic logging/tracing facilities in your game would be to In the example above, we're using this method to log information: `Debug.WriteLine()`
We could also use this method to have a similar result: `Trace.TraceInformation()` -But we should generally avoid this for the reasons we will explain in a bit. But it is important to know the difference between the methods on the `Debug` and `Trace` classes: * The methods on the `Debug` class will not be compiled into a Release build. This means, logs coming through these methods will not be output in a `Release` build, and all `Debug.Write()`, `Debug.WriteLine()` and similar calls will be stripped from the final executable, which makes them a good way of having logs when working on your game. @@ -46,22 +49,22 @@ In order to have them displayed in a console window, you will need to register a [!code-csharp[](./snippets/default_program.cs)] -Using the example below, we will now register a `ConsoleTraceListener`in the `Program.cs` to direct the output of the logging methods to the console window: +Using the example below, we will now register a `ConsoleTraceListener` in the `Program.cs` to direct the output of the logging methods to the console window: [!code-csharp[](./snippets/program_with_consoletracelistener.cs)] Once this is done, any logs you write with methods like `Debug.WriteLine()`, `Trace.TraceInformation()`, `Trace.TraceError()`, etc. will be visible in the console window, as long as you are running the game in the `Debug` mode. > [!NOTE] -> *The code example above uses top-level statements which is the default for MonoGame project templates. If you are using an older template, you might need to add the code to the `Main` method of your `Program.cs` file instead.* +> The code example above uses top-level statements which is the default for MonoGame project templates. If you are using an older template, you might need to add the code to the `Main` method of your `Program.cs` file instead. > [!WARNING] -> *Having logs in hot-paths like the `Update()` method will generate a significant overhead and will decrease your game's performance, in addition to causing pressure on the garbage collector, which in turn can end up causing stutter. +> Having logs in hot-paths like the `Update()` method will generate a significant overhead and will decrease your game's performance, in addition to causing pressure on the garbage collector, which in turn can end up causing stutter. > > Thus, make sure to add logging in the relevant methods that only get called when certain things happen in-game. > And for the same reason, always prefer using `Debug.WriteLine()` over `Trace.TraceInformation()` unless you actually need that particular log in the release builds. > -> Because even if there is no console window to direct these logs to, `Trace.TraceInformation()` and similar methods will still incur a performance penalty in the release builds.* +> Because even if there is no console window to direct these logs to, `Trace.TraceInformation()` and similar methods will still incur a performance penalty in the release builds. ## Advanced Logging @@ -72,5 +75,12 @@ For this purpose, we can register a `TextWriterTraceListener` or a custom other [!code-csharp[](./snippets/program_with_textwritertracelistener.cs)] -In this example, any exception that is not handled in the game itself through a `try/catch` block bubbles up to the top-level `Main` method where it's caught and logged to a file on the disk. -We can then ask players to send us these log files if they encounter crashes during gameplay. \ No newline at end of file +In this example, any exception that is not handled in the game itself through a `try/catch` block bubbles up to the top-level `Main` method where it's caught and logged to a file on the disk. In addition to that, any log entry we created via `Trace.TraceError()` in game will also be written to this same log file.
+We can then ask players to send us these log files if they encounter crashes during gameplay. + +Going even further, we can even build a custom trace listener that inherits from `System.Diagnostics.TraceListener` to forward error logs to an API, which can be useful for having an overview of the bugs your game is encountering in real-time. + +> [!WARNING] +> Setting `Trace.AutoFlush` to `true` will make sure Debug and Trace logs to be flushed to disk before the game crashes, but it will also turn the `Debug.WriteLine()`, `Trace.TraceWarning()` and similar calls into blocking calls, impacting the game's performance. This is good enough for Debug logs, or for crash logs in a Release build. But if we have further trace logging active in-game, this can impact performance. +> +> In that scenario, we should ideally avoid this, and implement our own trace listener to perform async writes to disk or to an API in a background thread. \ No newline at end of file diff --git a/articles/getting_started/snippets/debug_logging_simple.cs b/articles/getting_started/snippets/debug_logging_simple.cs index e2ba4b3f..2c643bf7 100644 --- a/articles/getting_started/snippets/debug_logging_simple.cs +++ b/articles/getting_started/snippets/debug_logging_simple.cs @@ -9,6 +9,6 @@ protected void ConnectToHost() } else { - Debug.WriteLine($"{DateTime.UtcNow:s}::User failed to connect to host {connectionResult.Host}.\nConnection state: {connectionResult.State}\nState: {connectionResult.State}, Exception: {connectionResult.Exception}"); + Debug.WriteLine($"{DateTime.UtcNow:s}::User failed to connect to host {connectionResult.Host}.\nConnection state: {connectionResult.State}, Exception: {connectionResult.Exception}"); } } \ No newline at end of file diff --git a/articles/getting_started/snippets/program_with_textwritertracelistener.cs b/articles/getting_started/snippets/program_with_textwritertracelistener.cs index da1b29f7..a85bd9e9 100644 --- a/articles/getting_started/snippets/program_with_textwritertracelistener.cs +++ b/articles/getting_started/snippets/program_with_textwritertracelistener.cs @@ -20,21 +20,16 @@ public static void Main(string[] args) AppDomain.CurrentDomain.UnhandledException += (sender, exArgs) => { var ex = exArgs.ExceptionObject as Exception; - LogFatalException($"Unhandled Exception from sender: {sender}\nException: {ex?.Message}\n{ex?.StackTrace}"); + Trace.TraceError($"Unhandled Exception from sender: {sender}\nException: {ex?.Message}\n{ex?.StackTrace}"); }; // Catch exceptions from background tasks/threads. TaskScheduler.UnobservedTaskException += (sender, exArgs) => { - LogFatalException($"Unobserved Task Exception from sender: {sender}\nException: {exArgs.Exception.Message}\n{exArgs.Exception.StackTrace}"); + Trace.TraceError($"Unobserved Task Exception from sender: {sender}\nException: {exArgs.Exception.Message}\n{exArgs.Exception.StackTrace}"); }; using var game = new GameClass(); game.Run(); } - - private static void LogFatalException(string errorMessage) - { - Trace.TraceError(errorMessage); - } } diff --git a/articles/toc.yml b/articles/toc.yml index e85c3263..f8ce4fb6 100644 --- a/articles/toc.yml +++ b/articles/toc.yml @@ -60,7 +60,9 @@ items: - name: Advanced Topics items: - name: Debugging - href: getting_started/debugging.md + items: + - name: Logging + href: getting_started/logging.md - name: Packaging href: getting_started/packaging_games.md - name: Preparing for consoles diff --git a/pdf/articles/toc.yml b/pdf/articles/toc.yml index d7c5966d..6adf49c8 100644 --- a/pdf/articles/toc.yml +++ b/pdf/articles/toc.yml @@ -54,7 +54,9 @@ items: - name: Advanced Topics items: - name: Debugging - href: ../../articles/getting_started/debugging.md + items: + - name: Logging + href: ../../articles/getting_started/debugging.md - name: Packaging href: ../../articles/getting_started/packaging_games.md - name: Preparing for consoles