Defines configuration for GrandOutput. This object is not thread safe. New GrandOutputConfiguration can be created when needed (and method LoadFromFile or Load called).
Пример #1
0
 /// <summary>
 /// Ensures that the <see cref="Default"/> GrandOutput is created and that any <see cref="ActivityMonitor"/> that will be created in this
 /// application domain will automatically have a <see cref="GrandOutputClient"/> registered for this Default GrandOutput.
 /// If the Default is already initialized, the <paramref name="configuration"/> is applied.
 /// </summary>
 /// <param name="configuration">
 /// Configuration to apply to the default GrandOutput.
 /// When null, a default configuration with a <see cref="Handlers.TextFileConfiguration"/> in a "Text" path is configured.
 /// </param>
 /// <param name="clearExistingTraceListeners">
 /// If the <see cref="Default"/> is actually instantiated, existing <see cref="Trace.Listeners"/>
 /// are cleared before registering a <see cref="MonitorTraceListener"/> associated to this default grand output.
 /// See remarks.
 /// </param>
 /// <returns>The Default GrandOutput that has been created or reconfigured.</returns>
 /// <remarks>
 /// <para>
 /// This method is thread-safe (a simple lock protects it) and uses a <see cref="ActivityMonitor.AutoConfiguration"/> action
 /// that uses <see cref="EnsureGrandOutputClient(IActivityMonitor)"/> on newly created ActivityMonitor.
 /// </para>
 /// <para>
 /// The Default GrandOutput also adds a <see cref="MonitorTraceListener"/> in the <see cref="Trace.Listeners"/> collection that
 /// has <see cref="MonitorTraceListener.FailFast"/> sets to false: <see cref="MonitoringFailFastException"/> are thrown instead of
 /// calling <see cref="Environment.FailFast(string)"/>.
 /// If this behavior must be changed, please exploit the <see cref="Trace.Listeners"/> that is a <see cref="TraceListenerCollection"/>, wide open
 /// to any modifications, and the fact that <see cref="MonitorTraceListener"/> exposes its associated grand output and
 /// that <see cref="MonitorTraceListener.FailFast"/> property can be changed at any time.
 /// </para>
 /// <para>
 /// The GrandOutput.Default can safely be <see cref="Dispose()"/> at any time: disposing the Default
 /// sets it to null.
 /// </para>
 /// </remarks>
 static public GrandOutput EnsureActiveDefault(GrandOutputConfiguration?configuration = null, bool clearExistingTraceListeners = true)
 {
     lock ( _defaultLock )
     {
         if (_default == null)
         {
             if (configuration == null)
             {
                 configuration = new GrandOutputConfiguration()
                                 .AddHandler(new Handlers.TextFileConfiguration()
                 {
                     Path = "Text"
                 });
                 configuration.InternalClone = true;
             }
             _default = new GrandOutput(true, configuration);
             ActivityMonitor.AutoConfiguration += AutoRegisterDefault;
             _traceListener = new MonitorTraceListener(_default, failFast: false);
             if (clearExistingTraceListeners)
             {
                 Trace.Listeners.Clear();
             }
             Trace.Listeners.Add(_traceListener);
         }
         else if (configuration != null)
         {
             _default.ApplyConfiguration(configuration, true);
         }
     }
     return(_default);
 }
