通过互联网向开发人员发送应用程序错误和日志的最佳方式是什么?

发布于 2024-07-21 22:09:41 字数 445 浏览 8 评论 0原文

作为 C# 应用程序的作者,我发现如果我能够访问异常或调试日志,对用户报告的问题进行故障排除会容易得多。

我已经包含了一个本地日志记录机制,用户可以打开或关闭该机制。 我希望用户能够通过互联网提交日志,以便我可以查看日志中的错误。

我考虑过使用 SMTPClient网络服务 来发送信息。 SMTPClient 可能无法工作,因为防火墙可能会阻止传出 SMTP 访问。 Web 服务在发送大量数据(可能超过 1 MB)时会出现问题吗?

您建议将应用程序直接传输错误报告给开发人员进行审查的最佳方式是什么?

编辑:澄清:这是一个Windows应用程序,当发生错误时,我想弹出一个对话框,要求提交错误。 我的问题是关于通过互联网将错误日志从应用程序传输给我(开发人员)的机制。

As the author of a C# application, I found that troubleshooting issues reported by users would be much easier if I had access to the exception or debug logs.

I have included a home-grown logging mechanism that the user can turn on or off. I want the user to be able to submit the logs via the internet so I can review the logs for the error.

I have thought of using either SMTPClient or a web service to send the information. SMTPClient might not work because firewalls may block outgoing SMTP access. Would a web service has issue with sending a large amount of data (potentially 1+ MB)?

What would you recommend as the best way to have an application transmit error reports directly to developers for review?

EDIT: Clarification: This is a Windows application and when an error occurs I want to bring up a dialog asking to submit the error. My question is about the mechanism to transmit the error log from the application to me (developer) via the internet.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

盛装女皇 2024-07-28 22:09:41

通过某种方式让用户知道您打算这样做。 向他们索要代理,向他们索要电子邮件服务器,诸如此类。

如果具有安全意识的人发现您正在打开套接字或类似的东西并在没有通知的情况下发送数据,他们会感到非常紧张。

确实如此。

Some way that let's the user know you mean to do it. Ask them for a proxy, ask them for an email server, something like that.

The security minded will get real nervous if they discover that you're opening a socket or something like it and sending data out without notification.

And rightly so.

豆芽 2024-07-28 22:09:41

我建议不要发送所有内容(对您的申请的整个审核)。
但只要用户想要(“反馈”按钮)或者应用程序中存在明确的异常、致命错误、问题状态。

我们使用了 Web 服务和电子邮件 (SMTPClient)。 的看法

我对这些网络服务

  • 每个用户没有特殊配置
  • 大小限制,超过 5Mb-8MB 的电子邮件是可能的

  • 公开可见(黑客喜欢玩
    有了这些东西)
  • 额外的开发来创建带有数据库后端的Web服务
  • 稍后创建额外的字段是
  • 不好的Web服务中的更改不好!

SMTP客户端

  • 每个用户没有特殊配置
  • 登录到公共文件夹使搜索/过滤变得容易(分组,...)
  • 所有数据都可以发送,屏幕截图,堆栈跟踪,用户设置,...
    --> HTML
  • 记录格式和信息的更改很容易,因为我们使用 HTML 电子邮件

不好

  • 每个用户的特殊配置(smtp 服务器、电子邮件用户...)
  • 电子邮件的大小限制(5MB-8MB ??)
  • 记录到电子邮件数据库需要大量发展

I would suggest NOT to send everything (the whole audit of your application).
But just if the user wants it ("Feedback" button) or if there is an explicit exception, fatal error, problem state in the application.

We used both Web services and email (SMTPClient). My thoughts on these

Web service
GOOD

  • No special configuration per user
  • Size limit, more than 5Mb-8MB of email are possible

BAD

  • Public visible (hacker like to play
    with these things)
  • Additional developing to create the web service with db back end
  • Creating additional fields later is bad
  • Changes in web service are NOT GOOD!

SMTPClient
GOOD

  • No special configuration per user
  • Logging to public folder makes search/filter easy (grouping, ...)
  • All data possible to send, screenshots, stacktrace, user settings, ...
    --> HTML
  • Changes in logging format and info is easy, because we used HTML emails

BAD

  • Special configuration per user (smtp server, email user, ...)
  • Size limit of email (5MB-8MB ??)
  • Logging to db of emails requires lot of development
羁〃客ぐ 2024-07-28 22:09:41

