示例#1
0
 public static IDisposable OpenGroup(this IActivityMonitor @this, LogLevel level, string text, Exception ex, [CallerFilePath] string fileName = null, [CallerLineNumber] int lineNumber = 0)
 {
     if (@this.ShouldLogGroup(level, fileName, lineNumber))
     {
         return(@this.UnfilteredOpenGroup(new ActivityMonitorGroupData(level | LogLevel.IsFiltered, null, text, @this.NextLogTime(), ex, null, fileName, lineNumber)));
     }
     return(@this.UnfilteredOpenGroup(new ActivityMonitorGroupData()));
 }
            static internal IDisposable Start(ActivityMonitor.DependentToken token, IActivityMonitor monitor, string fileName, int lineNumber)
            {
                string msg = token.FormatStartMessage();

                if (token.Topic != null)
                {
                    string currentTopic = token.Topic;
                    monitor.SetTopic(token.Topic, fileName, lineNumber);
                    var g = monitor.UnfilteredOpenGroup(ActivityMonitor.Tags.StartDependentActivity, LogLevel.Info, null, msg, monitor.NextLogTime(), null, fileName, lineNumber);
                    return(Util.CreateDisposableAction(() => { g.Dispose(); monitor.SetTopic(currentTopic, fileName, lineNumber); }));
                }
                return(monitor.UnfilteredOpenGroup(ActivityMonitor.Tags.StartDependentActivity, LogLevel.Info, null, msg, monitor.NextLogTime(), null, fileName, lineNumber));
            }
