部署到IIS时,TraceListener不工作

时间:2017-09-20 07:27:00

标签: asp.net iis tracelistener

我自定义TraceListener以使用存储过程登录Sql。我在我的网页上使用它。当我在visual studio环境中开发和测试它时,它正常工作。但是当我在另一台服务器上的IIS上发布它时,没有日志!我的表中没有SQL条目。

我使用这篇文章开发了这个: https://www.codeproject.com/Articles/447238/Advanced-Tracing

using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Xml.Linq;
using System.Threading;
using System.Linq;

//Delegate definition for the real method responsible for logging
internal delegate void LogIt(string message, string type, string componentName);

internal delegate void LogIt2(string userId, string machineName, string details1, string details2, string machineName2, string moduleName, string dateLastLogin, string calssName, string methodName, string ErorMassage);

// Delegate for DBTraceFailed event 
public delegate void DBTraceFailedHandler(string exceptionText);

public class DBTraceListener : TraceListener
{
    public event DBTraceFailedHandler DBTraceFailed;
#region Constants

private const string STORED_PROC_NAME = "AddUserLog";

private const string STORED_PROC_PARAM_UserId = "@PI_UserId";
private const string STORED_PROC_PARAM_IP = "@PI_IP";
private const string STORED_PROC_PARAM_PcName = "@PI_PcName";
private const string STORED_PROC_PARAM_Actions = "@PI_Actions";
private const string STORED_PROC_PARAM_Details = "@PI_Details";
private const string STORED_PROC_PARAM_Module = "@PI_Module";
private const string STORED_PROC_PARAM_LastLogin = "@PI_LastLogin";
private const string STORED_PROC_PARAM_ClassName = "@PI_Class";
private const string STORED_PROC_PARAM_Method = "@PI_Method";
private const string STORED_PROC_PARAM_Message = "@PI_Message";


private const string TRACE_SWITCH_NAME = "DBTraceSwitch";//?
private const string TRACE_SWITCH_DESCRIPTION = "Trace switch defined in config file for configuring trace output to database";

// Not defining it as readonly string so that in future it could come
// from an external source and we can provide initializer for it
private static readonly string DEFAULT_TRACE_TYPE = "Verbose";//all

#endregion

#region Class Data

// Database connection object
private SqlConnection _cn;// the connection

// Database command object
private SqlCommand _cm;

// Connection string for database
private string _connectionString;

// Flag for DBTraceListener object disposal status
private bool _disposed = false;

// Trace Switch object for controlling trace output, defaulting to Verbose
private TraceSwitch TraceSwitch = new TraceSwitch(TRACE_SWITCH_NAME, TRACE_SWITCH_DESCRIPTION, DEFAULT_TRACE_TYPE);

// Delegate to point to the method which would do actual operation of logging
private LogIt workerMethod;
private LogIt2 workerMethod2;

// Component Name 
private string _componentName;

// Lock object
private object _traceLockObject = new object();
private object _fileLockObject = new object();

// Timer to refresh trace configuration information
private Timer _traceSwitchTimer;

// Flag to indicate whether trace configuration data needs to be refreshed
private bool _refreshTraceConfig = false;

#endregion

#region Properties

public override bool IsThreadSafe
{
    get { return false; }
}

public string ConnectionString
{
    get
    {
        if (string.IsNullOrEmpty(this._connectionString))
        {
            this.LoadAttributes();
        }
        return this._connectionString;
    }
    set { this._connectionString = value; }
}

public string ComponentName
{
    get
    {
        if (string.IsNullOrEmpty(this._componentName))
        {
            this.LoadAttributes();
        }
        return this._componentName;
    }
    set { this._componentName = value; }
}

public bool RefreshTraceConfig
{
    get
    {
        this.LoadAttributes();
        return this._refreshTraceConfig;
    }
    set
    {
        if (value)
        {
            // Refresh trace section every 15 minutes
            if (!this._refreshTraceConfig)
            {
                // i.e. If timer is not already active
                this._refreshTraceConfig = true;
                this._traceSwitchTimer = new Timer(new TimerCallback(RefreshSwitch), null, new TimeSpan(0, 15, 0), new TimeSpan(0, 15, 0));
            }
        }
        else
        {
            // If timer is active, stop it
            this._refreshTraceConfig = false;
            this._traceSwitchTimer.Dispose();
            this._traceSwitchTimer = null;
        }
    }
}

#endregion


#region Constructors

public DBTraceListener() : this(string.Empty) { }

public DBTraceListener(string initializeData)
    : base(initializeData)
{
    // Initialize connection object
    this._cn = new SqlConnection();
    this._cn.ConnectionString = initializeData;
    this.ConnectionString = initializeData;

    try
    {
        this._cn.Open();
    }
    catch (Exception ex)
    {
        // Write to internal 
        this.WriteEntryToInternalLog(string.Format("Could not connect to database from the provided connection string. Exception: {0}", ex.ToString()));

        // Let the caller know that this listener object cannot do its 
        // work because it cannot establish connection to database
        //
        // Since Tracing framework is initialized by CLR, you would 
        // in all likelihood get Could not create type... error
        throw;
    }

    // Setup command object
    this._cm = this._cn.CreateCommand();
    this._cm.CommandText = STORED_PROC_NAME;
    this._cm.CommandType = CommandType.StoredProcedure;
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_UserId, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_IP, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_PcName, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Actions, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Details, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Module, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_LastLogin, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_ClassName, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Method, DBNull.Value));
    this._cm.Parameters.Add(new SqlParameter(STORED_PROC_PARAM_Message, DBNull.Value));

}
#endregion