我们使用 3 种方法将

  • SMTP 发送到专用邮箱。 这需要大量配置并与“大公司”IT 部门合作,以确定他们的邮件服务器是什么以及如何对其进行身份验证并通过它发送。 还有像 Norton Internet Security 这样的程序可以阻止客户端计算机上的出站 SMTP 流量,这会带来额外的麻烦。
  • 提交到我们服务器上的 asmx。 这是我们的首选方法,但很多事情都会阻碍。 主要是代理,但诺顿也可以介入并打击您。 如果涉及代理,请逃跑:-)
  • 使用 HttpWebRequest 和多部分/表单编码的 mime 类型的 HTTP POST。 它还存在代理和防火墙问题,但有时可以在 asmx 提交失败的情况下工作。

祝你好运。 你是对的,如果你有堆栈跟踪,甚至可能是可怜的老用户正在做什么的屏幕截图,那么调试就会容易得多

We use 3 methods where I work

  • SMTP to a dedicated mailbox. This requires a lot of configuration and dancing around with "big corporate" IT departments to work out what their mail server is and how to authenticate against it and send through it. Then there's programs like Norton Internet Security that can block outbound SMTP traffic on the client machine which throw extra spanners in the works.
  • Submission to an asmx on our server. This is our preferred method, but lots of things can get in the way. It's mainly proxies, but Norton can also step in and swat you down. If there's a proxy involved, run away run away :-)
  • HTTP POST using HttpWebRequest and mime typ of multipart/form-encoded. It also has proxy and firewall issues, but can sometimes work where asmx submission fails.

Good luck. You're right in that it's much easier to debug if you've got the stack trace and perhaps even a screenie of what the poor old user was doing.

伊面 2024-07-28 22:09:41

您可以自己编写它,也可以使用诸如 log4net 之类的东西,它会为您处理异常日志记录...

You can write it yourself, or you can use something like log4net, it takes care of the exception logging for you...

只等公子 2024-07-28 22:09:41

我喜欢将此类内容作为电子邮件接收到专用邮箱。 这样我就可以轻松地归档、搜索或忽略它。

在客户端/发送方方面,我认为提供发送日志的弹出窗口是一个好主意。 如果是 Windows,您可以使用 MAPI 发送电子邮件。 在 UNIX 系统上,“邮件”问题适用于大多数系统。

您可以在确认消息中提示用户输入电子邮件地址,并可能提供一些有关如何发送电子邮件的选项(包括复制/粘贴到他们选择的邮件客户端中)。

您不应该做的一件事是在未经用户许可的情况下发送信息。

I like to receive stuff like this as email to a dedicated mailbox. That way I can easily archive it, search it, or ignore it.

On the client/sender side, I think a pop-up offering to send the logs is a good idea. If windows, you can use MAPI to send the email. On a unix system "mail" problem works on most systems.

You can prompt the user for an email address in the confirmation message, and maybe offer a few options on how to send it (including copy/paste into the mail client of their choice).

One thing you should NOT do is send the information without the user's permission.

情深已缘浅 2024-07-28 22:09:41

如果您不希望在一天内发送很多报告...您可以创建一个 Gmail 帐户并使用它来发送电子邮件,以避免强制用户配置 SMTP 服务器。 不确定 Gmail 的条款和条件是如何执行此操作的。

这是我编写的一个类,它使用 gmail 帐户发送电子邮件...

显然这里存在一些安全问题,例如有人可能会访问您的 gmail 帐户。 因此,请考虑到这一点。

该类中有一些方法可以同步或异步发送电子邮件。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Text;
using System.Net;
using System.Net.Mail;
using System.Net.Mime; 
//Mime is Not necerrary if you dont change the msgview and 
//if you dont add custom/extra headers 
using System.Threading;
using System.IO;
using System.Windows.Forms; // needed for MessageBox only.



namespace BR.Util
{
    public class Gmailer
    {

        SmtpClient client = new SmtpClient();
        static String mDefaultToAddress = "[email protected]";
        static String mDefaultFromAddress = "[email protected]";
        static String mDefaultFromDisplayName = "Anonymous";

        String mGmailLogin = "[email protected]";
        String mGmailPassword = "yourpassword";


        public Gmailer()
        {
            client.Credentials = new System.Net.NetworkCredential(mGmailLogin, mGmailPassword);
            client.Port = 587;           
            client.Host = "smtp.gmail.com";
            client.EnableSsl = true;
            client.SendCompleted += new SendCompletedEventHandler(Gmailer_DefaultAsyncSendCompletedHandler);
        }

        public void setSendCompletedHandler(SendCompletedEventHandler pHandler)
        {
            client.SendCompleted -= Gmailer_DefaultAsyncSendCompletedHandler;
            client.SendCompleted += pHandler;
        }

