programing

예외.메시지 대 예외.문자열로()

batch 2023. 5. 21. 17:43
반응형

예외.메시지 대 예외.문자열로()

는 기록중코있다니습가드인▁다▁logging▁is니를 기록하는 코드를 가지고 있습니다.Exception.Message하지만, 저는 사용하는 것이 더 낫다는 기사를 읽었습니다.Exception.ToString()후자의 경우 오류에 대한 보다 중요한 정보를 유지할 수 있습니다.

입니까, 로깅을 합니까? 모든 코드 로깅을 교체해도 안전합니까?Exception.Message?

또한 log4net에 XML 기반 레이아웃을 사용하고 있습니다.그것이 가능합니까?Exception.ToString()잘못된 XML 문자가 포함되어 있을 수 있습니다. 문제가 발생할 수 있습니까?

Exception.Message 예외와 관련된 메시지(doh)만 포함합니다.예:

개체 참조가 개체의 인스턴스로 설정되지 않았습니다.

메소드는 예외 유형, 메시지(이전의 메시지), 스택 추적 및 중첩/내부 예외에 대한 이러한 모든 것을 포함하는 훨씬 더 자세한 출력을 제공합니다.보다 정확하게는 메소드는 다음을 반환합니다.

ToString은 사람이 이해할 수 있도록 현재 예외를 반환합니다.예외에 문화에 민감한 데이터가 포함된 경우 현재 시스템 문화를 고려하려면 ToString에서 반환하는 문자열 표현이 필요합니다.반환된 문자열의 형식에 대한 정확한 요구 사항은 없지만 사용자가 인식한 개체의 값을 반영하려고 시도해야 합니다.

ToString의 기본 구현은 현재 예외를 던진 클래스의 이름, 메시지, 내부 예외에서 ToString을 호출한 결과 및 환경을 호출한 결과를 가져옵니다.스택 추적.이러한 멤버 중 하나가 null 참조(Visual Basic에서는 없음)인 경우 해당 값은 반환되는 문자열에 포함되지 않습니다.

오류 메시지가 없거나 빈 문자열("")인 경우 오류 메시지가 반환되지 않습니다.내부 예외의 이름과 스택 추적은 Null 참조(Visual Basic에서는 Nothing)가 아닌 경우에만 반환됩니다.

이미 말한 것 외에, 사용하지 않음ToString()사용자에게 표시할 예외 개체입니다. 냥그.Message속성으로 충분하거나 더 높은 수준의 사용자 지정 메시지가 있어야 합니다.

로깅목의측서면, 사용니다합에반시드적다▁in를 사용합니다.ToString()'만 아니라 '예외'에도됩니다.Message대부분의 시나리오와 마찬가지로 이 예외가 발생한 위치와 콜 스택이 무엇이었는지에 대해 머리를 긁적이며 알 수 있습니다.스택 추적을 통해 모든 것을 알 수 있었을 것입니다.

전체 예외를 문자열로 변환

전화를 거는 것은 단지 속성을 사용하는 것보다 더 많은 정보를 제공합니다.그러나 이마저도 다음과 같은 많은 정보가 남아 있습니다.

  1. Data모든 예외에서 컬렉션 속성을 찾았습니다.
  2. 예외에 추가된 다른 사용자 지정 속성입니다.

이 추가 정보를 캡처하려는 경우가 있습니다.아래 코드는 위의 시나리오를 처리합니다.또한 예외의 속성을 좋은 순서로 기록합니다.C# 7을 사용하고 있지만 필요한 경우 이전 버전으로 변환하는 것이 매우 쉬울 것입니다.관련 답변을 참조하십시오.

public static class ExceptionExtensions
{
    public static string ToDetailedString(this Exception exception) =>
        ToDetailedString(exception, ExceptionOptions.Default);