Пример #2
0
 public void ConfigObjectAttributeRequired()
 {
     GrandOutputConfiguration c = new GrandOutputConfiguration();
     Assert.That( c.Load( XDocument.Parse( @"<GrandOutputConfiguration><Add /></GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor ), Is.False );
     Assert.That( c.Load( XDocument.Parse( @"<GrandOutputConfiguration><Channel><Add Type=""BinaryFile"" /></Channel></GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor ), Is.False );
     Assert.That( c.Load( XDocument.Parse( @"<GrandOutputConfiguration><Channel><Add Type=""BinaryFile"" Name=""GlobalCatch"" /></Channel></GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor ), Is.False );
     // This is okay: Type, Name and Path for BinaryFile.
     Assert.That( c.Load( XDocument.Parse( @"<GrandOutputConfiguration><Channel><Add Type=""BinaryFile"" Name=""GlobalCatch"" Path=""In-Root-Log-Path"" /></Channel></GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor ) );
 }
Пример #3
0
 /// <summary>
 /// Applies a configuration.
 /// This is thread safe and can be called at any moment.
 /// </summary>
 /// <param name="configuration">The configuration to apply.</param>
 /// <param name="waitForApplication">
 /// True to block until this configuration has been applied.
 /// Note that another (new) configuration may have already replaced the given configuration
 /// once this call ends.
 /// </param>
 public void ApplyConfiguration(GrandOutputConfiguration configuration, bool waitForApplication = false)
 {
     Throw.CheckNotNullArgument(configuration);
     if (!configuration.InternalClone)
     {
         configuration = configuration.Clone();
         configuration.InternalClone = true;
     }
     _sink.ApplyConfiguration(configuration, waitForApplication);
 }
Пример #4
0
        /// <summary>
        /// Ensures that the <see cref="Default"/> GrandOutput is created (see <see cref="EnsureActiveDefault"/>) and configured with default settings:
        /// only one one channel with its minimal filter sets to Debug with one text file handler that writes .txt files in "<see cref="SystemActivityMonitor.RootLogPath"/>\GrandOutputDefault" directory.
        /// The <see cref="SystemActivityMonitor.RootLogPath"/> must be valid and if a GrandOutput.config file exists inside, it is loaded as the configuration.
        /// If it exists, it must be valid (otherwise an exception is thrown).
        /// Once loaded, the file is monitored and any change that occurs to it dynamically triggers a <see cref="SetConfiguration"/> with the new file.
        /// </summary>
        /// <param name="monitor">An optional monitor.</param>
        static public GrandOutput EnsureActiveDefaultWithDefaultSettings(IActivityMonitor monitor = null)
        {
            lock ( _defaultLock )
            {
                if (_default == null)
                {
                    if (monitor == null)
                    {
                        monitor = new SystemActivityMonitor(true, "GrandOutput")
                        {
                            MinimalFilter = GrandOutputMinimalFilter
                        }
                    }
                    ;
                    using (monitor.OpenGroup(LogLevel.Info, "Attempting Default GrandOutput configuration.", null))
                    {
                        try
                        {
                            SystemActivityMonitor.AssertRootLogPathIsSet();
                            _configPath = SystemActivityMonitor.RootLogPath + "GrandOutput.config";
                            GrandOutputConfiguration def = CreateDefaultConfig();
                            if (!File.Exists(_configPath))
                            {
                                File.WriteAllText(_configPath, _defaultConfig);
                            }
                            if (!def.LoadFromFile(_configPath, monitor))
                            {
                                throw new CKException("Unable to load Configuration file: '{0}'.", _configPath);
                            }
                            GrandOutput output = new GrandOutput();
                            if (!output.SetConfiguration(def, monitor))
                            {
                                throw new CKException("Failed to set Configuration.");
                            }
                            StartMonitoring(monitor);
                            _default = output;
                            ActivityMonitor.AutoConfiguration += m => _default.Register(m);
                        }
                        catch (Exception ex)
                        {
                            monitor.SendLine(LogLevel.Fatal, null, ex);
                            throw;
                        }
                    }
                }
            }
            return(_default);
        }

        const string _defaultConfig =
            @"<GrandOutputConfiguration>
    <Channel MinimalFilter=""Debug"">
        <Add Type=""TextFile"" Name=""All"" Path=""GrandOutputDefault"" MaxCountPerFile=""20000"" />
    </Channel>
</GrandOutputConfiguration>";
 static GrandOutputConfiguration CreateDefaultConfig()
 {
     GrandOutputConfiguration def = new GrandOutputConfiguration();
     Debug.Assert( def.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.None );
     Debug.Assert( def.GlobalDefaultFilter == null );
     var route = new RouteConfiguration();
     route.ConfigData = new GrandOutputChannelConfigData() { MinimalFilter = LogFilter.Debug };
     route.AddAction( new TextFileConfiguration( "All" ) { Path = "GrandOutputDefault" } );
     def.ChannelsConfiguration = route;
     return def;
 }
        /// <summary>
        /// Clones this configuration.
        /// </summary>
        /// <returns>Clone of this configuration.</returns>
        public GrandOutputConfiguration Clone()
        {
            var c = new GrandOutputConfiguration
            {
                TimerDuration            = TimerDuration,
                ExternalLogLevelFilter   = ExternalLogLevelFilter,
                MinimalFilter            = MinimalFilter,
                TrackUnhandledExceptions = TrackUnhandledExceptions
            };

            c.Handlers.AddRange(Handlers.Select(h => h.Clone()));
            return(c);
        }
Пример #7
0
        static GrandOutputConfiguration CreateDefaultConfig()
        {
            GrandOutputConfiguration def = new GrandOutputConfiguration();

            Debug.Assert(def.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.None);
            Debug.Assert(def.GlobalDefaultFilter == null);
            var route = new RouteConfiguration();

            route.ConfigData = new GrandOutputChannelConfigData()
            {
                MinimalFilter = LogFilter.Debug
            };
            route.AddAction(new TextFileConfiguration("All")
            {
                Path = "GrandOutputDefault"
            });
            def.ChannelsConfiguration = route;
            return(def);
        }
Пример #8
0
        public void ApplyConfigWithError()
        {
            GrandOutputConfiguration c = new GrandOutputConfiguration();
            Assert.That( c.Load( XDocument.Parse( @"
<GrandOutputConfiguration AppDomainDefaultFilter=""Release"" >
    <Channel>
        <Add Type=""BinaryFile"" Name=""GlobalCatch"" Path=""Configuration/ invalid path? (? is forbidden)"" />
    </Channel>
</GrandOutputConfiguration>"
                ).Root, TestHelper.ConsoleMonitor ) );
            Assert.That( c.ChannelsConfiguration.Configurations.Count, Is.EqualTo( 1 ) );

            GrandOutput g = new GrandOutput();
            Assert.That( g.SetConfiguration( c, TestHelper.ConsoleMonitor ), Is.False );
            Assert.That( g.IsDisposed, Is.False );
            g.Dispose( TestHelper.ConsoleMonitor );
            Assert.That( g.IsDisposed );

        }
Пример #9
0
        /// <summary>
        /// Attempts to set a new configuration.
        /// </summary>
        /// <param name="config">The configuration that must be set.</param>
        /// <param name="monitor">Optional monitor.</param>
        /// <param name="millisecondsBeforeForceClose">Optional timeout to wait before forcing the close of the currently active configuration.</param>
        /// <returns>True on success.</returns>
        public bool SetConfiguration(GrandOutputConfiguration config, IActivityMonitor monitor = null, int millisecondsBeforeForceClose = Timeout.Infinite)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            if (monitor == null)
            {
                monitor = new SystemActivityMonitor(true, "GrandOutput")
                {
                    MinimalFilter = GrandOutputMinimalFilter
                }
            }
            ;
            using (monitor.OpenGroup(LogLevel.Info, this == Default ? "Applying Default GrandOutput configuration." : "Applying GrandOutput configuration.", null))
            {
                if (_channelHost.SetConfiguration(monitor, config.ChannelsConfiguration ?? new RouteConfiguration(), millisecondsBeforeForceClose))
                {
                    if (this == _default && config.GlobalDefaultFilter.HasValue)
                    {
                        ActivityMonitor.DefaultFilter = config.GlobalDefaultFilter.Value;
                    }

                    if (config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.Clear || config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.ClearThenApply)
                    {
                        ActivityMonitor.SourceFilter.ClearOverrides();
                    }
                    if (config.SourceOverrideFilter != null && (config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.Apply || config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.ClearThenApply))
                    {
                        foreach (var k in config.SourceOverrideFilter)
                        {
                            ActivityMonitor.SourceFilter.SetOverrideFilter(k.Value, k.Key);
                        }
                    }
                    monitor.CloseGroup("Success.");
                    return(true);
                }
                return(false);
            }
        }
Пример #10
0
 GrandOutput(bool isDefault, GrandOutputConfiguration config)
 {
     if (config == null)
     {
         throw new ArgumentNullException(nameof(config));
     }
     // Creates the identity card and the client list first.
     _identityCard  = new IdentityCard();
     _clients       = new List <WeakReference <GrandOutputClient> >();
     _minimalFilter = LogFilter.Undefined;
     // Starts the pump thread. Its monitor will be registered
     // in this GrandOutput.
     _sink = new DispatcherSink(m => DoEnsureGrandOutputClient(m),
                                _identityCard,
                                config.TimerDuration ?? TimeSpan.FromMilliseconds(500),
                                TimeSpan.FromMinutes(5),
                                DoGarbageDeadClients,
                                OnFiltersChanged,
                                isDefault);
     ApplyConfiguration(config, waitForApplication: true);
     ActivityMonitor.StaticLogger.OnStaticLog += _sink.ExternalOrStaticLog;
 }
Пример #11
0
        /// <summary>
        /// Attempts to set a new configuration.
        /// </summary>
        /// <param name="config">The configuration that must be set.</param>
        /// <param name="monitor">Optional monitor.</param>
        /// <param name="millisecondsBeforeForceClose">Optional timeout to wait before forcing the close of the currently active configuration.</param>
        /// <returns>True on success.</returns>
        public bool SetConfiguration( GrandOutputConfiguration config, IActivityMonitor monitor = null, int millisecondsBeforeForceClose = Timeout.Infinite )
        {
            if( config == null ) throw new ArgumentNullException( "config" );
            if( monitor == null ) monitor = new SystemActivityMonitor( true, "GrandOutput" ) { MinimalFilter = GrandOutputMinimalFilter };
            using( monitor.OpenGroup( LogLevel.Info, this == Default ? "Applying Default GrandOutput configuration." : "Applying GrandOutput configuration.", null ) )
            {
                if( _channelHost.SetConfiguration( monitor, config.ChannelsConfiguration ?? new RouteConfiguration(), millisecondsBeforeForceClose ) )
                {
                    if( this == _default &&  config.GlobalDefaultFilter.HasValue ) ActivityMonitor.DefaultFilter = config.GlobalDefaultFilter.Value;

                    if( config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.Clear || config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.ClearThenApply )
                    {
                        ActivityMonitor.SourceFilter.ClearOverrides();
                    }
                    if( config.SourceOverrideFilter != null && (config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.Apply || config.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.ClearThenApply) )
                    {
                        foreach( var k in config.SourceOverrideFilter ) ActivityMonitor.SourceFilter.SetOverrideFilter( k.Value, k.Key );
                    }
                    monitor.CloseGroup( "Success." );
                    return true;
                }
                return false;
            }
        }
Пример #12
0
        public void ApplyConfigSimple()
        {
            GrandOutputConfiguration c = new GrandOutputConfiguration();

            Assert.That( c.Load( XDocument.Parse( @"
<GrandOutputConfiguration AppDomainDefaultFilter=""Release"" >
    <Channel MinimalFilter=""{Trace,Info}"">
        <Add Type=""BinaryFile"" Name=""GlobalCatch"" Path=""Configuration/ApplyConfig"" />
    </Channel>
</GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor ) );

            Assert.That( c.ChannelsConfiguration.Configurations.Count, Is.EqualTo( 1 ) );

            ActivityMonitor m = new ActivityMonitor( false );
            using( GrandOutput g = new GrandOutput() )
            {
                m.Info().Send( "Before Registering - NOSHOW" );
                g.Register( m );
                m.Info().Send( "Before configuration - NOSHOW" );
                Assert.That( g.SetConfiguration( c, TestHelper.ConsoleMonitor ) );
                m.Info().Send( "After configuration. INFO1" );

                Assert.That( m.ActualFilter, Is.EqualTo( new LogFilter( LogLevelFilter.Trace, LogLevelFilter.Info ) ) ); 
                m.Trace().Send( "TRACE1-NOSHOW (MinimalFilter of the Channel)." );
                
                Assert.That( g.SetConfiguration( new GrandOutputConfiguration(), TestHelper.ConsoleMonitor ) );
                g.Dispose( TestHelper.ConsoleMonitor );

                m.Info().Send( "After disposing - NOSHOW." );

                Assert.That( m.ActualFilter, Is.EqualTo( LogFilter.Undefined ) ); 
            }
            
        }
Пример #13
0
 public void InvalidRootNode()
 {
     GrandOutputConfiguration c = new GrandOutputConfiguration();
     Assert.That( c.Load( XDocument.Parse( @"<root><Add Type=""BinaryFile"" /></root>" ).Root, TestHelper.ConsoleMonitor ), Is.False );
 }
Пример #14
0
 /// <summary>
 /// Initializes a new <see cref="GrandOutput"/>.
 /// </summary>
 /// <param name="config">The configuration.</param>
 public GrandOutput(GrandOutputConfiguration config)
     : this(false, config)
 {
 }