| Key | Default | Value |
| ----------------------- | ------- | -------------------------------------------- |
| **GameRecorderEnabled** | `false` | Enables the Game Recorder. |
-| **GameRecorderPath** | *empty* | Path where the recorded games will be saved. |
+| **GameRecorderPath** | _empty_ | Path where the recorded games will be saved. |
### ServerRedirector
| **>UdpMasterEndpoint** | | On the master, this value acts as a listen ip and port. On a node, this should be the public ip and port of the master. Format `127.0.0.1:32320`. |
| **Nodes** | | An array containing public ips and ports of nodes. Only needs to be set on the master. See above for an example. |
+### Serilog (Logging)
+
+Impostor's log framework, Serilog, can be configured in the config file. You can change its default log level and you can add additional sinks.
+
+| Key | Default | Value |
+| ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| **MinimumLevel** | `Information` | Minimum log level for a message to be printed. If a log entry is as severe or more severe than this level, it will be printed. From most severe to least severe: `Fatal`,`Error`, `Warning`, `Information`, `Debug`, `Verbose` |
+| **Using** | `[]` | List of additional Serilog Sinks assemblies to load. |
+| **WriteTo** | `[]` | Additional logging sinks. See the Serilog documentation or the example in this section. Serilog |
+
+For more information, check the [Serilog.Settings.Configuration](https://github.com/serilog/serilog-settings-configuration) documentation.
+
+For example, to add logging to a file, you should add the following snippet to your configuration:
+
+```json
+"Serilog": {
+ "Using": [
+ "Serilog.Sinks.File"
+ ],
+ "WriteTo": [
+ {
+ "Name": "File",
+ "Args": {
+ "path": "logs/log.txt",
+ "rollingInterval": "Day"
+ }
+ }
+ ]
+}
+```
+
+Next to that, you also need to copy over Serilog.Sinks.File.dll from [NuGet](https://www.nuget.org/packages/Serilog.Sinks.File/). See the [Serilog.Sinks.File documentation](https://github.com/serilog/serilog-sinks-file#json-appsettingsjson-configuration) for a list of parameters that can be configured.
+
+Other Serilog sinks are also supported, but are out of scope for this documentation.
+
## Config providers
### File
using System;
using System.IO;
using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
using Impostor.Api.Events.Managers;
using Impostor.Api.Games;
using Impostor.Api.Games.Managers;
using Microsoft.Extensions.ObjectPool;
using Serilog;
using Serilog.Events;
+using Serilog.Settings.Configuration;
namespace Impostor.Server
{
{
private static int Main(string[] args)
{
-#if DEBUG
- var logLevel = LogEventLevel.Debug;
-#else
- var logLevel = LogEventLevel.Information;
-#endif
-
- if (args.Contains("--verbose"))
- {
- logLevel = LogEventLevel.Verbose;
- }
- else if (args.Contains("--errors-only"))
- {
- logLevel = LogEventLevel.Error;
- }
-
Log.Logger = new LoggerConfiguration()
- .MinimumLevel.Is(logLevel)
-#if DEBUG
- .MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
-#else
- .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
-#endif
- .Enrich.FromLogContext()
.WriteTo.Console()
- .CreateLogger();
+ .CreateBootstrapLogger();
try
{
services.AddSingleton<Matchmaker>();
services.AddHostedService<MatchmakerService>();
})
- .UseSerilog()
+ .UseSerilog((context, loggerConfiguration) =>
+ {
+#if DEBUG
+ var logLevel = LogEventLevel.Debug;
+#else
+ var logLevel = LogEventLevel.Information;
+#endif
+
+ if (args.Contains("--verbose"))
+ {
+ logLevel = LogEventLevel.Verbose;
+ }
+ else if (args.Contains("--errors-only"))
+ {
+ logLevel = LogEventLevel.Error;
+ }
+
+ static Assembly? LoadSerilogAssembly(AssemblyLoadContext loadContext, AssemblyName name)
+ {
+ var paths = new[] { AppDomain.CurrentDomain.BaseDirectory, Directory.GetCurrentDirectory() };
+ foreach (var path in paths)
+ {
+ try
+ {
+ return loadContext.LoadFromAssemblyPath(Path.Combine(path, name.Name + ".dll"));
+ }
+ catch (FileNotFoundException)
+ {
+ }
+ }
+
+ return null;
+ }
+
+ AssemblyLoadContext.Default.Resolving += LoadSerilogAssembly;
+
+ loggerConfiguration
+ .MinimumLevel.Is(logLevel)
+#if DEBUG
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
+#else
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
+#endif
+ .Enrich.FromLogContext()
+ .WriteTo.Console()
+ .ReadFrom.Configuration(context.Configuration, ConfigurationAssemblySource.AlwaysScanDllFiles);
+
+ AssemblyLoadContext.Default.Resolving -= LoadSerilogAssembly;
+ })
.UseConsoleLifetime()
.UsePluginLoader(pluginConfig);
}