        /// <summary>
        /// Static method which sends an email synchronously.
        /// It uses a hardcoded from email.
        /// </summary>
        /// <returns></returns>
        public static bool quickSend(String toEmailAddress, String subject, String body)
        {
            return Gmailer.quickSend(toEmailAddress, mDefaultFromAddress, mDefaultFromDisplayName, subject, body);
        }

        /// <summary>
        /// Static method which sends an email synchronously.
        /// It uses the hardcoded email address.
        /// </summary>
        /// <returns>true if successful, false if an error occurred.</returns>
        public static bool quickSend(String toEmailAddress, String fromEmailAddress,
                                     String fromDisplayName, String subject, String body)
        {
            try
            {
                Gmailer gmailer = new Gmailer();
                System.Net.Mail.MailMessage mailMsg = gmailer.createMailMessage(toEmailAddress, fromEmailAddress, fromDisplayName, subject, body);
                gmailer.send(mailMsg);
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        // <summary> creates a MailMessage object initialized with the default values.</summary>
        public System.Net.Mail.MailMessage createMailMessage()
        {
            return createMailMessage(mDefaultToAddress, mDefaultFromAddress, mDefaultFromDisplayName, mDefaultEmailSubject, mDefaultEmailBody);
        }

        public System.Net.Mail.MailMessage createMailMessage(String toEmailAddress, String fromEmailAddress, 
                                                             String fromDisplayName, String subject, String body)
        {
            //Build The MSG
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
            msg.To.Add(toEmailAddress);
            msg.From = new MailAddress(fromEmailAddress, fromDisplayName, System.Text.Encoding.UTF8);
            msg.Subject = subject;
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = body;
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false;
            msg.Priority = MailPriority.High;
            return msg;
        }

        public System.Net.Mail.MailMessage addAttachmentToMailMessage(System.Net.Mail.MailMessage msg, String attachmentPath)
        {
            msg.Attachments.Add(new Attachment(attachmentPath));
            return msg;
        }

        // <summary> method which blocks until the MailMessage has been sent.  Throws
        // System.Net.Mail.SmtpException if error occurs.</summary>
        public void send(System.Net.Mail.MailMessage pMailMessage)
        {
            //try {
                client.Send(pMailMessage);
            //}
            //catch (System.Net.Mail.SmtpException ex)
            //{
            //    MessageBox.Show(ex.Message, "Send Mail Error");
            //}
        }

        // 
        public void sendAsync(System.Net.Mail.MailMessage pMailMessage)
        {
            object userState = pMailMessage;
            try
            {
                MailSent = false;
                client.SendAsync(pMailMessage, userState);
            }
            catch (System.Net.Mail.SmtpException ex)
            {
                MessageBox.Show(ex.Message, "Send Mail Error");
            }
        }

        // <summary> 
        // Provides a default SendComplete handler which is activated when an AsyncCompletedEvent 
        // is triggered by the private client variable.  This is useful for debugging etc.
        // Use the method setSendCompletedHandler to define your own application specific handler.
        // That method also turns this handler off.
        // </summary>
        public void Gmailer_DefaultAsyncSendCompletedHandler(object sender, AsyncCompletedEventArgs e)
        {
            MailMessage mail = (MailMessage)e.UserState;
            string subject = mail.Subject;

            if (e.Cancelled)
            {
                string cancelled = string.Format("[{0}] Send canceled.", subject);
                MessageBox.Show(cancelled);                
            }
            if (e.Error != null)
            {
                string error = String.Format("[{0}] {1}", subject, e.Error.ToString());
                MessageBox.Show(error);                
            }
            else
            {
                MessageBox.Show("Message sent.");
            }
            MailSent = true;
        }


        private bool _MailSent = false;
        /// <summary>
        /// Set to false when an async send operation is started and is set to true when finished.
        /// </summary>
        public bool MailSent
        {
            set
            {
                _MailSent = value;
            }
            get
            {
                return _MailSent;
            }
        }
    }
}

If you aren't expecting that many reports to be sent in a single day... you could create a gmail account and use that to send the emails to get around having to force the user to configure an SMTP server. Not sure what gmail's terms and conditions are for doing this.

Here is a class which I wrote which sends an email using a gmail account...

Obviously there are some security issues here like someone could potentially get access to your gmail account. So, take that into consideration.

There are methods in this class to send the email synchronously or asynchronously.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Text;
using System.Net;
using System.Net.Mail;
using System.Net.Mime; 
//Mime is Not necerrary if you dont change the msgview and 
//if you dont add custom/extra headers 
using System.Threading;
using System.IO;
using System.Windows.Forms; // needed for MessageBox only.



namespace BR.Util
{
    public class Gmailer
    {

        SmtpClient client = new SmtpClient();
        static String mDefaultToAddress = "[email protected]";
        static String mDefaultFromAddress = "[email protected]";
        static String mDefaultFromDisplayName = "Anonymous";

