{"id":19754936,"url":"https://github.com/nreco/logging","last_synced_at":"2025-05-14T15:07:31.712Z","repository":{"id":20907318,"uuid":"91232588","full_name":"nreco/logging","owner":"nreco","description":"Generic file logger for .NET Core (FileLoggerProvider) with minimal dependencies","archived":false,"fork":false,"pushed_at":"2024-11-18T13:27:37.000Z","size":85,"stargazers_count":312,"open_issues_count":14,"forks_count":63,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-14T06:48:21.620Z","etag":null,"topics":["dotnet-core","file","logging"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nreco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-14T09:19:07.000Z","updated_at":"2025-03-31T22:33:12.000Z","dependencies_parsed_at":"2022-08-07T09:16:24.163Z","dependency_job_id":"c59929a6-c40a-445c-bfc8-3b3cdc01a8df","html_url":"https://github.com/nreco/logging","commit_stats":{"total_commits":31,"total_committers":6,"mean_commits":5.166666666666667,"dds":"0.19354838709677424","last_synced_commit":"a03fe597abceb905023d70b6b65a282ae1425ad4"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nreco%2Flogging","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nreco%2Flogging/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nreco%2Flogging/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nreco%2Flogging/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nreco","download_url":"https://codeload.github.com/nreco/logging/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254169716,"owners_count":22026214,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dotnet-core","file","logging"],"created_at":"2024-11-12T03:06:46.088Z","updated_at":"2025-05-14T15:07:31.695Z","avatar_url":"https://github.com/nreco.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NReco.Logging.File\nSimple and efficient file logger provider for NET6 / NET8 / NET9 without any additional dependencies.\n\nNuGet | Tests\n--- | --- \n[![NuGet Release](https://img.shields.io/nuget/v/NReco.Logging.File.svg)](https://www.nuget.org/packages/NReco.Logging.File/) | ![Tests](https://github.com/nreco/logging/actions/workflows/dotnet-test.yml/badge.svg) \n\n* very similar to standard ConsoleLogger but writes to a file\n* can append to existing file or overwrite log file on restart\n* supports a 'rolling file' behaviour and can control total log size\n* it is possible to change log file name on-the-fly\n* suitable for intensive concurrent usage: has internal message queue to avoid threads blocking\n* optimized low-allocation default log messages formatting suitable for intensive usage\n\n## How to use\nAdd *NReco.Logging.File* package reference and initialize a file logging provider in `services.AddLogging` (Startup.cs):\n```csharp\nusing NReco.Logging.File;\n\nservices.AddLogging(loggingBuilder =\u003e {\n\tloggingBuilder.AddFile(\"app.log\", append:true);\n});\n```\nor\n```csharp\nservices.AddLogging(loggingBuilder =\u003e {\n\tvar loggingSection = Configuration.GetSection(\"Logging\");\n\tloggingBuilder.AddFile(loggingSection);\n});\n```\nExample of the configuration section in appsettings.json:\n```jsonc\n\"Logging\": {\n\t\"LogLevel\": {\n\t  \"Default\": \"Debug\",\n\t  \"System\": \"Information\",\n\t  \"Microsoft\": \"Error\"\n\t},\n\t\"File\": {\n\t\t\"Path\": \"app.log\",\n\t\t\"Append\": true,\n\t\t\"MinLevel\": \"Warning\",  // min level for the file logger\n\t\t\"FileSizeLimitBytes\": 0,  // use to activate rolling file behaviour\n\t\t\"MaxRollingFiles\": 0  // use to specify max number of log files\n\t}\n}\n```\n\n## Rolling File\nThis feature is activated with `FileLoggerOptions` properties: `FileSizeLimitBytes` and `MaxRollingFiles`. Lets assume that file logger is configured for \"test.log\":\n\n* if only `FileSizeLimitBytes` is specified file logger will create \"test.log\", \"test1.log\", \"test2.log\" etc\n* use `MaxRollingFiles` in addition to `FileSizeLimitBytes` to limit number of log files; for example, for value \"3\" file logger will create \"test.log\", \"test1.log\", \"test2.log\" and again \"test.log\", \"test1.log\" (old files will be overwritten).\n* if file name is changed in time (with `FormatLogFileName` handler) max number of files works only for the same file name. For example, if file name is based on date, `MaxRollingFiles` will limit number of log files only for the concrete date.\n\n## Change log file name on-the-fly\nIt is possible to specify a custom log file name formatter with `FileLoggerOptions` property `FormatLogFileName`. Log file name may change in time - for example, to create a new log file per day:\n```csharp\nservices.AddLogging(loggingBuilder =\u003e {\n\tloggingBuilder.AddFile(\"app_{0:yyyy}-{0:MM}-{0:dd}.log\", fileLoggerOpts =\u003e {\n\t\tfileLoggerOpts.FormatLogFileName = fName =\u003e {\n\t\t\treturn String.Format(fName, DateTime.UtcNow);\n\t\t};\n\t});\n});\n```\nNote that this handler is called on _every_ log message 'write'; you may cache the log file name calculation in your handler to avoid any potential overhead in case of high-load logger usage.\n\n## Custom log entry formatting\nYou can specify `FileLoggerOptions.FormatLogEntry` handler to customize log entry content. For example, it is possible to write log entry as JSON array:\n```csharp\nloggingBuilder.AddFile(\"logs/app.js\", fileLoggerOpts =\u003e {\n\tfileLoggerOpts.FormatLogEntry = (msg) =\u003e {\n\t\tvar sb = new System.Text.StringBuilder();\n\t\tStringWriter sw = new StringWriter(sb);\n\t\tvar jsonWriter = new Newtonsoft.Json.JsonTextWriter(sw);\n\t\tjsonWriter.WriteStartArray();\n\t\tjsonWriter.WriteValue(DateTime.Now.ToString(\"o\"));\n\t\tjsonWriter.WriteValue(msg.LogLevel.ToString());\n\t\tjsonWriter.WriteValue(msg.LogName);\n\t\tjsonWriter.WriteValue(msg.EventId.Id);\n\t\tjsonWriter.WriteValue(msg.Message);\n\t\tjsonWriter.WriteValue(msg.Exception?.ToString());\n\t\tjsonWriter.WriteEndArray();\n\t\treturn sb.ToString();\n\t}\n});\n```\n\n## Custom log entry filtering\nYou may provide a predicate to perform filter log entries filtering on the logging provider level. This may be useful if you want to have 2 (or more)\nfile loggers that separate log entries between log files on some criteria:\n```csharp\nloggingBuilder.AddFile(\"logs/errors_only.log\", fileLoggerOpts =\u003e {\n\tfileLoggerOpts.FilterLogEntry = (msg) =\u003e {\n\t\treturn msg.LogLevel == LogLevel.Error;\n\t}\n});\n```\n\n## File errors handling\nLog file is opened immediately when `FileLoggerProvider` is created (= on `AddFile` call) and you may handle initial file opening errors simply by wrapping `AddFile` with a `try .. catch`. \nHowever you might want to propose a new log file name to guartee that file logging works even if an original log file is not accessible. To provide your own handling of file errors you may specify `HandleFileError` delegate:\n```csharp\nloggingBuilder.AddFile(loggingSection, fileLoggerOpts =\u003e {\n\tfileLoggerOpts.HandleFileError = (err) =\u003e {\n\t\terr.UseNewLogFileName( Path.GetFileNameWithoutExtension(err.LogFileName)+ \"_alt\" + Path.GetExtension(err.LogFileName) );\n\t};\n});\n```\nReal-life implementation may be more complicated to guarantee that a new file name can be used without errors; note that `HandleFileError` is not recursive and it will not be called if proposed file name cannot be opened too. \n\nA new file name is applied in the same way as when it comes from the initial `FileLoggerProvider` options (if `FormatLogFileName` is specified it is called to resolve a final log file name).\n\n\n## License\nCopyright 2017-2024 Vitaliy Fedorchenko and contributors\n\nDistributed under the MIT license\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnreco%2Flogging","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnreco%2Flogging","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnreco%2Flogging/lists"}