Agentless logging from .NET to Datadog
You don't need to install the Datadog Agent to get your .NET logs into Datadog. Two agentless options send them straight over HTTPS, structured and ready to search.
Datadog's standard setup for logs is to write them to a file and have the Datadog Agent tail that file and forward it. That works well on a server or VM you control. On Azure App Service, Azure Functions or a small container, installing and running an Agent alongside your app is extra moving parts.
Agentless logging skips the Agent: your application sends its logs directly to Datadog's HTTPS intake. There are two ways to do it in .NET.
Option 1: the Serilog sink
If you use Serilog, or are happy to, this is the simplest route. Add the Serilog.AspNetCore and Serilog.Sinks.Datadog.Logs packages:
builder.Services.AddSerilog((services, logger) => logger
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.WriteTo.DatadogLogs(
apiKey: builder.Configuration["Datadog:ApiKey"],
source: "csharp",
service: "orders-api",
host: Environment.MachineName,
tags: [$"env:{builder.Environment.EnvironmentName.ToLowerInvariant()}", "version:1.4.0"],
configuration: new DatadogConfiguration
{
Url = "https://http-intake.logs.datadoghq.com"
}));
Your code keeps using ILogger<T> as usual. Serilog sits behind it and batches log events to Datadog over HTTPS on port 443.
Set the URL for your Datadog site. Accounts live in different regions, and each has its own intake address. http-intake.logs.datadoghq.com is for US1; EU accounts use http-intake.logs.datadoghq.eu, and other regions have their own. Check the site in your Datadog URL and the logs documentation if you're unsure. Sending to the wrong site fails quietly.
Option 2: the Datadog .NET tracer
If you already use Datadog APM, or want it, the .NET tracer can send logs directly too, from plain Microsoft.Extensions.Logging with no Serilog required. Add the Datadog.Trace.Bundle NuGet package, enable automatic instrumentation with the CORECLR_* environment variables from Datadog's setup guide for your OS, and set:
DD_API_KEY=<your API key>
DD_SITE=datadoghq.com
DD_LOGS_DIRECT_SUBMISSION_INTEGRATIONS=ILogger
DD_ENV=production
DD_SERVICE=orders-api
DD_VERSION=1.4.0
DD_LOGS_DIRECT_SUBMISSION_INTEGRATIONS also accepts Serilog, NLog and Log4Net, separated by semicolons. By default it sends Information and above; change that with DD_LOGS_DIRECT_SUBMISSION_MINIMUM_LEVEL, or filter by category under a Datadog key in the Logging section of appsettings.json.
The big advantage is log and trace correlation: the tracer adds trace and span IDs to every log entry, so in Datadog you can jump from a slow request's trace straight to the logs it wrote. Note that this option relies on the tracer's automatic instrumentation, which is more setup than a single NuGet package, and traces themselves are sent separately from logs.
Make the logs worth searching
Agentless or not, a few habits decide whether the logs are useful:
- Use message templates, not string interpolation.
logger.LogInformation("Order {OrderId} shipped", id)sendsOrderIdas its own attribute. In Datadog, create a facet on it and you can filter and group by order. - Use unified service tagging. Consistent
env,serviceandversionvalues on logs, traces and metrics let Datadog connect them, and let you compare error rates before and after a deployment. - Watch volume. Datadog bills by logs ingested and indexed. Send
Informationand above from production, keepDebugfor development, and use exclusion filters in Datadog for noisy entries you don't need to keep.
Things to know before you rely on it
- Protect the API key. It allows anyone to send data into your account. Keep it in Key Vault or a secret app setting, never in
appsettings.jsonin the repository. - Logs are sent from your process. They're batched in memory and sent in the background. If Datadog is unreachable for long enough, the queue fills and new entries are dropped, and anything still queued when the process is killed is lost. Flush on shutdown (
Log.CloseAndFlush()if you use Serilog's static logger), and keep critical audit records somewhere durable as well. - There's no local copy. With the Agent approach, a log file stays on disk if the network fails. Agentless trades that resilience for simplicity.
Takeaway
For App Service, Functions and small containers, agentless logging is the quickest way to get .NET logs into Datadog. Use the Serilog sink for the simplest setup, or the .NET tracer's direct submission if you want APM and log-trace correlation. Either way, point it at the right Datadog site, keep the API key secret, and log with message templates so every value is searchable.