    public static string ToDetailedString(this Exception exception, ExceptionOptions options)
    {
        if (exception == null)
        {
            throw new ArgumentNullException(nameof(exception));
        } 

        var stringBuilder = new StringBuilder();

        AppendValue(stringBuilder, "Type", exception.GetType().FullName, options);

        foreach (PropertyInfo property in exception
            .GetType()
            .GetProperties()
            .OrderByDescending(x => string.Equals(x.Name, nameof(exception.Message), StringComparison.Ordinal))
            .ThenByDescending(x => string.Equals(x.Name, nameof(exception.Source), StringComparison.Ordinal))
            .ThenBy(x => string.Equals(x.Name, nameof(exception.InnerException), StringComparison.Ordinal))
            .ThenBy(x => string.Equals(x.Name, nameof(AggregateException.InnerExceptions), StringComparison.Ordinal)))
        {
            var value = property.GetValue(exception, null);
            if (value == null && options.OmitNullProperties)
            {
                if (options.OmitNullProperties)
                {
                    continue;
                }
                else
                {
                    value = string.Empty;
                }
            }

            AppendValue(stringBuilder, property.Name, value, options);
        }

        return stringBuilder.ToString().TrimEnd('\r', '\n');
    }

    private static void AppendCollection(
        StringBuilder stringBuilder,
        string propertyName,
        IEnumerable collection,
        ExceptionOptions options)
        {
            stringBuilder.AppendLine($"{options.Indent}{propertyName} =");

            var innerOptions = new ExceptionOptions(options, options.CurrentIndentLevel + 1);

            var i = 0;
            foreach (var item in collection)
            {
                var innerPropertyName = $"[{i}]";

                if (item is Exception)
                {
                    var innerException = (Exception)item;
                    AppendException(
                        stringBuilder,
                        innerPropertyName,
                        innerException,
                        innerOptions);
                }
                else
                {
                    AppendValue(
                        stringBuilder,
                        innerPropertyName,
                        item,
                        innerOptions);
                }

                ++i;
            }
        }

    private static void AppendException(
        StringBuilder stringBuilder,
        string propertyName,
        Exception exception,
        ExceptionOptions options)
    {
        var innerExceptionString = ToDetailedString(
            exception, 
            new ExceptionOptions(options, options.CurrentIndentLevel + 1));

        stringBuilder.AppendLine($"{options.Indent}{propertyName} =");
        stringBuilder.AppendLine(innerExceptionString);
    }

    private static string IndentString(string value, ExceptionOptions options)
    {
        return value.Replace(Environment.NewLine, Environment.NewLine + options.Indent);
    }

    private static void AppendValue(
        StringBuilder stringBuilder,
        string propertyName,
        object value,
        ExceptionOptions options)
    {
        if (value is DictionaryEntry)
        {
            DictionaryEntry dictionaryEntry = (DictionaryEntry)value;
            stringBuilder.AppendLine($"{options.Indent}{propertyName} = {dictionaryEntry.Key} : {dictionaryEntry.Value}");
        }
        else if (value is Exception)
        {
            var innerException = (Exception)value;
            AppendException(
                stringBuilder,
                propertyName,
                innerException,
                options);
        }
        else if (value is IEnumerable && !(value is string))
        {
            var collection = (IEnumerable)value;
            if (collection.GetEnumerator().MoveNext())
            {
                AppendCollection(
                    stringBuilder,
                    propertyName,
                    collection,
                    options);
            }
        }
        else
        {
            stringBuilder.AppendLine($"{options.Indent}{propertyName} = {value}");
        }
    }
}

public struct ExceptionOptions
{
    public static readonly ExceptionOptions Default = new ExceptionOptions()
    {
        CurrentIndentLevel = 0,
        IndentSpaces = 4,
        OmitNullProperties = true
    };

    internal ExceptionOptions(ExceptionOptions options, int currentIndent)
    {
        this.CurrentIndentLevel = currentIndent;
        this.IndentSpaces = options.IndentSpaces;
        this.OmitNullProperties = options.OmitNullProperties;
    }

