এক্সেপশন.ম্যাসেজ বনাম এক্সেপশন.টস্ট্রিং ()


207

আমার লগিংয়ের কোড রয়েছে Exception.Message। যাইহোক, আমি একটি নিবন্ধ পড়েছি যা এতে উল্লেখ করা হয়েছে যে এটি ব্যবহার করা ভাল Exception.ToString()। পরবর্তীগুলির সাথে, আপনি ত্রুটি সম্পর্কে আরও গুরুত্বপূর্ণ তথ্য ধরে রাখেন।

এটি কি সত্য, এবং সমস্ত কোড লগিংকে সামনে রেখে প্রতিস্থাপন করা কি নিরাপদ Exception.Message?

আমি লগ 4 নেটয়ের জন্য একটি এক্সএমএল ভিত্তিক লেআউটটিও ব্যবহার করছি । এটিতে কী Exception.ToString()অবৈধ এক্সএমএল অক্ষর থাকতে পারে যা সমস্যার কারণ হতে পারে?


1
আপনার ELMAH (কোড. google.com/p/elmah ) এও নজর দেওয়া উচিত - এএসপি.নেটের জন্য ত্রুটিযুক্ত লগিংয়ের জন্য খুব সহজেই ব্যবহারযোগ্য কাঠামো।
আশীষ গুপ্ত

উত্তর:


278

Exception.Messageব্যতিক্রম সম্পর্কিত শুধুমাত্র বার্তা (দোহ) রয়েছে। উদাহরণ:

অবজেক্টের রেফারেন্স কোনও অবজেক্টের উদাহরণে সেট করা হয়নি

Exception.ToString()পদ্ধতি আউটপুট বাগাড়ম্বরপূর্ণ অনেক দিতে, নেস্টেড / ভেতরের ব্যতিক্রম জন্য আবার ব্যতিক্রম ধরন, বার্তা (আগে থেকে), একটি স্ট্যাক ট্রেস, এবং এই সব ধারণকারী হবে। আরও স্পষ্টভাবে, পদ্ধতিটি নিম্নলিখিতগুলি প্রদান করে:

টোস্ট্রিং বর্তমান ব্যতিক্রমগুলির একটি প্রতিনিধিত্ব প্রত্যাবর্তন করে যা মানুষের বোঝার উদ্দেশ্যে। ব্যতিক্রমটি যেখানে সংস্কৃতি-সংবেদনশীল ডেটা রয়েছে সেখানে টোস্ট্রিংয়ের দ্বারা ফিরে আসা স্ট্রিং প্রতিনিধিত্বকে বর্তমান সিস্টেম সংস্কৃতি বিবেচনায় নেওয়া প্রয়োজন। যদিও ফেরত স্ট্রিংয়ের ফর্ম্যাটটির জন্য কোনও সঠিক প্রয়োজনীয়তা নেই, এটি ব্যবহারকারীর দ্বারা উপলব্ধ হিসাবে বস্তুর মান প্রতিফলিত করার চেষ্টা করা উচিত।

টোস্ট্রিংয়ের ডিফল্ট বাস্তবায়ন ক্লাসের নামটি গ্রহণ করে যা বর্তমান ব্যতিক্রম ছুঁড়ে ফেলেছে, বার্তাটি, অভ্যন্তরীণ ব্যতিক্রম টোস্ট্রিংকে কল করার ফলাফল এবং পরিবেশ.স্যাকট্রেস কল করার ফলাফল। এই সদস্যদের মধ্যে যদি কোনও নাল রেফারেন্স হয় (ভিজ্যুয়াল বেসিকের কিছুই নয়), এর মানটি ফেরত স্ট্রিংয়ের সাথে অন্তর্ভুক্ত নয়।

যদি কোনও ত্রুটি বার্তা না থাকে বা এটি একটি খালি স্ট্রিং ("") থাকে, তবে কোনও ত্রুটি বার্তা ফিরে আসে না। অভ্যন্তরীণ ব্যতিক্রমের নাম এবং স্ট্যাকের ট্রেস কেবল তখনই ফিরে আসে যখন সেগুলি নাল রেফারেন্স নয় (ভিজুয়াল বেসিক ক্ষেত্রে কিছুই নয়)।


85
+1 লগগুলিতে কেবল "অবজেক্টের রেফারেন্স কোনও অবজেক্টের উদাহরণ হিসাবে সেট করা হয় না" এটি দেখতে খুব বেদনাদায়ক। আপনি সত্যিই অসহায় বোধ করেন। :-)
আশীষ গুপ্ত

1
শেষ অংশের জন্য, ব্যতিক্রমগুলি রয়েছে যেগুলি ব্যতিক্রমের সাথে আসে না ess ম্যাসেজ। ত্রুটিটি পরিচালনা করার অংশে আপনি যা করেন তার ফাংশনে, আপনি ব্যতিক্রমের কারণেই সমস্যা হতে পারেন essমেসেজ।
প্রবাল ডো 2

