Azure Diagnostics wrt自定义日志并遵守scheduledTransferPeriod

Azure Diagnostics wrt自定义日志并遵守scheduledTransferPeriod,azure,azure-diagnostics,Azure,Azure Diagnostics,我已经实现了自己的TraceListener,类似于 我注意到,日志会立即显示在我的Azure表存储中。我想知道这是自定义跟踪侦听器所期望的,还是因为我处于开发环境中 我的诊断 <?xml version="1.0" encoding="utf-8"?> <DiagnosticMonitorConfiguration configurationChangePollInterval="PT1M""overallQuotaInMB="4096" xmlns="http://sch

我已经实现了自己的TraceListener,类似于

我注意到,日志会立即显示在我的Azure表存储中。我想知道这是自定义跟踪侦听器所期望的,还是因为我处于开发环境中

我的诊断

<?xml version="1.0" encoding="utf-8"?>
 <DiagnosticMonitorConfiguration configurationChangePollInterval="PT1M""overallQuotaInMB="4096" xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration">
  <DiagnosticInfrastructureLogs scheduledTransferLogLevelFilter="Information" />
  <Directories scheduledTransferPeriod="PT1M">
    <IISLogs container="wad-iis-logfiles" />
    <CrashDumps container="wad-crash-dumps" />
  </Directories>
  <Logs bufferQuotaInMB="0" scheduledTransferPeriod="PT30M" scheduledTransferLogLevelFilter="Information" />
</DiagnosticMonitorConfiguration>


我看了你提到的博客文章中的源代码。如果您注意到
Details
方法的代码中,它正在调用
Trace.Flush()
方法,该方法实质上是将迄今为止收集的跟踪日志数据写入表存储中。换句话说,自定义跟踪侦听器根本没有从diagnostics.wadcfg文件中获取计划的传输周期。

在这一点上,我认为没有一个解决方案可以利用scheduledTransferPeriod和自定义日志。我最终接受了即时传输,因为我想要自己的表模式。在某些时候,我可能会编写自己的传输间隔。

我将Autoflush设置为true,因此每次都会推送。但是,当我将Autoflush设置为false时,flush方法从未被调用。有人知道是否应该触发刷新吗?您可以通过将其包含在问题中来共享您的代码吗?在博客文章中,手动调用了flush方法。我现在的问题是,scheduledTransferPeriod对自定义跟踪侦听器是否有任何影响?至少对于博客文章中提到的代码,答案是否定的,因为它直接写入表存储,而不是依赖VM中运行的诊断代理。
  <system.diagnostics>
    <!--http://msdn.microsoft.com/en-us/library/sk36c28t(v=vs.110).aspx
    By default autoflush is false.
    By default useGlobalLock is true.  While we try to be threadsafe, we keep this default for now.  Later if we would like to increase performance we can remove this. see http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.usegloballock(v=vs.110).aspx -->
    <trace>
      <listeners>
        <add name="TableTraceListener"
            type="Pos.Services.Implementation.TableTraceListener, Pos.Services.Implementation"
             />
        <remove name="Default" />
      </listeners>
    </trace>
  </system.diagnostics>
namespace Pos.Services.Implementation
{
    class TableTraceListener : TraceListener
    {
#region Fields      

        //connection string for azure storage
        readonly string _connectionString;
        //Custom sql storage table for logs.
        //TODO put in config
        readonly string _diagnosticsTable;

        [ThreadStatic]
        static StringBuilder _messageBuffer;

        readonly object _initializationSection = new object();
        bool _isInitialized;

        CloudTableClient _tableStorage;
        readonly object _traceLogAccess = new object();
        readonly List<LogEntry> _traceLog = new List<LogEntry>();
#endregion

#region Constructors
       public TableTraceListener() : base("TableTraceListener")
        {
            _connectionString = RoleEnvironment.GetConfigurationSettingValue("DiagConnection");
            _diagnosticsTable = RoleEnvironment.GetConfigurationSettingValue("DiagTableName");
        }

#endregion

#region Methods

        /// <summary>
        /// Flushes the entries to the storage table
        /// </summary>
        public override void Flush()
        {
            if (!_isInitialized)
            {
                lock (_initializationSection)
                {
                    if (!_isInitialized)
                    {
                        Initialize();
                    }
                }
            }

            var context = _tableStorage.GetTableServiceContext();
            context.MergeOption = MergeOption.AppendOnly;
            lock (_traceLogAccess)
            {
                _traceLog.ForEach(entry => context.AddObject(_diagnosticsTable, entry));
                _traceLog.Clear();
            }

            if (context.Entities.Count > 0)
            {
                context.BeginSaveChangesWithRetries(SaveChangesOptions.None, (ar) => context.EndSaveChangesWithRetries(ar), null);
            }
        }

        /// <summary>
        /// Creates the storage table object. This class does not need to be locked because the caller is locked.
        /// </summary>
        private void Initialize()
        {
            var account = CloudStorageAccount.Parse(_connectionString);
            _tableStorage = account.CreateCloudTableClient();
            _tableStorage.GetTableReference(_diagnosticsTable).CreateIfNotExists();
            _isInitialized = true;
        } 

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

 #region Trace and Write Methods
        /// <summary>
        /// Writes the message to a string buffer
        /// </summary>
        /// <param name="message">the Message</param>
        public override void Write(string message)
        {
            if (_messageBuffer == null)
                _messageBuffer = new StringBuilder();

            _messageBuffer.Append(message);
        }

        /// <summary>
        /// Writes the message with a line breaker to a string buffer
        /// </summary>
        /// <param name="message"></param>
        public override void WriteLine(string message)
        {
            if (_messageBuffer == null)
                _messageBuffer = new StringBuilder();

            _messageBuffer.AppendLine(message);
        }

        /// <summary>
        /// Appends the trace information and message
        /// </summary>
        /// <param name="eventCache">the Event Cache</param>
        /// <param name="source">the Source</param>
        /// <param name="eventType">the Event Type</param>
        /// <param name="id">the Id</param>
        /// <param name="message">the Message</param>
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
        {
            base.TraceEvent(eventCache, source, eventType, id, message);
            AppendEntry(id, eventType, eventCache);
        }

        /// <summary>
        /// Adds the trace information to a collection of LogEntry objects
        /// </summary>
        /// <param name="id">the Id</param>
        /// <param name="eventType">the Event Type</param>
        /// <param name="eventCache">the EventCache</param>
        private void AppendEntry(int id, TraceEventType eventType, TraceEventCache eventCache)
        {
            if (_messageBuffer == null)
                _messageBuffer = new StringBuilder();

            var message = _messageBuffer.ToString();
            _messageBuffer.Length = 0;

            if (message.EndsWith(Environment.NewLine))
                message = message.Substring(0, message.Length - Environment.NewLine.Length);

            if (message.Length == 0)
                return;

            var entry = new LogEntry()
            {
                PartitionKey = string.Format("{0:D10}", eventCache.Timestamp >> 30),
                RowKey = string.Format("{0:D19}", eventCache.Timestamp),
                EventTickCount = eventCache.Timestamp,
                Level = (int)eventType,
                EventId = id,
                Pid = eventCache.ProcessId,
                Tid = eventCache.ThreadId,
                Message = message
            };

            lock (_traceLogAccess)
                _traceLog.Add(entry);
        }

#endregion
#endregion
    }
}