#region Methods

private void LoadAttributes()
{
    if (Attributes.ContainsKey("connectionString"))
    {
        this.ConnectionString = this.Attributes["connectionString"];
    }

    if (Attributes.ContainsKey("componentName"))
    {
        this.ComponentName = this.Attributes["componentName"];
    }

    if (Attributes.ContainsKey("refreshTraceConfig"))
    {
        bool val;
        bool.TryParse(this.Attributes["refreshTraceConfig"], out val);
        this.RefreshTraceConfig = val;
    }
}

void RefreshSwitch(object o)
{
    // Trace.Refresh call is not expected to throw any exception, but if it DOES
    // catch the exception and do nothing
    try
    {
        if (this.RefreshTraceConfig)
        {
            Trace.Refresh();
        }
    }
    catch (Exception ex)
    {
        this.WriteLine(
                string.Format("DBTraceListener.Trace.RefreshSwitch failed with following exception: {0}, ", ex.ToString()),
                "Error"
            );

        this.WriteEntryToInternalLog(string.Format("Trace.RefreshSwitch failed with following exception: {0}, ", ex.ToString()));
    }
}

private void WriteEntryToInternalLog(string msg)
{
    lock (this._fileLockObject)
    {
        try
        {
            File.AppendAllText(@"C:\DBTraceListener.log",//AppDomain.CurrentDomain.BaseDirectory+
                string.Format("{0}{1}: {2}", Environment.NewLine, DateTime.Now.ToString(), msg));
        }
        catch
        {
            // Do nothing
        }
    }
}

/// <summary>
/// Another method useful for testing if DBTraceListener is
/// able to establish connection to database
/// </summary>
/// <returns>void</returns>
public bool TestDBConnection()
{
    try
    {
        using (SqlConnection cn = new SqlConnection(this.ConnectionString))
        {
            cn.Open();
        }
        return true;
    }
    catch
    {
        // In case of any exception just return false
        return false;
    }
}

internal bool ShouldLogTrace(TraceEventType eventType)
{
    bool shouldLog = true;

    switch (eventType)
    {
        case TraceEventType.Critical:
        case TraceEventType.Error:
            shouldLog = this.TraceSwitch.TraceError;
            break;

        case TraceEventType.Warning:
            shouldLog = this.TraceSwitch.TraceWarning;
            break;

        case TraceEventType.Information:
            shouldLog = this.TraceSwitch.TraceInfo;
            break;

        case TraceEventType.Start:
        case TraceEventType.Stop:
        case TraceEventType.Suspend:
        case TraceEventType.Resume:
        case TraceEventType.Transfer:
        case TraceEventType.Verbose:
            shouldLog = this.TraceSwitch.TraceVerbose;
            break;
    }

    return shouldLog;
}