49
এটি দেখতে খুব বেদনাদায়ক যে আমি কোড লিখেছি যা মূলত টুস্ট্রিং () যা করে ঠিক একই জিনিসটি করে।
প্রেস্টন ম্যাককর্মিক

1
@ কুণালগোয়েল যদি লগটি প্রোড থেকে আসে এবং ইনপুটটি কী ছিল তা আপনার কোনও ইঙ্গিত না থাকলে, না, আপনি কেবল "সিএলআর ব্যতিক্রমটি চালু করে ডিবাগ করতে পারবেন না"।
jpmc26

1
দ্রষ্টব্য, এটি "ToString এর ডিফল্ট বাস্তবায়ন" ... ("ডিফল্ট" এর উপর জোর দেওয়া) .. এর অর্থ এই নয় যে প্রত্যেকে যে কোনও কাস্টম ব্যতিক্রম ছাড়াই সেই অনুশীলনটি অনুসরণ করেছে। #
অ্যালার্নডহার্ড

52

ইতিমধ্যে যা বলা হয়েছে তা ছাড়াও, ব্যবহারকারীর কাছে প্রদর্শন করার জন্য ব্যতিক্রম বস্তুটিতে ব্যবহার করবেন নাToString() । কেবল Messageসম্পত্তিটি পর্যাপ্ত হওয়া উচিত, বা একটি উচ্চ স্তরের কাস্টম বার্তা।

লগিংয়ের উদ্দেশ্যে, ToString()ব্যতিক্রমগুলি অবশ্যই স্পষ্টভাবে ব্যবহার করুন, Messageবেশিরভাগ দৃশ্যের মতো, আপনার মাথাটি স্ক্র্যাচিংয়ে ছেড়ে দেওয়া হবে যেখানে বিশেষত এই ব্যতিক্রম ঘটেছিল, এবং কল স্ট্যাকটি কী ছিল। স্ট্যাকট্রেস আপনাকে সমস্ত কিছু বলত।


আপনি যদি লগগুলিতে টস্ট্রিং () ব্যবহার করে থাকেন তবে টোস্ট্রিংয়ে সংবেদনশীল তথ্য অন্তর্ভুক্ত করবেন না তা নিশ্চিত করুন
মাইকেল ফ্রেইজিম

22

পুরো ব্যতিক্রমটিকে স্ট্রিংয়ে রূপান্তর করা

কল করা Exception.ToString()আপনাকে কেবল Exception.Messageসম্পত্তি ব্যবহারের চেয়ে আরও বেশি তথ্য দেয় । যাইহোক, এটি এখনও এখনও প্রচুর তথ্য ফেলে দেয়:

  1. Dataসংগ্রহে সম্পত্তি সব ব্যতিক্রম পাওয়া যায় নি।
  2. ব্যতিক্রম যুক্ত অন্য কোনও কাস্টম বৈশিষ্ট্য।

এমন অনেক সময় আছে যখন আপনি এই অতিরিক্ত তথ্য ক্যাপচার করতে চান। নীচের কোডটি উপরের পরিস্থিতিতে পরিচালনা করে। এটি একটি সুন্দর ক্রমে ব্যতিক্রমগুলির বৈশিষ্ট্যগুলিও লিখে দেয়। এটি সি # 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; }
}

শীর্ষ টিপ - লগিং ব্যতিক্রম

লগিংয়ের জন্য বেশিরভাগ লোক এই কোডটি ব্যবহার করবে। আমার সেরিলোগের সাথে সেরিলোগ ব্যবহার করার কথা বিবেচনা করুন x ব্যতিক্রমগুলি নুগেট প্যাকেজ যা কোনও ব্যতিক্রমের সমস্ত বৈশিষ্ট্য লগ করে তবে বেশিরভাগ ক্ষেত্রেই এটি দ্রুত এবং প্রতিফলন ছাড়াই করে does সেরিলোগ হ'ল একটি উন্নত লগিং ফ্রেমওয়ার্ক যা লেখার সময় সমস্ত ক্রোধ।

শীর্ষ টিপ - মানব পাঠযোগ্য স্ট্যাক ট্রেস ces

আপনি ব্যবহার করতে পারেন Ben.Demystifier NuGet প্যাকেজ আপনার ব্যতিক্রম বা মানব পাঠযোগ্য স্ট্যাক ট্রেস পেতে serilog-enrichers-demystify NuGet প্যাকেজ যদি আপনি Serilog ব্যবহার করছেন।


9

