A minimal .NET 6 console application demonstrating dual Datadog log sinks configuration with Serilog, sending logs simultaneously to two different Datadog regions (US and EU).
- ✅ Dual Datadog sinks configured at the same level
- ✅ US region sink (
https://http-intake.logs.datadoghq.com) - ✅ EU region sink (
https://http-intake.logs.datadoghq.eu) - ✅ Different log levels per sink (Information vs Warning)
- ✅ Custom tags per region
- ✅ Console output for verification
- ✅ Configuration-based setup via
appsettings.json - ✅ Built-in diagnostic logging with
SelfLog - ✅ File-based sink simulation for testing without API keys
- ✅ Real-time sink status verification
- .NET 6 SDK or higher
- Valid Datadog API keys for US and/or EU regions
- Network access to Datadog (port 443 for HTTPS)
cd SerilogDatadogDualSinks-net6Edit appsettings.json and replace the placeholder API keys:
REPLACE_WITH_API_KEY_US→ Your Datadog US API keyREPLACE_WITH_API_KEY_EU→ Your Datadog EU API key
Note: Each Datadog site requires its own API key. Get your keys from:
dotnet restore
dotnet runThe application uses five sinks configured simultaneously:
| Sink | Type | Region/Purpose | URL/Path | Min Level | Tags |
|---|---|---|---|---|---|
| Console | Console | Display | - | All | - |
| File US | File | Simulate US | logs/simulated-datadog-us-*.log |
Information |
- |
| File EU | File | Simulate EU | logs/simulated-datadog-eu-*.log |
Warning |
- |
| Datadog US | Datadog | United States | https://http-intake.logs.datadoghq.com |
Information |
env:dev, region:us |
| Datadog EU | Datadog | Europe | https://http-intake.logs.datadoghq.eu |
Warning |
env:dev, region:eu |
- US Sink: Captures logs from
Informationlevel and above - EU Sink: Captures logs from
Warninglevel and above (more restrictive)
The file sinks allow you to test the behavior without valid Datadog API keys:
simulated-datadog-us-*.log- Shows what would be sent to US regionsimulated-datadog-eu-*.log- Shows what would be sent to EU region
=================================================
SERILOG CONFIGURATION LOADED
=================================================
✓ Sink #1: Console
✓ Sink #2: File
✓ Sink #3: File
✓ Sink #4: DatadogLogs
- Service: sample-app
- URL: https://http-intake.logs.datadoghq.com
- Min Level: Information
- API Key: ⚠️ NOT CONFIGURED
- Tags: env:dev, region:us
✓ Sink #5: DatadogLogs
- Service: sample-app
- URL: https://http-intake.logs.datadoghq.eu
- Min Level: Warning
- API Key: ⚠️ NOT CONFIGURED
- Tags: env:dev, region:eu
=================================================
Total sinks loaded: 5
=================================================
💡 Tip: If API keys are valid, logs will appear in Datadog within ~30 seconds
🔍 Watch for RED messages below - they indicate sink errors
[17:32:42 INF] Application started
[17:32:42 WRN] This warning should go to both Datadog sinks
[17:32:42 INF] Processing item 0
[17:32:42 INF] Processing item 1
[17:32:42 INF] Processing item 2
[17:32:42 ERR] An error occurred while processing
[17:32:42 INF] Application finished successfully
⏳ Flushing logs to all sinks (this may take a few seconds)...
✅ All logs flushed successfully
📄 Check 'serilog-diagnostics.log' for any internal errors
When API keys are invalid or not configured, you'll see diagnostic messages in RED:
[SERILOG INTERNAL] Could not send payload to Datadog: [Forbidden] Forbidden
This is EXPECTED and confirms that:
- ✅ Sinks are loaded and working
- ✅ Logs are properly formatted
- ✅ HTTP requests are being made to Datadog
- ❌ Authentication failed (need valid API keys)
After running, check these files to verify behavior:
logs/simulated-datadog-us-YYYYMMDD.log- US region simulation (Information+)logs/simulated-datadog-eu-YYYYMMDD.log- EU region simulation (Warning+)serilog-diagnostics.log- Serilog internal errors (if any)
SerilogDatadogDualSinks-net6/
├── Program.cs # Main application
├── appsettings.json # Serilog & Datadog configuration
├── SerilogDatadogDualSinks-net6.csproj # Project file
└── README.md # This file
- Serilog (2.10.0) - Core logging library
- Serilog.Settings.Configuration (3.3.0) - Configuration-based setup
- Serilog.Sinks.Console (4.0.1) - Console output
- Serilog.Sinks.File (5.0.0) - File output for simulation
- Serilog.Sinks.Datadog.Logs (0.5.2) - Datadog integration
- Serilog.Expressions (3.4.1) - Advanced filtering
- Microsoft.Extensions.Configuration.Json (6.0.0) - JSON configuration
- Microsoft.Extensions.Configuration.EnvironmentVariables (6.0.1) - Environment variables
To use TCP protocol instead of HTTPS, modify appsettings.json:
"configuration": {
"url": "intake.logs.datadoghq.com",
"port": 10516,
"useSSL": true,
"useTCP": true
}Adjust the following fields in appsettings.json:
"service": "your-app-name",
"tags": ["env:production", "region:us", "version:1.0.0"]Control buffering behavior:
"queueLimit": 100000,
"batchSizeLimit": 1000The application includes simulation sinks that write to files. This allows you to verify the behavior without Datadog credentials:
dotnet runThen check:
# View US sink simulation (Information+)
cat logs/simulated-datadog-us-*.log
# View EU sink simulation (Warning+ only)
cat logs/simulated-datadog-eu-*.log
# Check for internal errors
cat serilog-diagnostics.logLook for these indicators:
✅ Working correctly:
- Console shows
✅ Configuredfor API keys (if set) or⚠️ NOT CONFIGURED - No RED messages during execution
serilog-diagnostics.logis empty or doesn't exist- Simulation files contain expected logs
❌ Issues detected:
- RED
[SERILOG INTERNAL]messages in console serilog-diagnostics.logcontains errors- Simulation files are missing or empty
| Message | Meaning | Action |
|---|---|---|
[Forbidden] Forbidden |
Invalid API key | Replace placeholder with real API key |
An invalid request URI was provided |
Incorrect URL format | Ensure URL starts with https:// |
Could not send payload to Datadog |
Network/auth issue | Check API key and network connectivity |
| No RED messages | Everything working | Logs are being sent successfully |
- ✅ Verify API keys are correct and not placeholders
- ✅ Check
serilog-diagnostics.logfor errors - ✅ Verify simulation files show expected logs
- ✅ Check network connectivity to Datadog endpoints
- ✅ Ensure log level meets the sink's
restrictedToMinimumLevel - ✅ Wait ~30 seconds for ingestion (Datadog has slight delays)
If simulation files in logs/ are empty:
- Check file permissions in the project directory
- Verify
Serilog.Sinks.Filepackage is installed - Look for errors in
serilog-diagnostics.log
This is expected when:
- Using placeholder API keys (
REPLACE_WITH_API_KEY_*) - Testing without real credentials
This is NOT expected when:
- Using valid API keys
- URLs are correctly formatted
If you see .NET version compatibility warnings, consider upgrading to .NET 8 or suppress warnings by adding to .csproj:
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>This is a sample project for demonstration purposes.
The application uses Serilog.Debugging.SelfLog to capture internal errors:
SelfLog.Enable(msg =>
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"[SERILOG INTERNAL] {msg}");
Console.ResetColor();
});This shows in real-time if sinks encounter issues like:
- Network failures
- Authentication errors
- Configuration problems
- Serialization issues
The app displays configuration details on startup:
- Sink type (Console, File, DatadogLogs)
- Service name and URL
- Minimum log level
- API key status (configured or not)
- Tags
This confirms sinks are loaded before any logging occurs.