示例#3
0
            /// <summary>
            /// Launches one or more dependent activities (thanks to a delegate) that will use the current monitor's topic.
            /// This creates a new <see cref="ActivityMonitor.DependentToken"/> and opens a group that wraps the execution of the <paramref name="dependentLauncher"/>.
            /// </summary>
            /// <param name="dependentLauncher">Must create and launch dependent activities that should use the created token.</param>
            /// <returns>A dependent token.</returns>
            public void Launch(Action <ActivityMonitor.DependentToken> dependentLauncher)
            {
                if (dependentLauncher == null)
                {
                    throw new ArgumentNullException(nameof(dependentLauncher));
                }
                string msg;
                var    t = ActivityMonitor.DependentToken.CreateWithMonitorTopic(_monitor, true, out msg);

                using (_monitor.UnfilteredOpenGroup(ActivityMonitor.Tags.CreateDependentActivity, LogLevel.Info, null, msg, t.CreationDate, null, _fileName, _lineNumber))
                {
                    dependentLauncher(t);
                    _monitor.CloseGroup(_monitor.NextLogTime(), "Success.");
                }
            }
        void IActivityMonitorClient.OnOpenGroup(IActivityLogGroup group)
        {
            Debug.Assert(group.GroupLevel != LogLevel.None, "A client never sees a filtered group.");
            Debug.Assert(group.Depth > 0, "Depth is 1-based.");
            // Make sure the index is available.
            // This handles the case where this ClientBridge has been added to the Monitor.Output
            // after the opening of Groups: we must not trigger a Close on the final monitor for them.
            int idx = group.Depth;

            while (idx > _openedGroups.Count)
            {
                _openedGroups.Add(false);
            }

            // By using here our array of boolean to track filtered opened groups against the target, we avoid useless
            // solicitation (and marshaling when crossing application domains).
            // Note: If the group has already been filtered out by extension methods (group.GroupLevel == LogLevel.None),
            // we do not see it here. Checking the LogLevelFilter is ok.
            if (((group.GroupLevel & LogLevel.IsFiltered) == 0 && !_applyTargetFilterToUnfilteredLogs) || (int)GetActualTargetFilter().Group <= (int)group.MaskedGroupLevel)
            {
                _targetMonitor.UnfilteredOpenGroup(group.GroupTags, group.GroupLevel, null, group.GroupText, group.LogTime, group.Exception, group.FileName, group.LineNumber);
                _openedGroups[idx - 1] = true;
            }
            else
            {
                _openedGroups[idx - 1] = false;
            }
        }
        void Run()
        {
            try
            {
                int streamVersion = _reader.ReadInt32();
                if (_interProcess)
                {
                    _server.DisposeLocalCopyOfClientHandle();
                }
                for (; ;)
                {
                    var e = LogEntry.Read(_reader, streamVersion, out bool badEndOfStream);
                    if (e == null || badEndOfStream)
                    {
                        _endFlag = badEndOfStream ? LogReceiverEndStatus.MissingEndMarker : LogReceiverEndStatus.Normal;
                        break;
                    }
                    switch (e.LogType)
                    {
                    case LogEntryType.Line:
                    {
                        if (_monitor.ShouldLogLine(e.LogLevel, e.Tags, out var finalTags))
                        {
                            var d = new ActivityMonitorLogData(e.LogLevel | LogLevel.IsFiltered, finalTags, e.Text, CKException.CreateFrom(e.Exception), e.FileName, e.LineNumber);
                            d.SetExplicitLogTime(e.LogTime);
                            _monitor.UnfilteredLog(ref d);
                        }
                        break;
                    }

                    case LogEntryType.OpenGroup:
                    {
                        ActivityMonitorLogData d;
                        if (_monitor.ShouldLogLine(e.LogLevel, e.Tags, out var finalTags))
                        {
                            d = new ActivityMonitorLogData(e.LogLevel | LogLevel.IsFiltered, finalTags, e.Text, CKException.CreateFrom(e.Exception), e.FileName, e.LineNumber);
                            d.SetExplicitLogTime(e.LogTime);
                        }
                        else
                        {
                            d = default;
                        }
                        _monitor.UnfilteredOpenGroup(ref d);
                    }

                    break;

                    case LogEntryType.CloseGroup:
                        _monitor.CloseGroup(e.Conclusions, e.LogTime);
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                _endFlag = LogReceiverEndStatus.Error;
                _monitor.UnfilteredLog(LogLevel.Fatal, null, "While receiving pipe logs.", ex);
            }
        }
示例#6
0
            /// <summary>
            /// Replays this monitor's content into another monitor.
            /// </summary>
            /// <param name="replay">The target monitor. Can not be null.</param>
            /// <param name="monitor">Optional monitor (nothing is logged when null).</param>
            public void Replay(IActivityMonitor replay, IActivityMonitor?monitor = null)
            {
                using (monitor?.OpenInfo($"Replaying activity from '{MonitorId}'."))
                {
                    int nbMissing = 0;
                    int nbTotal   = 0;
                    using (var page = ReadFirstPage(1024))
                    {
                        foreach (ParentedLogEntry e in page.Entries)
                        {
                            ++nbTotal;
                            LogLevel level = e.Entry.LogLevel;
                            if (e.IsMissing)
                            {
                                ++nbMissing;
                                level = LogLevel.Trace;
                            }
                            switch (e.Entry.LogType)
                            {
                            case LogEntryType.Line:
                                var d = new ActivityMonitorLogData(level, e.Entry.Tags, e.Entry.Text, CKException.CreateFrom(e.Entry.Exception), e.Entry.FileName, e.Entry.LineNumber);
                                d.SetExplicitLogTime(e.Entry.LogTime);
                                replay.UnfilteredLog(ref d);
                                break;

                            case LogEntryType.OpenGroup:
                                d = new ActivityMonitorLogData(level, e.Entry.Tags, e.Entry.Text, CKException.CreateFrom(e.Entry.Exception), e.Entry.FileName, e.Entry.LineNumber);
                                d.SetExplicitLogTime(e.Entry.LogTime);
                                replay.UnfilteredOpenGroup(ref d);
                                break;

                            case LogEntryType.CloseGroup:
                                replay.CloseGroup(e.Entry.Conclusions, e.Entry.LogTime);
                                break;
                            }
                        }
                        page.ForwardPage();
                    }
                    monitor?.CloseGroup($"Replayed {nbTotal} entries ({nbMissing} missing).");
                }
            }
            /// <summary>
            /// Replays this monitor's content into another monitor.
            /// </summary>
            /// <param name="replay">The target monitor. Can not be null.</param>
            /// <param name="m">Optional monitor (nothing is logged when null).</param>
            public void Replay(IActivityMonitor replay, IActivityMonitor m = null)
            {
                using (m != null ? m.OpenGroup(LogLevel.Info, string.Format("Replaying activity from '{0}'.", MonitorId), null) : null)
                {
                    int nbMissing = 0;
                    int nbTotal   = 0;
                    using (var page = ReadFirstPage(1024))
                    {
                        foreach (ParentedLogEntry e in page.Entries)
                        {
                            ++nbTotal;
                            LogLevel level = e.Entry.LogLevel;
                            if (e.IsMissing)
                            {
                                ++nbMissing;
                                level = LogLevel.Trace;
                            }
                            switch (e.Entry.LogType)
                            {
                            case LogEntryType.Line:
                                replay.UnfilteredLog(e.Entry.Tags, level, e.Entry.Text, e.Entry.LogTime, CKException.CreateFrom(e.Entry.Exception), e.Entry.FileName, e.Entry.LineNumber);
                                break;

                            case LogEntryType.OpenGroup:
                                replay.UnfilteredOpenGroup(e.Entry.Tags, level, null, e.Entry.Text, e.Entry.LogTime, CKException.CreateFrom(e.Entry.Exception), e.Entry.FileName, e.Entry.LineNumber);
                                break;

                            case LogEntryType.CloseGroup:
                                replay.CloseGroup(e.Entry.LogTime, e.Entry.Conclusions);
                                break;
                            }
                        }
                        page.ForwardPage();
                    }
                    if (m != null)
                    {
                        m.CloseGroup(String.Format("Replayed {0} entries ({1} missing).", nbTotal, nbMissing));
                    }
                }
            }
 /// <summary>
 /// Opens a group regardless of <see cref="IActivityMonitor.ActualFilter">ActualFilter</see> level.
 /// <see cref="CloseGroup"/> must be called in order to close the group, and/or the returned object must be disposed (both safely can be called:
 /// the group is closed on the first action, the second one is ignored).
 /// </summary>
 /// <param name="this">This <see cref="IActivityMonitor"/>.</param>
 /// <param name="tags">Tags (from <see cref="ActivityMonitor.Tags"/>) to associate to the log. It will be union-ed with current <see cref="IActivityMonitor.AutoTags">AutoTags</see>.</param>
 /// <param name="level">Log level. The <see cref="LogLevel.None"/> level is used to open a filtered group. See remarks.</param>
 /// <param name="getConclusionText">Optional function that will be called on group closing.</param>
 /// <param name="text">Text to log (the title of the group). Null text is valid and considered as <see cref="String.Empty"/> or assigned to the <see cref="Exception.Message"/> if it exists.</param>
 /// <param name="logTime">
 /// Time of the log entry.
 /// You can use <see cref="DateTimeStamp.UtcNow"/> or <see cref="ActivityMonitorExtension.NextLogTime">IActivityMonitor.NextLogTime()</see> extension method.
 /// </param>
 /// <param name="ex">Optional exception associated to the group.</param>
 /// <param name="fileName">The source code file name from which the group is opened.</param>
 /// <param name="lineNumber">The line number in the source from which the group is opened.</param>
 /// <returns>A disposable object that can be used to close the group.</returns>
 /// <remarks>
 /// <para>
 /// Opening a group does not change the current <see cref="IActivityMonitor.MinimalFilter">MinimalFilter</see>, except when
 /// opening a <see cref="LogLevel.Fatal"/> or <see cref="LogLevel.Error"/> group: in such case, the Filter is automatically
 /// sets to <see cref="LogFilter.Debug"/> to capture all potential information inside the error group.
 /// </para>
 /// <para>
 /// Changes to the monitor's current Filter or AutoTags that occur inside a group are automatically restored to their original values when the group is closed.
 /// This behavior guaranties that a local modification (deep inside unknown called code) does not impact caller code: groups are a way to easily isolate such
 /// configuration changes.
 /// </para>
 /// <para>
 /// Note that this automatic configuration restoration works even if the group is filtered (when the <paramref name="level"/> is None).
 /// </para>
 /// </remarks>
 static public IDisposable UnfilteredOpenGroup(this IActivityMonitor @this, CKTrait tags, LogLevel level, Func <string> getConclusionText, string text, DateTimeStamp logTime, Exception ex, [CallerFilePath] string fileName = null, [CallerLineNumber] int lineNumber = 0)
 {
     return(@this.UnfilteredOpenGroup(new ActivityMonitorGroupData(level, tags, text, logTime, ex, getConclusionText, fileName, lineNumber)));
 }
 static internal IDisposable Start( ActivityMonitor.DependentToken token, IActivityMonitor monitor, string fileName, int lineNumber )
 {
     string msg = token.FormatStartMessage();
     if( token.Topic != null )
     {
         string currentTopic = token.Topic;
         monitor.SetTopic( token.Topic, fileName, lineNumber );
         var g = monitor.UnfilteredOpenGroup( ActivityMonitor.Tags.StartDependentActivity, LogLevel.Info, null, msg, monitor.NextLogTime(), null, fileName, lineNumber );
         return Util.CreateDisposableAction( () => { g.Dispose(); monitor.SetTopic( currentTopic, fileName, lineNumber ); } );
     }
     return monitor.UnfilteredOpenGroup( ActivityMonitor.Tags.StartDependentActivity, LogLevel.Info, null, msg, monitor.NextLogTime(), null, fileName, lineNumber );
 }
 internal IDisposableGroup InitializeAndSend(Exception exception, CKTrait tags, string text)
 {
     Debug.Assert(!IsRejected);
     Initialize(text, exception, tags, Monitor.NextLogTime());
     return(Monitor.UnfilteredOpenGroup(this));
 }