#region TraceData

// TODO: Need to check whether it serves any purpose to override TraceData methods in this listener class

public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
{
    this.TraceData(eventCache, source, eventType, id, data);
}

public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
{
    //TODO: The values of data array needs to be extracted for Message placeholder

    if (this.ShouldLogTrace(eventType))
    {
        this.WriteLine(string.Format(
            "Source:{0} \nId:{1} \nMessage:{2}",
            source,
            id,
            data.ToString()),
            eventType.ToString());
    }
}

#endregion

#region TraceEvent

public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
{
    this.TraceEvent(eventCache, source, eventType, id, string.Empty);
}

public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
    //?????
}

public virtual void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
{
    //?????
}

#endregion

#region TraceTransfer

public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
{
    try
    {
        if (this.ShouldLogTrace(TraceEventType.Transfer))
        {
            XElement msg = new XElement("TraceLog",
                    new XElement("Message", message),
                    new XElement("Source", source),
                    new XElement("Id", id),
                    new XElement("RelatedActivityId", relatedActivityId.ToString()),
                    new XElement("CallStack", eventCache.Callstack.ToString()),
                    new XElement("ThreadId", eventCache.ThreadId),
                    new XElement("ProcessId", eventCache.ProcessId));

            this.WriteLine(msg.ToString(), TraceEventType.Verbose.ToString());
        }
    }
    catch (Exception ex)
    {
        this.WriteLine(
            string.Format("DBTraceListener - Trace.TraceTransfer failed with following exception: {0}, for message {1} ", ex.ToString(), message),
            "Error"
        );

        this.WriteEntryToInternalLog(string.Format("Trace.TraceTransfer failed with following exception: {0}", ex.ToString()));
    }
}

#endregion


#region Write Methods

public override void Write(object o)
{
    if (o != null)
    {
        this.WriteLine(o.ToString(), null);
    }
}

public override void Write(string message)
{
    this.WriteLine(message, null);
}

public override void Write(object o, string category)
{
    if (o != null)
    {
        this.WriteLine(o.ToString(), category);
    }
}

public override void Write(string message, string category)
{
    this.WriteLine(message, category);
}

#endregion

#region WriteLine Methods

public override void WriteLine(object o)
{
    if (o != null)
    {
        this.WriteLine(o.ToString(), null);
    }
}

public override void WriteLine(string message)
{
    this.WriteLine(message, null);
}

public override void WriteLine(object o, string category)
{
    if (o != null)
    {
        this.WriteLine(o.ToString(), category);
    }
}

public override void WriteLine(string message, string category)
{
    WriteLineInternal( message, category);
}

#endregion

#region WriteLineInternal

private void WriteLineInternal(string message, string category)
{
    try
    {
        if (!this.ShouldLogTrace(TraceEventType.Verbose))
        {
            this.WriteEntryToInternalLog(string.Format("WriteLineInternal: log is not going to write, TraceEventType.Verbose: {0} Message: {1}", TraceEventType.Verbose,message));
            return;
        }

        System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
        string userId = String.Empty, ip = String.Empty, actions = String.Empty, details = String.Empty, pcName = String.Empty, moduleName = String.Empty, dateLastLogin = String.Empty, calssName = String.Empty, methodName = String.Empty, ErrorMassage = String.Empty;

        try
        {
            xmlDoc.LoadXml(message);
            userId = xmlDoc.SelectSingleNode("/LogInfo/Record/UserId").InnerText;
            ip = xmlDoc.SelectSingleNode("/LogInfo/Record/IP").InnerText;
            pcName = xmlDoc.SelectSingleNode("/LogInfo/Record/PcName").InnerText;
            actions = xmlDoc.SelectSingleNode("/LogInfo/Record/Actions").InnerText;
            details = xmlDoc.SelectSingleNode("/LogInfo/Record/Details").InnerText;
            moduleName = xmlDoc.SelectSingleNode("/LogInfo/Record/Module").InnerText;
            dateLastLogin = xmlDoc.SelectSingleNode("/LogInfo/Record/LastLogin").InnerText;
            calssName = xmlDoc.SelectSingleNode("/LogInfo/Record/ClassName").InnerText;
            methodName = xmlDoc.SelectSingleNode("/LogInfo/Record/Method").InnerText;
            ErrorMassage = xmlDoc.SelectSingleNode("/LogInfo/Record/Message").InnerText;
        }
        catch (Exception exp)
        {

        }

        workerMethod2 = SaveLogEntry;
        workerMethod2.BeginInvoke(userId, ip, actions, details, pcName, moduleName, dateLastLogin, calssName,methodName,ErrorMassage,null,null);
    }
    catch(Exception ex)
    {
        this.WriteEntryToInternalLog(string.Format("WriteLine failed with following exception: {0}", ex.ToString()));
    }
}