আমি বলব @ উইম ঠিক আছে। আপনার ব্যবহারকারীর কাছে প্রদর্শন করতে ToString()কোনও প্রযুক্তিগত শ্রোতা ধরে রেখে - লগফাইলে ব্যবহার করা উচিত Message। যে কেউ তর্ক করতে পারে যে এমনকি এটি ব্যবহারকারীর পক্ষে উপযুক্ত নয়, প্রতিটি ব্যতিক্রম প্রকারের এবং উপস্থিতিগুলির জন্য (আর্গুমেন্টএক্সেপশনস ইত্যাদি বিবেচনা করুন)।

এছাড়াও, স্ট্যাকট্রেস ছাড়াও ToString()এমন তথ্য অন্তর্ভুক্ত করবে যা আপনি অন্যথায় পাবেন না। উদাহরণস্বরূপ ফিউশন আউটপুট, ব্যতিক্রম "বার্তাগুলি" এ লগ বার্তা অন্তর্ভুক্ত করতে সক্ষম করা থাকলে

কিছু ব্যতিক্রম ধরণের অতিরিক্ত তথ্য (যেমন কাস্টম সম্পত্তি থেকে) অন্তর্ভুক্ত থাকে ToString()তবে বার্তায় নেই in


8

আপনার প্রয়োজনীয় তথ্যের উপর নির্ভর করে। স্ট্যাক ট্রেস ডিবাগ করার জন্য এবং অভ্যন্তরীণ ব্যতিক্রমগুলি দরকারী:

    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";
    }

12
এটি কম-বেশি যা Exception.ToString()আপনাকে দেবে, তাই না?
জার্ন শো-রোড

5
@ ম্যাট: এই দৃশ্যে একটি উদাহরণ তৈরি StringBuilderকরা দুটি নতুন স্ট্রিং বরাদ্দের চেয়ে বেশি ব্যয়বহুল হতে পারে, এটি অত্যন্ত বিতর্কিত এটি এখানে আরও দক্ষ হবে। এটি আমরা পুনরাবৃত্তির সাথে কাজ করছি এমন নয়। ভিন্ন ভিন্ন মানুষ ভিন্ন ভিন্ন জিনিস এর জন্য উপযোগী.
উইম হলব্র্যান্ডস

2
এখানে সমস্যাটি হ'ল, আপনি কেবল বহিরাগত ব্যতিক্রমের "অভ্যন্তরীণ ধারণা" পাবেন। আইওডাব্লু, যদি ইনারএক্সসেপশন নিজেই একটি অভ্যন্তরীণ ধারণা সেট করে থাকে তবে আপনি এটি ফেলে দেবেন না (ধরে নিবেন যে আপনি প্রথম স্থানে চান)। আমি সত্যিই টসস্ট্রিং () এর সাথে লেগে থাকি।
খ্রিস্টান.কে

6
স্রেফ ex.ToString ব্যবহার করুন। এটি আপনাকে সমস্ত বিবরণ দেয়।
জন স্যান্ডার্স

3
@ ক্রিশ্চিয়ান: সংকলকটি একাধিক + এস সহ বুদ্ধিমান। উদাহরণস্বরূপ দেখুন "The অপারেটরটি ব্যবহার করা সহজ এবং স্বজ্ঞাত কোডের জন্য তৈরি করে। এমনকি আপনি যদি একটি বিবৃতিতে বেশ কয়েকটি + অপারেটর ব্যবহার করেন তবে স্ট্রিং সামগ্রীটি একবারেই অনুলিপি করা হয়।" থেকে msdn.microsoft.com/en-us/library/ms228504.aspx
ডেভিড Eison

3

লগ 4 নেট এর জন্য এক্সএমএল ফর্ম্যাটের ক্ষেত্রে, লগগুলির জন্য আপনাকে প্রাক্তন.স্টোস্ট্রিং () নিয়ে চিন্তা করার দরকার নেই। কেবল ব্যতিক্রম বস্তুটি নিজেই পাস করুন এবং লগ 4 নেট আপনাকে তার পূর্ব-কনফিগার করা এক্সএমএল ফর্ম্যাটের সমস্ত বিবরণ দেয় give আমি উপলক্ষে চালানো একমাত্র জিনিসটি নতুন লাইন ফর্ম্যাটিং, তবে আমি যখন ফাইলগুলি কাঁচা পড়ছি that's অন্যথায় এক্সএমএল পার্সিং দুর্দান্ত কাজ করে।


0

ভাল, আমি বলব এটি লগগুলিতে আপনি যা দেখতে চান তা নির্ভর করে, তাই না? প্রাক্তন যা সরবরাহ করে তাতে আপনি যদি খুশি হন তবে এটি ব্যবহার করুন। অন্যথায়, ex.toString () ব্যবহার করুন বা স্ট্যাক ট্রেস লগ করুন।


5
ex.ToString স্ট্যাক ট্রেস অন্তর্ভুক্ত
জন স্যান্ডার্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.