Exercise - Logging and tracing

Completed

Now that the application is starting development, it's good to add more diagnostics to the logic to help developers as they add new features. We can use our new knowledge of debug diagnostics to do this task.

Write to the debug console

Before we debug the application, let's add more debug diagnostics. Further diagnostics can help diagnose the application while it's being run under debug.

  1. At the top of the Program.cs file, add a new using statement to bring in System.Diagnostics so we can use the Debug methods.

    using System.Diagnostics;
    
  2. Add WriteLine statements at the start of the Fibonacci method to get clarity when you debug through the code.

    Debug.WriteLine($"Entering {nameof(Fibonacci)} method");
    Debug.WriteLine($"We are looking for the {n}th number");
    
  3. At the end of our for loop, we could output every value. Or, we could use a conditional print statement by using WriteIf or WriteLineIf. Add a print line only when sum is 1 at the end of the for loop.

    for (int i = 2; i <= n; i++)
    {                  
        sum = n1 + n2;
        n1 = n2;
        n2 = sum;
        Debug.WriteLineIf(sum == 1, $"sum is 1, n1 is {n1}, n2 is {n2}");    
    }
    
  4. Debug the application. You should get the following output:

    Entering Fibonacci method
    We are looking for the 5th number
    sum is 1, n1 is 1, n2 is 1
    

Check for conditions with Assert

In some situations, you might want to stop the entire running application when a certain condition isn't met. By using Debug.Assert, you can check for a condition and output additional information about the state of the application. Let's add a check right before the return statement to ensure n2 is 5.

// If n2 is 5 continue, else break.
Debug.Assert(n2 == 5, "The return value is not 5 and it should be.");
return n == 0 ? n1 : n2;

Our application logic is already correct, so let's update our Fibonacci(5); to Fibonacci(6);, which generates a different result.

Debug the application. When Debug.Assert is run in the code, the debugger stops the application so you can inspect variables, watch window, call stack, and more. It also outputs the message to the debug console.

---- DEBUG ASSERTION FAILED ----
---- Assert Short Message ----
The return value is not 5 and it should be.
---- Assert Long Message ----

   at Program.<<Main>$>g__Fibonacci|0_0(Int32 n) in C:\Users\Jon\Desktop\DotNetDebugging\Program.cs:line 23
   at Program.<Main>$(String[] args) in C:\Users\Jon\Desktop\DotNetDebugging\Program.cs:line 3

Stop debugging, then run the application without debug by entering the following command in the terminal.

dotnet run

The application is terminated after the assertion fails and information is logged to the application output.

Process terminated. Assertion failed.
The return value is not 5 and it should be.
   at Program.<<Main>$>g__Fibonacci|0_0(Int32 n) in C:\Users\Jon\Desktop\DotNetDebugging\Program.cs:line 23
   at Program.<Main>$(String[] args) in C:\Users\Jon\Desktop\DotNetDebugging\Program.cs:line 3

Now, let's run the application in Release configuration with the following command in the terminal.

dotnet run --configuration Release

The application successfully runs to completion because we're no longer in the Debug configuration.

Congratulations, you successfully and efficiently debugged code by using features of .NET, which include Debug.WriteLine and Debug.Assert. Well done!