#endregion

private void SaveLogEntry(string userId, string ip, string actions, string details, string pcName, string moduleName, string dateLastLogin, string calssName, string methodName, string ErorMassage)
{
    // IMPORTANT!!!!
    // DO NOT WRITE ANY Debug.WriteLine or Trace.WriteLine statements in this method
    try
    {
        this.WriteEntryToInternalLog(string.Format("SaveLogEntry Before Lock"));
    }
    catch { }
    lock (_traceLockObject)
    {
        try
        {
            // save trace message to database
            if (this._cn.State == ConnectionState.Broken || this._cn.State == ConnectionState.Closed)
            {
                this._cn.ConnectionString = this.ConnectionString;
                this._cn.Open();
            }

            this._cm.Parameters[STORED_PROC_PARAM_UserId].Value = userId;//string.IsNullOrEmpty(userId)? DBNull.Value:
            this._cm.Parameters[STORED_PROC_PARAM_IP].Value = ip;
            this._cm.Parameters[STORED_PROC_PARAM_PcName].Value = pcName;
            this._cm.Parameters[STORED_PROC_PARAM_Actions].Value = actions;
            this._cm.Parameters[STORED_PROC_PARAM_Details].Value = details;
            this._cm.Parameters[STORED_PROC_PARAM_Module].Value = moduleName;
            this._cm.Parameters[STORED_PROC_PARAM_LastLogin].Value = dateLastLogin;
            this._cm.Parameters[STORED_PROC_PARAM_ClassName].Value = calssName;
            this._cm.Parameters[STORED_PROC_PARAM_Method].Value = methodName;
            this._cm.Parameters[STORED_PROC_PARAM_Message].Value = ErorMassage;

            this._cm.ExecuteNonQuery();
            try
            {
                this.WriteEntryToInternalLog(string.Format("SaveLogEntry after ExecuteNonQuery"));
            }
            catch { }
        }
        catch (Exception ex)
        {
            // Raise event to let others know, just in case 
            // someone interested
            if (this.DBTraceFailed != null)
            {
                DBTraceFailed(ex.ToString());
            }

            // Write entry to internal log file
            this.WriteEntryToInternalLog(ex.ToString());
        }
        finally
        {
            // Nothing to dispose in case of exception
        }
    }
}

protected override string[] GetSupportedAttributes()
{
    return new string[] { "connectionString", "componentName", "refreshTraceConfig" };
}

protected override void Dispose(bool disposing)
{
    if (!this._disposed)
    {
        if (disposing)
        {
            if (this._cn != null)
                this._cn.Dispose();

            if (this._cm != null)
                this._cm.Dispose();

            if (this._traceSwitchTimer != null)
                this._traceSwitchTimer.Dispose();
        }

        this._disposed = true;
    }

    this._cm = null;
    this._cn = null;

    base.Dispose(disposing);
}

#endregion

}

我在我的代码中添加了跟踪侦听器而不是在配置文件中。

Debug.Listeners.Add(new DBTraceListener(System.Configuration.ConfigurationManager.ConnectionStrings["connectionString"].ToString()));

正如我所提到的,这在Visual Studio中正常工作,但在服务器PC上却没有。我的电脑正在运行XP,IIS 5;主机是Windows Server 2008 R2和IIS 7.5。

请帮我解决这个问题。

由于

0 个答案:

没有答案