/// <summary>
        /// Write log events to a series of files. Each file will be named according to
        /// the date of the first log entry written to it. Only simple date-based rolling is
        /// currently supported.
        /// </summary>
        /// <param name="sinkConfiguration">Logger sink configuration.</param>
        /// <param name="pathFormat">String describing the location of the log files,
        /// with {Date} in the place of the file date. E.g. "Logs\myapp-{Date}.log" will result in log
        /// files such as "Logs\myapp-2013-10-20.log", "Logs\myapp-2013-10-21.log" and so on.</param>
        /// <param name="restrictedToMinimumLevel">The minimum level for
        /// events passed through the sink.</param>
        /// <param name="outputTemplate">A message template describing the format used to write to the sink.
        /// the default is "{Timestamp} [{Level}] {Message}{NewLine}{Exception}".</param>
        /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
        /// <param name="fileSizeLimitBytes">The maximum size, in bytes, to which any single log file will be allowed to grow.
        /// For unrestricted growth, pass null. The default is 1 GB.</param>
        /// <param name="retainedFileCountLimit">The maximum number of log files that will be retained,
        /// including the current log file. For unlimited retention, pass null. The default is 31.</param>
        /// <returns>Configuration object allowing method chaining.</returns>
        /// <remarks>The file will be written using the UTF-8 character set.</remarks>
        public static LoggerConfiguration RollingFile(
            this LoggerSinkConfiguration sinkConfiguration,
            string pathFormat,
            LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
            string outputTemplate          = DefaultOutputTemplate,
            IFormatProvider formatProvider = null,
            long?fileSizeLimitBytes        = DefaultFileSizeLimitBytes,
            int?retainedFileCountLimit     = DefaultRetainedFileCountLimit)
        {
            if (sinkConfiguration == null)
            {
                throw new ArgumentNullException("sinkConfiguration");
            }
            if (outputTemplate == null)
            {
                throw new ArgumentNullException("outputTemplate");
            }
            var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
            var sink      = new RollingFileSink(pathFormat, formatter, fileSizeLimitBytes, retainedFileCountLimit);

            return(sinkConfiguration.Sink(sink, restrictedToMinimumLevel));
        }
        public DurableKinesisSink(KinesisSinkOptions options)
        {
            var state = KinesisSinkState.Create(options);

            if (string.IsNullOrWhiteSpace(options.BufferBaseFilename))
            {
                throw new ArgumentException("Cannot create the durable Amazon Kinesis sink without a buffer base file name.");
            }

            _sink = new RollingFileSink(
                options.BufferBaseFilename + "-{Date}.json",
                state.DurableFormatter,
                options.BufferFileSizeLimitBytes,
                null);

            _shipper = new HttpLogShipper(state);

            if (options.OnLogSendError != null)
            {
                _shipper.LogSendError += options.OnLogSendError;
            }
        }
