[C#] How to Get Detailed Information When an Exception Occurs: Using Message, StackTrace, and TargetSite

During application operation, if an unexpected error occurs, simply displaying “An error occurred” makes it difficult to identify the cause.

C# exception objects (the Exception class and its derived classes) contain detailed information as properties that help investigate the cause of errors.

Here, assuming a case where a division by zero error occurs during a KPI (Key Performance Indicator) calculation process, I will explain how to retrieve information such as “error content,” “location of occurrence,” and “method name” from the exception object and output it to a log.

目次

Key Properties of the Exception Object

By accessing the following properties through the exception variable (usually named ex or e) caught in the catch block, you can obtain detailed information.

  • Message: A summary description of the error (e.g., “Attempted to divide by zero.”).
  • StackTrace: The method call history at the time of the error (Stack Trace). This is the most important piece of information for identifying which line caused the error.
  • Source: The name of the application or object that caused the exception.
  • TargetSite: Information about the method that threw the exception (Reflection information).

Practical Code Example: Error Analysis in a Sales Analysis System

The following code is a program that calculates a store’s “Average Spend per Customer (Sales / Visitor Count).” It catches the DivideByZeroException that occurs when the visitor count becomes “0” due to a data defect and outputs detailed information to the console.

using System;

namespace StoreAnalysis
{
    class Program
    {
        static void Main()
        {
            // Scenario:
            // Batch processing to calculate average spend from store POS data.
            // Due to data inconsistency, data with 0 visitors was mixed in.

            int dailySales = 150000; // Sales Amount
            int visitorCount = 0;    // Visitor Count (Cause of error)

            try
            {
                // Call the average spend calculation process
                int avgSpend = CalculateAverageSpend(dailySales, visitorCount);
                Console.WriteLine($"Average Spend: {avgSpend:C}");
            }
            catch (DivideByZeroException ex)
            {
                // Get detailed information from the exception object (ex) and output it
                Console.WriteLine("=== Error Report ===");
                
                // 1. Error Message (What happened)
                Console.WriteLine($"[Message]    : {ex.Message}");
                
                // 2. Source Application Name
                Console.WriteLine($"[Source]     : {ex.Source}");
                
                // 3. Method name where the exception occurred
                // * TargetSite can be null, so it is safe to check for null
                if (ex.TargetSite != null)
                {
                    Console.WriteLine($"[TargetSite] : {ex.TargetSite}");
                }

                // 4. Stack Trace (Where it happened)
                Console.WriteLine($"[StackTrace] :\n{ex.StackTrace}");
            }
            catch (Exception ex)
            {
                // Other unexpected errors
                Console.WriteLine($"[Critical Error] {ex.Message}");
            }
        }

        // Method to calculate average spend
        static int CalculateAverageSpend(int sales, int visitors)
        {
            // If the denominator is 0 in integer division, a DivideByZeroException occurs here
            return sales / visitors;
        }
    }
}

Execution Result

=== Error Report ===
[Message]    : Attempted to divide by zero.
[Source]     : StoreAnalysis
[TargetSite] : Int32 CalculateAverageSpend(Int32, Int32)
[StackTrace] :
   at StoreAnalysis.Program.CalculateAverageSpend(Int32 sales, Int32 visitors) in C:\Work\StoreAnalysis\Program.cs:line 53
   at StoreAnalysis.Program.Main() in C:\Work\StoreAnalysis\Program.cs:line 19

Technical Points and Precautions

1. Importance of StackTrace

StackTrace is the most useful tool in debugging. As shown in the execution result above, it records “which file,” “which line,” and “which method” was called. When outputting errors to a log file, implementing it to always include StackTrace in addition to Message dramatically improves troubleshooting speed.

2. Utilizing the ToString() Method

You can obtain a formatted string containing the exception type, Message, and StackTrace all at once by calling the ex.ToString() method without accessing individual properties. ToString() is often sufficient for simple log output, but if you want to finely control the log format (such as when saving in JSON format), access the individual properties as shown above.

3. Limitations of TargetSite

The TargetSite property returns the MethodBase object of the method that threw the exception. However, depending on the .NET execution environment (especially AOT compilation environments or environments with specific optimizations), this information may not be retrieved correctly and may be null. When using it, always check for null. If strict method identification is required, prioritize analyzing the StackTrace.

Summary

Exception objects are a treasure trove of information for resolving errors. By appropriately recording information such as StackTrace and Source in addition to simply displaying the error message, you can quickly identify the cause even when failures occur in a production environment. Leveraging exception information is an essential technique for robust system operation.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次