Serilog: Configuration via appsettings.json

    Created: 2026-01-14
    Serilog

    This post is a continuation of the Serilog series (previous part: Serilog: Installation & Basics).

    In this part, we will:

    • Configure logging to files.
    • Move configuration into appsettings.json.
    • Explore log levels and enrichment for better context.

    Checkout to branch

    If you didn't clone SerilogDemo repo yet, do it now and checkout to branch 002-config-via-appsettings.

    You will see small changes (compared to the end of previous part):

    • WeatherForecastService.cs class was added to extract logic from the Program.cs file. We want to keep it as clean as possible (for now).
    • WeatherForecast class was moved to separate file.

    Let's get started!

    Configure simple file logging

    Install the following package:

    Let's use this package in our Program.cs. Replace current Serilog configuration with the following:

    This configuration will log to both the console and a file (in the Logs folder; the file will have the name single-file-log.log). Try it out yourself!

    Rolling file logging

    This might sound obvious, but logging to a single file is not a good approach for production applications. The file will grow indefinitely and will be hard to manage.

    Let's change our configuration to use rolling files. Update the Program.cs file:

    Now, Serilog will create a new log file each day. Logs will still be stored in the Logs folder, but files will have names like log-{Date}.log (e.g. log-20260109.log). It will reduce the size of individual files and make it easier to manage them. We are good to go now, right?

    File size limit

    For simple apps/services rolling files daily is usually enough. However, in monolithic applications with high traffic, a single day of logs can still produce very large files. To mitigate this, we can set a file size limit. Once the log file reaches this limit, Serilog will create a new file for subsequent logs. Update the Program.cs file again:

    Now, each log file will be limited to approximately 4 KB (~40 lines of logs). When the limit is reached, Serilog will no longer append to that file. It means that our logs will be lost!

    Let's fix it by enabling file rolling on size limit and making the limit more reasonable (10 MB):

    This config looks much better! Now, each log file will be limited to 10 MB, and when the limit is reached, Serilog will create a new file with an incremented suffix. If you tested out all these configs, your Logs folder should look somewhat like this:

    Let's fix one more thing - files will stack up indefinitely. We can limit how long we keep log files by adding the retainedFileTimeLimit parameter:

    NOTE

    We configured retainedFileTimeLimit so logs older than 31 days will be deleted. Alternatively, you can use retainedFileCountLimit to keep a fixed number of log files, but in our case, time-based retention makes more sense. If you omit the fileSizeLimitBytes and rollOnFileSizeLimit parts of the config, it would make more sense to use retainedFileCountLimit instead.

    Beware default Serilog file sink behavior

    If you change the File sink configuration back to the simpler version .WriteTo.File("Logs/log-.log", rollingInterval: RollingInterval.Day) and let it run for a long time, you will notice that after the log file reaches 1 GB in size, Serilog will stop writing further logs to that file.

    🚨 All this without any warning or error! 🚨

    To avoid bringing down apps with runaway disk usage the file sink limits file size to 1GB by default

    This is just safety mechanism described in Serilog.Sinks.File documentation. I highly recommend visiting that page to learn more about advanced File sink configuration options.

    Configuration stored in appsettings.json

    Now we will configure Serilog to read its settings from the appsettings.json file instead of hard-coding everything in Program.cs. Why is this useful?

    • Easier to change logging without recompiling or redeploying the application, especially when each environment (Development, Staging, Production) needs different sinks or log levels. Just override Serilog settings per environment using files like appsettings.Development.json or environment variables.
    • Centralized, discoverable configuration: to see what is enabled in a given environment, you just open the config file instead of hunting through the codebase.

    Let's see how to do it in practice!

    File configuration setup

    First, install the following package:

    Update Program.cs file to read configuration from appsettings.json. Replace the Serilog configuration with the following:

    Now, we need to add Serilog configuration to appsettings.json file. Open it and add the following section:

    That's it! Now, when you run the application, Serilog will read its configuration from appsettings.json file.

    I highly recommend visiting this GitHub repo to find out more!

    Log levels

    In life, all decisions matter. Some are critical—they can completely change your life (e.g., choosing a career path). Some are of mediocre importance—they may shorten your journey to a long-term goal. Others are merely incidental—they just happen to be.

    With logging, it's the same. Some logs are critical—they indicate serious issues that need immediate attention. Others have their reason to exist but are not that important. Finally, some logs are just noise—they clutter the log files without providing much value. It's about priorities.

    For a good logging experience in your team/application, it's crucial to understand log levels and use them properly.

    Serilog log levels (most to least severe)
    Expand each level to see practical guidance and a structured logging example.

    NOTE

    A fundamental understanding of log levels may seem trivial, and it's often overlooked. However, proper use of log levels can significantly enhance the effectiveness of logging in any application.

    Enrichment

    Enrichment is the process of adding additional context to your logs. This context can be anything that helps you understand the log better - user IDs, request IDs, machine names, etc.

    Serilog provides a powerful enrichment mechanism that allows you to add custom properties to your logs. You can use built-in enrichers or create your own.

    To use enrichers, you need to install the appropriate packages. For example, to add machine name and thread ID to your logs, you can install the following packages:

    Then, you can update your Serilog configuration to use these enrichers. If you are using appsettings.json, you can add the following section:

    If you run the application now, these properties will be attached to all log events. To see them in your output, you'll need to configure an output template that includes them (we'll do this next). For now, the enriched properties are stored internally and can be used by structured logging sinks.

    This adds machine name and thread ID to all your logs. You can then use these properties in your log output templates or filters. Read this wiki page to learn more about enrichers and how to create your own.

    If you want a deeper, real-world walkthrough using SerilogDemo and Grafana, check out Serilog: Enrichers for Better Context.

    But wait, what are log output templates in the first place? Good question! Output templates allow you to customize the format of your log messages. You can include properties, timestamps, log levels, and more in a structured way.

    Let's configure one! 🔥

    Custom output template

    Go to appsettings.json file and update WriteTo section for File sink to look like this:

    Run the app and test it out. Now, your log files should look like this:

    NOTE

    Console logs didn't change a bit! You have full flexibility to configure each sink independently. You can even create multiple instances of the same sink with different configurations (if you find a reasonable use case for that).

    Check out this wiki page for more!

    Summary

    In this part, we explored advanced Serilog configuration options, including file logging with rolling files, configuration via appsettings.json, log levels, and enrichment. Proper logging is crucial for monitoring and debugging applications, and Serilog provides a robust set of features to achieve this.

    If you find some part of this guide unclear, have questions or feedback, drop a comment below 🙂

    What's next

    In the next part of this series, we will explore structured logging.

    Stay tuned! 🚀

    Recommended for you