예제 #3
0
        public DurableSeqSink(
            string serverUrl,
            string bufferBaseFilename,
            string apiKey,
            int batchPostingLimit,
            TimeSpan period,
            long?bufferFileSizeLimitBytes,
            long?eventBodyLimitBytes,
            LoggingLevelSwitch levelControlSwitch,
            HttpMessageHandler messageHandler,
            long?retainedInvalidPayloadsLimitBytes)
        {
            if (serverUrl == null)
            {
                throw new ArgumentNullException(nameof(serverUrl));
            }
            if (bufferBaseFilename == null)
            {
                throw new ArgumentNullException(nameof(bufferBaseFilename));
            }

            _shipper = new HttpLogShipper(
                serverUrl,
                bufferBaseFilename,
                apiKey,
                batchPostingLimit,
                period,
                eventBodyLimitBytes,
                levelControlSwitch,
                messageHandler,
                retainedInvalidPayloadsLimitBytes);

            _sink = new RollingFileSink(
                bufferBaseFilename + "-{Date}.json",
                new RawJsonFormatter(),
                bufferFileSizeLimitBytes,
                null,
                encoding: Encoding.UTF8);
        }
        public DurableLogglySink(
            string bufferBaseFilename,
            int batchPostingLimit,
            TimeSpan period,
            long?bufferFileSizeLimitBytes,
            long?eventBodyLimitBytes,
            LoggingLevelSwitch levelControlSwitch,
            long?retainedInvalidPayloadsLimitBytes,
            int?retainedFileCountLimit     = null,
            IFormatProvider formatProvider = null
            )
        {
            if (bufferBaseFilename == null)
            {
                throw new ArgumentNullException(nameof(bufferBaseFilename));
            }

            //use a consistent UTF encoding with BOM so no confusion will exist when reading / deserializing
            var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);

            //handles sending events to Loggly's API through LogglyClient and manages the pending list
            _shipper = new HttpLogShipper(
                bufferBaseFilename,
                batchPostingLimit,
                period,
                eventBodyLimitBytes,
                levelControlSwitch,
                retainedInvalidPayloadsLimitBytes,
                encoding);

            //writes events to the file to support connection recovery
            _sink = new RollingFileSink(
                bufferBaseFilename + "-{Date}.json",
                new LogglyFormatter(formatProvider), //serializes as LogglyEvent
                bufferFileSizeLimitBytes,
                retainedFileCountLimit,
                encoding);
        }
예제 #5
0
        public static ILogger Configure(IConfigurationRoot config)
        {
            var logFilename = config["Serilog:LogFilename"];
            var seqEnabled  = bool.Parse(config["Serilog:SeqEnabled"]);
            var seqApiKey   = config["Serilog:SeqApiKey"];
            var seqUrl      = config["Serilog:SeqUrl"];
            var directory   = logFilename.Replace("${basedir}", Directory.GetCurrentDirectory());

            var logSink = new RollingFileSink(directory, new JsonFormatter(), null, 100);

            var loggerConfiguration = new LoggerConfiguration()
                                      .MinimumLevel.Debug()
                                      .Enrich.FromLogContext()
                                      .WriteTo.Sink(logSink);

            if (seqEnabled)
            {
                return(loggerConfiguration
                       .WriteTo.Seq(seqUrl, apiKey: seqApiKey)
                       .CreateLogger());
            }

            return(loggerConfiguration.CreateLogger());
        }
        /// <summary>
        /// Write log events to a series of files asynchronously. Each file will be named according to
        /// the date of the first log entry written to it. Only simple date-based rolling is
        /// currently supported.
        /// </summary>
        /// <param name="sinkConfiguration">Logger sink configuration.</param>
        /// <param name="formatter">Formatter to control how events are rendered into the file. To control
        /// plain text formatting, use the overload that accepts an output template instead.</param>
        /// <param name="pathFormat">String describing the location of the log files,
        /// with {Date} in the place of the file date. E.g. "Logs\myapp-{Date}.log" will result in log
        /// files such as "Logs\myapp-2013-10-20.log", "Logs\myapp-2013-10-21.log" and so on.</param>
        /// <param name="restrictedToMinimumLevel">The minimum level for
        /// events passed through the sink. Ignored when <paramref name="levelSwitch"/> is specified.</param>
        /// <param name="levelSwitch">A switch allowing the pass-through minimum level
        /// to be changed at runtime.</param>
        /// <param name="fileSizeLimitBytes">The maximum size, in bytes, to which any single log file will be allowed to grow.
        /// For unrestricted growth, pass null. The default is 1 GB.</param>
        /// <param name="retainedFileCountLimit">The maximum number of log files that will be retained,
        /// including the current log file. For unlimited retention, pass null. The default is 31.</param>
        /// <param name="buffered">Indicates if flushing to the output file can be buffered or not. The default
        /// is false.</param>
        /// <param name="shared">Allow the log files to be shared by multiple processes. The default is false.</param>
        /// <param name="flushToDiskInterval">If provided, a full disk flush will be performed periodically at the specified interval.</param>
        /// <param name="queueSize">The size of the concurrent queue used to feed the background worker thread. If
        /// the thread is unable to process events quickly enough and the queue is filled, subsequent events will be
        /// dropped until room is made in the queue.</param>
        /// <returns>Configuration object allowing method chaining.</returns>
        /// <remarks>The file will be written using the UTF-8 encoding without a byte-order mark.</remarks>
        public static LoggerConfiguration AsyncRollingFile(
            this LoggerSinkConfiguration sinkConfiguration,
            ITextFormatter formatter,
            string pathFormat,
            LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
            long?fileSizeLimitBytes        = DefaultFileSizeLimitBytes,
            int?retainedFileCountLimit     = DefaultRetainedFileCountLimit,
            LoggingLevelSwitch levelSwitch = null,
            bool buffered = false,
            bool shared   = false,
            TimeSpan?flushToDiskInterval = null,
            int queueSize = 65536)
        {
            if (sinkConfiguration == null)
            {
                throw new ArgumentNullException(nameof(sinkConfiguration));
            }
            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }

            if (shared && buffered)
            {
                throw new ArgumentException("Buffered writes are not available when file sharing is enabled.", nameof(buffered));
            }

            ILogEventSink sink = new RollingFileSink(pathFormat, formatter, fileSizeLimitBytes, retainedFileCountLimit, buffered: buffered, shared: shared);

            if (flushToDiskInterval.HasValue)
            {
                sink = new PeriodicFlushToDiskSink(sink, flushToDiskInterval.Value);
            }

            return(sinkConfiguration.Async(c => c.Sink(sink, restrictedToMinimumLevel, levelSwitch), queueSize));
        }
