{"id":28493920,"url":"https://github.com/chickensoft-games/log","last_synced_at":"2025-07-08T13:32:43.774Z","repository":{"id":275652695,"uuid":"919705449","full_name":"chickensoft-games/Log","owner":"chickensoft-games","description":"Opinionated logging interface and implementations for C# applications and libraries.","archived":false,"fork":false,"pushed_at":"2025-06-26T23:47:55.000Z","size":111,"stargazers_count":8,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-03T16:10:42.067Z","etag":null,"topics":["chickensoft","logging"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/Chickensoft.Log","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/chickensoft-games.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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,"zenodo":null}},"created_at":"2025-01-20T21:20:39.000Z","updated_at":"2025-06-27T19:12:15.000Z","dependencies_parsed_at":"2025-02-03T21:24:12.389Z","dependency_job_id":"4af284aa-0911-4699-aa06-7b43ba5d1207","html_url":"https://github.com/chickensoft-games/Log","commit_stats":null,"previous_names":["chickensoft-games/log"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/chickensoft-games/Log","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chickensoft-games","download_url":"https://codeload.github.com/chickensoft-games/Log/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chickensoft-games%2FLog/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264277793,"owners_count":23583680,"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":["chickensoft","logging"],"created_at":"2025-06-08T09:37:26.968Z","updated_at":"2025-07-08T13:32:43.767Z","avatar_url":"https://github.com/chickensoft-games.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🪵 Log\n\n[![Chickensoft Badge][chickensoft-badge]][chickensoft-website]\n[![Discord][discord-badge]][discord]\n[![Read the docs][read-the-docs-badge]][docs]\n![line coverage][line-coverage]\n![branch coverage][branch-coverage]\n\nOpinionated logging interface and implementations for C# applications\nand libraries.\n\n---\n\n\u003cp align=\"center\"\u003e\n\u003cimg alt=\"Chickensoft.Log\" src=\"Chickensoft.Log/icon.png\" width=\"200\"\u003e\n\u003c/p\u003e\n\n## 📦 Installation\n\n\u003e [!TIP]\n\u003e For logging in Godot, see [Chickensoft.Log.Godot][log-godot].\n\nInstall the latest version of the [Chickensoft.Log] package from nuget:\n\n```sh\ndotnet add package Chickensoft.Log\n```\n\n## 🌱 Usage\n\n### Essentials\n\nIn Chickensoft.Log, messages are logged through the `ILog` interface. Each `ILog`\nhas a name (often the name of the class using the `ILog`), an `ILogFormatter` for\nformatting messages, and a collection of `ILogWriter`s, each responsible for\ndirecting log messages to one output.\n\n### Setting up a Log\n\nThe package includes a standard implementation of `ILog`, named `Log`. To create\na log, instantiate a `Log` and give it a name and at least one writer:\n\n```csharp\npublic class MyClass\n{\n  // Create a log with the name of MyClass, outputting to stdout/stderr\n  private ILog _log = new Log(nameof(MyClass), new ConsoleWriter());\n}\n```\n\nYou can give the log multiple writers to obtain multiple outputs:\n\n```csharp\npublic class MyClass\n{\n  // Create a log with the name of MyClass, outputting to stdout/stderr and\n  // .NET's Trace system\n  private ILog _log = new Log(nameof(MyClass), new ConsoleWriter(),\n    new TraceWriter());\n}\n```\n\n### Logging\n\nTo log messages, use `ILog`'s methods `Print()`, `Warn()`, and `Err()`.\n\nExample:\n\n```csharp\npublic class MyClass\n{\n  public void MyMethod()\n  {\n    // Outputs \"Info (MyClass): A log message\"\n    _log.Print(\"A log message\");\n    // Outputs \"Warn (MyClass): A warning message\"\n    _log.Warn(\"A warning message\");\n    // Outputs \"Error (MyClass): An error occurred\"\n    _log.Err(\"An error occurred\");\n\n    try\n    {\n      SomethingThatThrows();\n    }\n    catch (Exception e)\n    {\n      // Outputs the value of e.ToString(), prefixed by a line labeling it an exception,\n      // as an error\n      _log.Print(e);\n    }\n\n    // Outputs the current stack trace as a standard log message\n    _log.Print(new System.Diagnostics.StackTrace());\n  }\n}\n```\n\n\u003e [!TIP]\n\u003e Some writers may have separate channels for warnings and errors, while others\n\u003e may not. For instance, the `TraceWriter` has separate channels for regular log\n\u003e messages, warnings, and errors. The `FileWriter` has only one channel, the\n\u003e file it's writing to. Warnings and errors can still be distinguished by the\n\u003e label the formatter gives them, even if directed to the same channel as regular\n\u003e log messages.\n\n### Formatting\n\nOptionally, when constructing a log, you can provide an `ILogFormatter` that the\nlog will use to format each message. (The formatted message should include\nthe log's name, the level of the message, and the message itself.)\n\n```csharp\npublic class MyClass\n{\n  private ILog _log = new Log(nameof(MyClass), new ConsoleWriter())\n  {\n    Formatter = new MyFormatter()\n  };\n}\n```\n\nBy default, `Log` will use the included `LogFormatter` class implementing\n`ILogFormatter`.\n\nMessages are formatted with one of three level labels, depending which log method\nyou call. By default, the included `LogFormatter` uses the labels `\"Info\"`,\n`\"Warn\"`, and `\"Error\"`. You can change these labels for an individual\n`LogFormatter`:\n\n```csharp\nvar formatter = new LogFormatter()\n{\n  MessagePrefix = \"INFO\";\n  WarningPrefix = \"WARN\";\n  ErrorPrefix = \"ERROR\";\n};\n```\n\nYou can also change the default values of these labels for all `LogFormatter`s:\n\n```csharp\nLogFormatter.DefaultMessagePrefix = \"INFO\";\nLogFormatter.DefaultWarningPrefix = \"WARN\";\nLogFormatter.DefaultErrorPrefix = \"ERROR\";\n```\n\n\u003e [!WARNING]\n\u003e Changing the default values of the level labels will affect newly-created\n\u003e `LogFormatter`s, but will not affect ones that already exist.\n\n## ✒️ Writer Types\n\n`Log` accepts a parameter array of writers, which receive formatted messages\nfrom the log and are responsible for handling the output of the messages. The\nLog package provides three writer types for use in applications or libraries:\n\n* `ConsoleWriter`: Outputs log messages to stdout and stderr.\n* `TraceWriter`: Outputs log messages to .NET's `Trace` system. This is useful\nfor seeing log output in Visual Studio's \"Output\" tab while debugging.\n* `FileWriter`: Outputs log messages to file. By default, `FileWriter` will\nwrite to a file called \"output.log\" in the working directory, but you can either\nconfigure a different default, or configure individual `FileWriter`s to write to\nparticular files on creation. To avoid concurrency issues, `FileWriter` is\nimplemented as a pseudo-singleton with a single instance per file name; see\nbelow for details.\n\nThe package provides one additional writer type, `TestWriter`, which may be\nuseful for testing your code without mocking `ILog` (see below).\n\n### Using `TraceWriter`\n\nTo see `TraceWriter`'s output from a Godot application in Visual Studio's\nOutput pane, add a `DefaultTraceListener` to the system's list of `Trace`\nlisteners somewhere near your entry point:\n\n```csharp\nusing System.Diagnostics;\n\npublic class MyGodotApp : Node\n{\n  public override void _Ready()\n  {\n    Trace.Listeners.Add(new DefaultTraceListener());\n  }\n}\n```\n\nThis step is necessary with [GoDotTest] test suites as well as games (or any\nother Godot-based applications).\n\n\u003e [!TIP]\n\u003e This step is unnecessary if you are running or debugging in Visual Studio\n\u003e Code, so you may want to guard adding `DefaultTraceListener` with a\n\u003e command-line flag.\n\n### Using `FileWriter`\n\n`FileWriter` provides two static `Instance()` methods for obtaining references\nto writers.\n\nYou can obtain a reference to a writer using the default file name `\"output.log\"`:\n\n```csharp\npublic class MyClass\n{\n  private ILog _log = new Log(nameof(MyClass), FileWriter.Instance());\n}\n```\n\n---\nYou can obtain a writer that outputs messages to a custom file name:\n\n```csharp\npublic class MyClass\n{\n  private ILog _log = new Log(nameof(MyClass),\n    FileWriter.Instance(\"CustomFileName.log\"));\n}\n```\n\n---\nAnd you can change the default file name for `FileWriter`s:\n\n```csharp\npublic class Entry\n{\n  public static void Main()\n  {\n    // Change the default file name for FileWriter before any writers are created\n    FileWriter.DefaultFileName = \"MyFileName.log\";\n    // ...\n  }\n}\n\npublic class MyClass\n{\n  // Create a FileWriter that writes to the new default name\n  private ILog _log = new Log(nameof(MyClass), FileWriter.Instance());\n}\n```\n\n\u003e [!WARNING]\n\u003e Changing the default value for the log file name will affect newly-created\n\u003e `FileWriter`s, but will not affect ones that already exist.\n\n### Using `TestWriter`\n\nWhen testing code that uses an `ILog`, it may be cumbersome to mock `ILog`'s\nmethods. In that case, you may prefer to use the provided `TestWriter` type,\nwhich accumulates log messages for testing:\n\n```csharp\n// Class under test\npublic class MyClass\n{\n  public ILog Log { get; set; } = new Log(nameof(MyClass), new ConsoleWriter());\n\n  // Method that logs some information; we want to test the logged messages\n  public void MyMethod()\n  {\n    Log.Print(\"A normal log message\");\n    Log.Err(\"An error message\");\n  }\n}\n\npublic class MyClassTest\n{\n  [Fact]\n  public void MyMethodLogs()\n  {\n    // set up an instance of MyClass, but with a TestWriter instead of a ConsoleWriter\n    var testWriter = new TestWriter();\n    var obj = new MyClass() { Log = new Log(nameof(MyClass), testWriter) };\n    obj.MyMethod();\n    // use TestWriter to test the logging behavior of MyClass\n    testWriter.LoggedMessages\n      .ShouldBeEquivalentTo(new List\u003cstring\u003e\n        {\n          \"Info (MyClass): A normal log message\",\n          \"Error (MyClass): An error message\"\n        });\n  }\n}\n```\n\n\u003e [!WARNING]\n\u003e `TestWriter` is not thread-safe.\n\n## 💁 Getting Help\n\n*Having issues?* We'll be happy to help you in the [Chickensoft Discord server][discord].\n\n---\n\n🐣 Package generated from a 🐤 Chickensoft Template — \u003chttps://chickensoft.games\u003e\n\n[chickensoft-badge]: https://chickensoft.games/img/badges/chickensoft_badge.svg\n[chickensoft-website]: https://chickensoft.games\n[discord-badge]: https://chickensoft.games/img/badges/discord_badge.svg\n[discord]: https://discord.gg/gSjaPgMmYW\n[read-the-docs-badge]: https://chickensoft.games/img/badges/read_the_docs_badge.svg\n[docs]: https://chickensoft.games/docsickensoft%20Discord-%237289DA.svg?style=flat\u0026logo=discord\u0026logoColor=white\n[line-coverage]: Chickensoft.Log.Tests/badges/line_coverage.svg\n[branch-coverage]: Chickensoft.Log.Tests/badges/branch_coverage.svg\n\n[Chickensoft.Log]: https://www.nuget.org/packages/Chickensoft.Log\n[log-godot]: https://github.com/chickensoft-games/Log.Godot\n[GoDotTest]: https://github.com/chickensoft-games/GoDotTest\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchickensoft-games%2Flog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchickensoft-games%2Flog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchickensoft-games%2Flog/lists"}