        String mGmailLogin = "[email protected]";
        String mGmailPassword = "yourpassword";


        public Gmailer()
        {
            client.Credentials = new System.Net.NetworkCredential(mGmailLogin, mGmailPassword);
            client.Port = 587;           
            client.Host = "smtp.gmail.com";
            client.EnableSsl = true;
            client.SendCompleted += new SendCompletedEventHandler(Gmailer_DefaultAsyncSendCompletedHandler);
        }

        public void setSendCompletedHandler(SendCompletedEventHandler pHandler)
        {
            client.SendCompleted -= Gmailer_DefaultAsyncSendCompletedHandler;
            client.SendCompleted += pHandler;
        }

        /// <summary>
        /// Static method which sends an email synchronously.
        /// It uses a hardcoded from email.
        /// </summary>
        /// <returns></returns>
        public static bool quickSend(String toEmailAddress, String subject, String body)
        {
            return Gmailer.quickSend(toEmailAddress, mDefaultFromAddress, mDefaultFromDisplayName, subject, body);
        }

        /// <summary>
        /// Static method which sends an email synchronously.
        /// It uses the hardcoded email address.
        /// </summary>
        /// <returns>true if successful, false if an error occurred.</returns>
        public static bool quickSend(String toEmailAddress, String fromEmailAddress,
                                     String fromDisplayName, String subject, String body)
        {
            try
            {
                Gmailer gmailer = new Gmailer();
                System.Net.Mail.MailMessage mailMsg = gmailer.createMailMessage(toEmailAddress, fromEmailAddress, fromDisplayName, subject, body);
                gmailer.send(mailMsg);
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        // <summary> creates a MailMessage object initialized with the default values.</summary>
        public System.Net.Mail.MailMessage createMailMessage()
        {
            return createMailMessage(mDefaultToAddress, mDefaultFromAddress, mDefaultFromDisplayName, mDefaultEmailSubject, mDefaultEmailBody);
        }

        public System.Net.Mail.MailMessage createMailMessage(String toEmailAddress, String fromEmailAddress, 
                                                             String fromDisplayName, String subject, String body)
        {
            //Build The MSG
            System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
            msg.To.Add(toEmailAddress);
            msg.From = new MailAddress(fromEmailAddress, fromDisplayName, System.Text.Encoding.UTF8);
            msg.Subject = subject;
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = body;
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false;
            msg.Priority = MailPriority.High;
            return msg;
        }

        public System.Net.Mail.MailMessage addAttachmentToMailMessage(System.Net.Mail.MailMessage msg, String attachmentPath)
        {
            msg.Attachments.Add(new Attachment(attachmentPath));
            return msg;
        }

        // <summary> method which blocks until the MailMessage has been sent.  Throws
        // System.Net.Mail.SmtpException if error occurs.</summary>
        public void send(System.Net.Mail.MailMessage pMailMessage)
        {
            //try {
                client.Send(pMailMessage);
            //}
            //catch (System.Net.Mail.SmtpException ex)
            //{
            //    MessageBox.Show(ex.Message, "Send Mail Error");
            //}
        }

        // 
        public void sendAsync(System.Net.Mail.MailMessage pMailMessage)
        {
            object userState = pMailMessage;
            try
            {
                MailSent = false;
                client.SendAsync(pMailMessage, userState);
            }
            catch (System.Net.Mail.SmtpException ex)
            {
                MessageBox.Show(ex.Message, "Send Mail Error");
            }
        }

        // <summary> 
        // Provides a default SendComplete handler which is activated when an AsyncCompletedEvent 
        // is triggered by the private client variable.  This is useful for debugging etc.
        // Use the method setSendCompletedHandler to define your own application specific handler.
        // That method also turns this handler off.
        // </summary>
        public void Gmailer_DefaultAsyncSendCompletedHandler(object sender, AsyncCompletedEventArgs e)
        {
            MailMessage mail = (MailMessage)e.UserState;
            string subject = mail.Subject;

            if (e.Cancelled)
            {
                string cancelled = string.Format("[{0}] Send canceled.", subject);
                MessageBox.Show(cancelled);                
            }
            if (e.Error != null)
            {
                string error = String.Format("[{0}] {1}", subject, e.Error.ToString());
                MessageBox.Show(error);                
            }
            else
            {
                MessageBox.Show("Message sent.");
            }
            MailSent = true;
        }


        private bool _MailSent = false;
        /// <summary>
        /// Set to false when an async send operation is started and is set to true when finished.
        /// </summary>
        public bool MailSent
        {
            set
            {
                _MailSent = value;
            }
            get
            {
                return _MailSent;
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文