예제 #7
0
        public DurableKinesisFirehoseSink(KinesisFirehoseSinkOptions options, IAmazonKinesisFirehose kinesisFirehoseClient)
        {
            var state = new KinesisSinkState(options, kinesisFirehoseClient);

            if (string.IsNullOrWhiteSpace(options.BufferBaseFilename))
            {
                throw new ArgumentException("Cannot create the durable Amazon Kinesis Firehose sink without a buffer base file name.");
            }

            _sink = new RollingFileSink(
                options.BufferBaseFilename + "-{Date}.json",
                state.DurableFormatter,
                options.BufferFileSizeLimitBytes,
                null,
                shared: options.Shared);

            _shipper = new HttpLogShipper(state);

            _logSendErrorHandler = options.OnLogSendError;
            if (_logSendErrorHandler != null)
            {
                _shipper.LogSendError += _logSendErrorHandler;
            }
        }
예제 #8
0
        static LoggerConfiguration ConfigureFile(
            this Func <ILogEventSink, LogEventLevel, LoggingLevelSwitch, LoggerConfiguration> addSink,
            ITextFormatter formatter,
            string path,
            LogEventLevel restrictedToMinimumLevel,
            long?fileSizeLimitBytes,
            LoggingLevelSwitch levelSwitch,
            bool buffered,
            bool propagateExceptions,
            bool shared,
            TimeSpan?flushToDiskInterval,
            Encoding encoding,
            PersistentFileRollingInterval persistentFileRollingInterval,
            bool rollOnFileSizeLimit,
            int?retainedFileCountLimit,
            FileLifecycleHooks hooks,
            bool preserveLogFilename     = true,
            bool rollOnEachProcessRun    = true,
            bool useLastWriteAsTimestamp = false)
        {
            if (addSink == null)
            {
                throw new ArgumentNullException(nameof(addSink));
            }
            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0)
            {
                throw new ArgumentException("Negative value provided; file size limit must be non-negative.", nameof(fileSizeLimitBytes));
            }
            if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1)
            {
                throw new ArgumentException("At least one file must be retained.", nameof(retainedFileCountLimit));
            }
            if (shared && buffered)
            {
                throw new ArgumentException("Buffered writes are not available when file sharing is enabled.", nameof(buffered));
            }
            if (shared && hooks != null)
            {
                throw new ArgumentException("File lifecycle hooks are not currently supported for shared log files.", nameof(hooks));
            }

            ILogEventSink sink;

            if (rollOnFileSizeLimit || persistentFileRollingInterval != PersistentFileRollingInterval.Infinite)
            {
                sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, persistentFileRollingInterval, rollOnFileSizeLimit, hooks, preserveLogFilename, rollOnEachProcessRun, useLastWriteAsTimestamp);
            }
            else
            {
                try
                {
                    if (shared)
                    {
#pragma warning disable 618
                        sink = new SharedFileSink(path, formatter, fileSizeLimitBytes, encoding);
#pragma warning restore 618
                    }
                    else
                    {
                        sink = new FileSink(path, formatter, fileSizeLimitBytes, encoding, buffered, hooks);
                    }
                }
                catch (Exception ex)
                {
                    SelfLog.WriteLine("Unable to open file sink for {0}: {1}", path, ex);

                    if (propagateExceptions)
                    {
                        throw;
                    }

                    return(addSink(new NullSink(), LevelAlias.Maximum, null));
                }
            }

            if (flushToDiskInterval.HasValue)
            {
#pragma warning disable 618
                sink = new PeriodicFlushToDiskSink(sink, flushToDiskInterval.Value);
#pragma warning restore 618
            }

            return(addSink(sink, restrictedToMinimumLevel, levelSwitch));
        }
        static LoggerConfiguration ConfigureFile(
            this Func <ILogEventSink, LogEventLevel, LoggingLevelSwitch, LoggerConfiguration> addSink,
            ITextFormatter formatter,
            string path,
            LogEventLevel restrictedToMinimumLevel,
            long?fileSizeLimitBytes,
            LoggingLevelSwitch levelSwitch,
            bool buffered,
            bool propagateExceptions,
            bool shared,
            TimeSpan?flushToDiskInterval,
            Encoding encoding,
            RollingInterval rollingInterval,
            bool rollOnFileSizeLimit,
            int?retainedFileCountLimit)
        {
            if (addSink == null)
            {
                throw new ArgumentNullException(nameof(addSink));
            }
            if (formatter == null)
            {
                throw new ArgumentNullException(nameof(formatter));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0)
            {
                throw new ArgumentException("Negative value provided; file size limit must be non-negative.", nameof(fileSizeLimitBytes));
            }
            if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1)
            {
                throw new ArgumentException("At least one file must be retained.", nameof(retainedFileCountLimit));
            }
            if (shared && buffered)
            {
                throw new ArgumentException("Buffered writes are not available when file sharing is enabled.", nameof(buffered));
            }

            ILogEventSink sink;

            if (rollOnFileSizeLimit || rollingInterval != RollingInterval.Infinite)
            {
                sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, rollingInterval, rollOnFileSizeLimit);
            }
            else
            {
                try
                {
#pragma warning disable 618
                    if (shared)
                    {
                        sink = new SharedFileSink(path, formatter, fileSizeLimitBytes);
                    }
                    else
                    {
                        sink = new FileSink(path, formatter, fileSizeLimitBytes, buffered: buffered);
                    }
#pragma warning restore 618
                }
                catch (Exception ex)
                {
                    SelfLog.WriteLine("Unable to open file sink for {0}: {1}", path, ex);

                    if (propagateExceptions)
                    {
                        throw;
                    }

                    return(addSink(new NullSink(), LevelAlias.Maximum, null));
                }
            }

            if (flushToDiskInterval.HasValue)
            {
                sink = new PeriodicFlushToDiskSink(sink, flushToDiskInterval.Value);
            }

            return(addSink(sink, restrictedToMinimumLevel, levelSwitch));
        }