예제 #1
0
        public void Should_compress_deleting_log_files_in_place()
        {
            var archiveWrapper = new ArchiveHooks();

            using (var temp = TempFolder.ForCaller())
            {
                var path = temp.AllocateFilename("log");

                // Write events, such that we end up with 2 deleted files and 1 retained file
                WriteLogEvents(path, archiveWrapper, LogEvents);

                // Get all the files in the test directory
                var files = Directory.GetFiles(temp.Path)
                            .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
                            .ToArray();

                // We should have a single log file, and 2 gz files
                files.Count(x => x.EndsWith("log")).ShouldBe(1);
                files.Count(x => x.EndsWith("gz")).ShouldBe(2);

                // Ensure the data was GZip compressed, by decompressing and comparing against what we wrote
                int i = 0;
                foreach (var gzipFile in files.Where(x => x.EndsWith("gz")))
                {
                    var lines = Utils.DecompressLines(gzipFile);

                    lines.Count.ShouldBe(1);
                    lines[0].ShouldEndWith(LogEvents[i].MessageTemplate.Text);
                    i++;
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Write log events to Serilog, using a rolling log file configuration with a 1-byte size limit, so we roll
 /// after each log event, and with a retained count of 1 so 2 files will be deleted and 1 retained
 /// </summary>
 private static void WriteLogEvents(string path, ArchiveHooks hooks, LogEvent[] logEvents)
 {
     using (var log = new LoggerConfiguration()
                      .WriteTo.File(path, rollOnFileSizeLimit: true, fileSizeLimitBytes: 1, retainedFileCountLimit: 1, hooks: hooks)
                      .CreateLogger())
     {
         foreach (var logEvent in logEvents)
         {
             log.Write(logEvent);
         }
     }
 }
예제 #3
0
        public SerilogHooks(long limitBytes, int retainedFileCountLimit, string pathArchive = null, CompressionLevel compression = CompressionLevel.Fastest)
        {
            _limitBytes = limitBytes;

            _pathArchive = pathArchive;

            _retainedFileCountLimit = retainedFileCountLimit;

            if (string.IsNullOrEmpty(_pathArchive))
            {
                _pathArchive = null;
            }

            MyArchiveHooks = new ArchiveHooks(CompressionLevel.Fastest, _pathArchive);
        }
예제 #4
0
        public void Should_expand_tokens_in_target_path()
        {
            using (var temp = TempFolder.ForCaller())
            {
                var subfolder     = temp.AllocateFolderName();
                var targetDirPath = Path.Combine(subfolder, "{Date:yyyy}");
                var path          = temp.AllocateFilename("log");

                var archiveWrapper = new ArchiveHooks(CompressionLevel.NoCompression, targetDirPath);

                // Write events, such that we end up with 2 deleted files and 1 retained file
                WriteLogEvents(path, archiveWrapper, LogEvents);

                // Get the final, expanded target directory
                var targetDirs = Directory.GetDirectories(subfolder);
                targetDirs.Length.ShouldBe(1);

                // Ensure the directory name contains the expanded date token
                targetDirs[0].ShouldEndWith(DateTime.Now.ToString("yyyy"));
            }
        }
예제 #5
0
        public void Should_copy_deleting_log_files()
        {
            using (var temp = TempFolder.ForCaller())
            {
                var targetDirPath = temp.AllocateFolderName();
                var path          = temp.AllocateFilename("log");

                var archiveWrapper = new ArchiveHooks(CompressionLevel.NoCompression, targetDirPath);

                // Write events, such that we end up with 2 deleted files and 1 retained file
                WriteLogEvents(path, archiveWrapper, LogEvents);

                // Get all the files in the test directory
                var files = Directory.GetFiles(temp.Path)
                            .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
                            .ToArray();

                // We should only have a single log file
                files.Length.ShouldBe(1);

                // Get all the files in the target directory
                var targetFiles = Directory.GetFiles(targetDirPath)
                                  .OrderBy(p => p, StringComparer.OrdinalIgnoreCase)
                                  .ToArray();

                // We should have 2 log files in the target directory
                targetFiles.Length.ShouldBe(2);
                targetFiles.ShouldAllBe(x => x.EndsWith(".log"));

                // Ensure the content matches what we wrote
                for (var i = 0; i < targetFiles.Length; i++)
                {
                    var lines = System.IO.File.ReadAllLines(targetFiles[i]);

                    lines.Length.ShouldBe(1);
                    lines[0].ShouldEndWith(LogEvents[i].MessageTemplate.Text);
                }
            }
        }
        private static LoggerConfiguration configFromWebApiConfig(LoggerConfiguration loggerConfiguration, WebApiConfig apiConfig)
        {
            apiConfig = apiConfig ?? new WebApiConfig();

            loggerConfiguration.MinimumLevel.ControlledBy(apiConfig.InnerSerilogLevels.AppLogLevel)
            .MinimumLevel.Override("Microsoft", apiConfig.InnerSerilogLevels.SystemLogLevel)
            .MinimumLevel.Override("System", apiConfig.InnerSerilogLevels.SystemLogLevel)
            .MinimumLevel.Override("Microsoft.AspNetCore", apiConfig.InnerSerilogLevels.AppLogLevel)
            .MinimumLevel.Override("Microsoft.Hosting", apiConfig.InnerSerilogLevels.AppLogLevel)
            .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", apiConfig.InnerSerilogLevels.EFCoreCommandLevel)
            .MinimumLevel.Override("System.Net.Http.HttpClient", apiConfig.InnerSerilogLevels.AppLogLevel)
            .MinimumLevel.Override("ServerRequest.Logger", apiConfig.InnerSerilogLevels.ServerRequestLevel)
            .MinimumLevel.Override("ClientRequest.Logger", apiConfig.InnerSerilogLevels.ClientRequestLevel)
            .Destructure.ToMaximumStringLength(apiConfig.MaxLogLength);

            loggerConfiguration = loggerConfiguration.Enrich.FromLogContext();
            if (apiConfig.ConsoleJsonLog)
            {
                loggerConfiguration = loggerConfiguration.WriteTo.Console(new CompactJsonFormatter(apiConfig));
            }
            else if (apiConfig.ConsoleLog)
            {
                loggerConfiguration = loggerConfiguration.WriteTo.Console();
            }
            else
            {
                loggerConfiguration = loggerConfiguration.WriteTo.Console(Serilog.Events.LogEventLevel.Warning);
            }
            if (apiConfig.FileLog || apiConfig.FileJsonLog)
            {
                string path = apiConfig.GetLogPath();

                string pathTemplate = apiConfig.LogPathTemplate;
                if (string.IsNullOrEmpty(pathTemplate))
                {
                    pathTemplate = LogPathTemplates.DayFolderAndLoggerNameFile;
                }

                Serilog.Formatting.Display.MessageTemplateTextFormatter pathFormatter = new Serilog.Formatting.Display.MessageTemplateTextFormatter(pathTemplate);

                ArchiveHooks archiveHooks = new ArchiveHooks(CompressionLevel.Fastest);
                string       template     = apiConfig.LogTemplate;
                if (string.IsNullOrEmpty(template))
                {
                    template = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{NewLine}{Exception}";
                }
                bool keySelector(Serilog.Events.LogEvent logEvent, out LogPathAndTimeKey key)
                {
                    StringWriter  sw = new StringWriter();
                    StringBuilder sb = new StringBuilder();

                    pathFormatter.Format(logEvent, sw);
                    sw.Flush();
                    string dp = sw.GetStringBuilder().ToString();
                    string p  = Path.Combine(path, dp);

                    key = new LogPathAndTimeKey()
                    {
                        Path = p,
                        Time = logEvent.Timestamp.Date
                    };
                    return(true);
                };

                if (apiConfig.FileJsonLog)
                {
                    var formatter = new CompactJsonFormatter(apiConfig);
                    loggerConfiguration = loggerConfiguration
                                          .WriteTo.MapCondition <LogPathAndTimeKey>(keySelector, (path, lc) =>
                    {
                        lc.Async(lc => lc.File(
                                     formatter,
                                     path.Path,
                                     rollingInterval: RollingInterval.Infinite,
                                     rollOnFileSizeLimit: true,
                                     fileSizeLimitBytes: apiConfig.MaxLogFileSize,
                                     retainedFileCountLimit: apiConfig.RetainedFileCount,
                                     hooks: archiveHooks));
                    }, key =>
                    {
                        // 自动Dispose前一天的日志
                        DateTimeOffset now = DateTimeOffset.Now.Date;
                        if (now > key.Time.Date)
                        {
                            return(true);
                        }
                        return(false);
                    });
                }
                else
                {
                    loggerConfiguration = loggerConfiguration
                                          .WriteTo.MapCondition <LogPathAndTimeKey>(keySelector, (path, lc) =>
                    {
                        lc.Async(lc => lc.File(
                                     path.Path,
                                     rollingInterval: RollingInterval.Infinite,
                                     rollOnFileSizeLimit: true,
                                     fileSizeLimitBytes: apiConfig.MaxLogFileSize,
                                     retainedFileCountLimit: apiConfig.RetainedFileCount,
                                     hooks: archiveHooks,
                                     outputTemplate: template));
                    }, key =>
                    {
                        // 自动Dispose前一天的日志
                        DateTimeOffset now = DateTimeOffset.Now.Date;
                        if (now > key.Time.Date)
                        {
                            return(true);
                        }
                        return(false);
                    });
                }
            }

            return(loggerConfiguration);
        }