在异步任务中登录Elmah

时间:2012-08-10 14:54:57

标签: asp.net-mvc-3 model-view-controller logging elmah

我需要在我的网络服务器上执行的异步任务中记录一些Elmah。但是当我尝试记录错误时,由于HttpContext而失败。

        var httpContext = HttpContext.Current;

        Task.Factory.StartNew(() =>
        {
            HttpContext.Current = httpContext;

            try
            {
                //Execute some code
            }
            catch (Exception ex)
            {
                //Generate some error for the user and log the error in Elmah
                try
                {
                    ErrorLog.GetDefault(HttpContext.Current).Log(new Error(ex));
                }
                catch(Exception ex)
                {
                }
            }
        });

为了获得任务的进度,我实施了一些轮询机制。目前没有任何错误记录到Elmah,这使得难以解决它们。

同时提供上下文作为参数不起作用。

它不起作用。我得到一个ArgumentException告诉我预期值不在预期范围内。使用以下stacktrace:

at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode,IntPtr errorInfo)    在System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name)    在System.Web.HttpRequest.AddServerVariableToCollection(String name)    在System.Web.HttpRequest.FillInServerVariablesCollection()    在System.Web.HttpServerVarsCollection.Populate()    在System.Web.HttpServerVarsCollection.Get(String name)    在Elmah.ErrorLog.InferApplicationName(HttpContext上下文)    在Elmah.ErrorLog.GetDefaultImpl(HttpContext context)    在Elmah.ServiceContainer.GetService(类型serviceType)    在Elmah.ServiceCenter.GetService(对象上下文,类型serviceType)    在Elmah.ErrorLog.GetDefault(HttpContext上下文)    在D:\ Users \ A500535 \ Documents \ Projecten \ Biobank \ Bis \ src \ Utilities \ Log \ ElmahErrorLog.cs:第13行中的Bis.Utilities.Log.ElmahErrorLog.TryLogError(异常执行)

2 个答案:

答案 0 :(得分:5)

下面是一个可能完成工作的丑陋黑客。从本质上讲,它会在虚假Error原型)上创建Exception对象,以便在请求仍在进行时捕获上下文。稍后,当任务因请求失败而启动时,将从发生的实际异常中创建另一个Error对象,然后从早期原型中选择性地复制有趣和上下文位。不幸的是,无论是否发生异常,都必须创建原型Error

// Create an error that will capture the context
// and serve as a prototype in case a real exception
// needs logging

var prototype = new Error(new Exception(), context);

Task.Factory.StartNew(() =>
{
    try
    {
        // Execute some code
    }
    catch (Exception ex)
    {
        // Generate some error for the user and log the error in ELMAH
        try
        {
            // Create a new error without contextual information
            // but then copy over the interesting bits from the
            // prototype capture at time of request.

            var error = new Error(ex)
            {
                HostName = prototype.HostName,
                User = prototype.User,
            };
            error.ServerVariables.Add(prototype.ServerVariables);
            error.QueryString.Add(prototype.QueryString);
            error.Cookies.Add(prototype.Cookies);
            error.Form.Add(prototype.Form);
            ErrorLog.GetDefault(null).Log(error);
        }
        catch(Exception)
        {
        }
    }
});

答案 1 :(得分:1)

当你启动一个新线程时,它不会获得HttpContext结构。由于Elmah日志记录需要HttpContext数据,因此它将失败。

请参阅以下QA: Elmah Does not email in a fire and forget scenario

对我而言,这适用于使用Task.Run调用的异步任务:

Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new NotSupportedException("elmah logging test")));