    internal string Indent { get { return new string(' ', this.IndentSpaces * this.CurrentIndentLevel); } }

    internal int CurrentIndentLevel { get; set; }

    public int IndentSpaces { get; set; }

    public bool OmitNullProperties { get; set; }
}

상단 팁 - 로깅 예외

대부분의 사람들이 이 코드를 사용하여 기록합니다.Serilog와 함께 Serilog를 사용해 보십시오.예외 NuGet 패키지는 예외의 모든 속성도 기록하지만 대부분의 경우 반영하지 않고 더 빨리 기록합니다.Serilog는 매우 발전된 로깅 프레임워크로, 작성 당시 대유행이었습니다.

상단 팁 - 사람이 읽을 수 있는 스택 추적

벤을 써도 돼요Demystifier NuGet 패키지는 예외에 대해 사람이 읽을 수 있는 스택 추적을 가져오거나 Serilog-enrichers-Demystify NuGet 패키지(Serilog를 사용하는 경우)입니다.

저는 윔이 맞다고 생각합니다.당신은 야합다니해를 사용해야 .ToString()파일의 - 대상자를 하여 - " " " " " - " " " " 입니다.Message사용자에게 표시합니다.할 수 (해 보십시오.) 모든 예외 유형과 발생에 대해 (인수를 생각해 보십시오.)예외 등).

추적 에도, 또한, 스추적외에,ToString()그렇지 않으면 얻을 수 없는 정보가 포함됩니다.예를 들어, 예외 "메시지"에 로그 메시지를 포함하도록 활성화된 경우 퓨전의 출력입니다.

에는 사용자 됩니다.ToString()하지만 메시지에는 없습니다.

필요한 정보에 따라 다릅니다.스택 추적 및 내부 예외를 디버깅하는 데 유용합니다.

    string message =
        "Exception type " + ex.GetType() + Environment.NewLine +
        "Exception message: " + ex.Message + Environment.NewLine +
        "Stack trace: " + ex.StackTrace + Environment.NewLine;
    if (ex.InnerException != null)
    {
        message += "---BEGIN InnerException--- " + Environment.NewLine +
                   "Exception type " + ex.InnerException.GetType() + Environment.NewLine +
                   "Exception message: " + ex.InnerException.Message + Environment.NewLine +
                   "Stack trace: " + ex.InnerException.StackTrace + Environment.NewLine +
                   "---END Inner Exception";
    }

log4net에 대한 XML 형식의 경우 ex에 대해 걱정할 필요가 없습니다.로그에 대한 ToString().예외 개체 자체를 전달하기만 하면 log4net은 사전 구성된 XML 형식으로 모든 세부 정보를 제공합니다.가끔 마주치는 것은 줄 바꿈 형식뿐이지만 파일을 원시적으로 읽을 때입니다.그렇지 않으면 XML을 구문 분석하는 것이 좋습니다.

이상적인 경우 전체 예외 개체를 와 비교하여 직렬화하는 것이 가장 좋습니다.ToString().이렇게 하면 전체 예외 개체(모든 내부 예외, 메시지, 스택 추적, 데이터, 키 등)가 캡슐화됩니다.

그런 다음 아무것도 누락되지 않았음을 확인할 수 있습니다.또한 모든 응용 프로그램에서 사용할 수 있는 범용 형식의 개체도 있습니다.

    public static void LogError(Exception exception, int userId)
    {
        LogToDB(Newtonsoft.Json.JsonConvert.SerializeObject(exception), userId);
    }

음, 로그에 무엇을 기록하고 싶은지에 따라 다르다고 말씀드리고 싶네요, 그렇죠?만약 당신이 어떤 전남편에게 만족한다면요.메시지가 제공됩니다. 사용하십시오.그렇지 않으면 ex.toString()을 사용하거나 스택 추적을 기록합니다.

언급URL : https://stackoverflow.com/questions/2176707/exception-message-vs-exception-tostring

반응형