Prerequisites
Option 1: Using HTTP Client
Create a new .NET project
Create a new .NET project. In your terminal, go to the directory where you want to create your project. Run the following command to create a new console app named AxiomLogs
.
dotnet new console -n AxiomLogs
Install packages
Install the packages for your project. Use the Microsoft.AspNet.WebApi.Client
package to make HTTP requests to the Axiom API. Run the following command to install the package:
dotnet add package Microsoft.AspNet.WebApi.Client
Create a class to handle logging to Axiom. Create a new file named AxiomLogger.cs
in your project directory with the following content:
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
public static class AxiomLogger
{
public static async Task LogToAxiom(string message, string logLevel)
{
var client = new HttpClient();
var datasetName = "YOUR-DATASET-NAME";
var axiomUri = $"https://api.axiom.co/v1/datasets/{datasetName}/ingest";
var apiToken = "YOUR-API-TOKEN";
var logEntries = new[]
{
new
{
timestamp = DateTime.UtcNow.ToString("o"),
message = message,
level = logLevel
}
};
var content = new StringContent(System.Text.Json.JsonSerializer.Serialize(logEntries), Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", apiToken);
var response = await client.PostAsync(axiomUri, content);
if (!response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Failed to send log: {response.StatusCode}\n{responseBody}");
}
else
{
Console.WriteLine("Log sent successfully.");
}
}
}
Configure the main program
Now that the Axiom logger is in place, update the main program so it can be used. Open the Program.cs
file and replace its contents with the following code:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
await AxiomLogger.LogToAxiom("Application started", "INFO");
await SimulateOperations();
await AxiomLogger.LogToAxiom($"CLR version: {Environment.Version}", "INFO");
await AxiomLogger.LogToAxiom("Application shutting down", "INFO");
}
static async Task SimulateOperations()
{
await AxiomLogger.LogToAxiom("Starting operations", "DEBUG");
await AxiomLogger.LogToAxiom("Connecting to database", "DEBUG");
await Task.Delay(500);
await AxiomLogger.LogToAxiom("Connected to database successfully", "INFO");
await AxiomLogger.LogToAxiom("Retrieving user data", "DEBUG");
await Task.Delay(1000);
await AxiomLogger.LogToAxiom("Retrieved 100 user records", "INFO");
await AxiomLogger.LogToAxiom("Updating user preferences", "DEBUG");
await Task.Delay(800);
await AxiomLogger.LogToAxiom("Updated user preferences successfully", "INFO");
try
{
await AxiomLogger.LogToAxiom("Processing payments", "DEBUG");
await Task.Delay(1500);
throw new Exception("Payment gateway unavailable");
}
catch (Exception ex)
{
await AxiomLogger.LogToAxiom($"Payment processing failed: {ex.Message}", "ERROR");
}
await AxiomLogger.LogToAxiom("Sending email notifications", "DEBUG");
await Task.Delay(1200);
await AxiomLogger.LogToAxiom("Sent 50 email notifications", "INFO");
await AxiomLogger.LogToAxiom("Detected high memory usage", "WARN");
await Task.Delay(500);
await AxiomLogger.LogToAxiom("Memory usage normalized", "INFO");
await AxiomLogger.LogToAxiom("Operations completed", "DEBUG");
}
}
This code simulates various app operations and logs messages at different levels (DEBUG, INFO, WARN, ERROR) to Axiom.
Project file configuration
Ensure your axiomlogs.csproj
file is configured with the package reference. The file should look like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
</ItemGroup>
</Project>
Build and run the app
To build and run the app, go to the project directory in your terminal and run the following command:
This command builds the project and runs the app. You see the log messages being sent to Axiom, and the console displays Log sent successfully.
for each log entry.
Option 2: Using Serilog
Install Serilog Packages
Add Serilog and the necessary extensions to your project. You need the Serilog
, Serilog.Sinks.Http
, and Serilog.Formatting.Json
packages.
dotnet add package Serilog
dotnet add package Serilog.Sinks.Http
dotnet add package Serilog.Formatting.Json
In your Program.cs
or a startup configuration file, set up Serilog to use the HTTP sink. Configure the sink to point to the Axiom ingestion API endpoint.
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Http(
requestUri: "https://api.axiom.co/v1/datasets/YOUR-DATASET-NAME/ingest",
textFormatter: new Serilog.Formatting.Json.JsonFormatter(),
httpClient: new HttpClient
{
DefaultRequestHeaders =
{
{ "Authorization", "Bearer YOUR-API-TOKEN" }
}
})
.CreateLogger();
class Program
{
static async Task Main(string[] args)
{
Log.Information("Application started");
await SimulateOperations();
Log.Information($"CLR version: {Environment.Version}");
Log.Information("Application shutting down");
}
static async Task SimulateOperations()
{
Log.Debug("Starting operations");
Log.Debug("Connecting to database");
await Task.Delay(500);
Log.Information("Connected to database successfully");
Log.Debug("Retrieving user data");
await Task.Delay(1000);
Log.Information("Retrieved 100 user records");
Log.Debug("Updating user preferences");
await Task.Delay(800);
Log.Information("Updated user preferences successfully");
try
{
Log.Debug("Processing payments");
await Task.Delay(1500);
throw new Exception("Payment gateway unavailable");
}
catch (Exception ex)
{
Log.Error($"Payment processing failed: {ex.Message}");
}
Log.Debug("Sending email notifications");
await Task.Delay(1200);
Log.Information("Sent 50 email notifications");
Log.Warning("Detected high memory usage");
await Task.Delay(500);
Log.Information("Memory usage normalized");
Log.Debug("Operations completed");
}
}
Project file configuration
Ensure your axiomlogs.csproj
file is configured with the package references. The file should look like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Http" Version="5.0.0" />
<PackageReference Include="Serilog.Formatting.Json" Version="3.1.0" />
</ItemGroup>
</Project>
Build and run the app
To build and run the app, go to the project directory in your terminal and run the following commands:
This command builds the project and runs the app. You see the log messages being sent to Axiom.
Option 3: Using NLog
Install NLog Packages
You need NLog and potentially an extension for HTTP targets.
dotnet add package NLog
dotnet add package NLog.Web.AspNetCore
Set up NLog by creating an NLog.config
file or configuring it programmatically. Here is an example configuration for NLog
using an HTTP target:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="BufferingWrapper"
name="allLogs"
flushTimeout="5000">
<target xsi:type="WebClient"
name="http"
url="https://api.axiom.co/v1/datasets/YOUR-DATASET-NAME/ingest"
method="POST"
header="Authorization: Bearer YOUR-API-TOKEN"
layout="${longdate}|${level:uppercase=true}|${message} ${exception:format=toString,Data}">
</target>
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="allLogs" />
</rules>
</nlog>
Configure the main program
Update the main program to use NLog
. In your Program.cs
file:
using NLog;
using NLog.Web;
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
class Program
{
static async Task Main(string[] args)
{
logger.Info("Application started");
await SimulateOperations();
logger.Info($"CLR version: {Environment.Version}");
logger.Info("Application shutting down");
}
static async Task SimulateOperations()
{
logger.Debug("Starting operations");
logger.Debug("Connecting to database");
await Task.Delay(500);
logger.Info("Connected to database successfully");
logger.Debug("Retrieving user data");
await Task.Delay(1000);
logger.Info("Retrieved 100 user records");
logger.Debug("Updating user preferences");
await Task.Delay(800);
logger.Info("Updated user preferences successfully");
try
{
logger.Debug("Processing payments");
await Task.Delay(1500);
throw new Exception("Payment gateway unavailable");
}
catch (Exception ex)
{
logger.Error($"Payment processing failed: {ex.Message}");
}
logger.Debug("Sending email notifications");
await Task.Delay(1200);
logger.Info("Sent 50 email notifications");
logger.Warn("Detected high memory usage");
await Task.Delay(500);
logger.Info("Memory usage normalized");
logger.Debug("Operations completed");
}
}
Project file configuration
Ensure your axiomlogs.csproj
file is configured with the package references. The file should look like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="4.7.12" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
</ItemGroup>
</Project>
Build and run the app
To build and run the app, go to the project directory in your terminal and run the following commands:
This command builds the project and runs the app. You should see the log messages being sent to Axiom.
Best practices for logging
To make your logging more effective, consider the following best practices:
- Include relevant information such as user IDs, request details, and system state in your log messages to provide context when investigating issues.
- Use different log levels (DEBUG, INFO, WARN, ERROR) to categorize the severity and importance of log messages. This allows you to filter and analyze logs more effectively
- Use structured logging formats like JSON to make it easier to parse and analyze log data
Conclusion
This guide covers the steps to send logs from a C# .NET app to Axiom. By following these instructions and adhering to logging best practices, you can effectively monitor your app, diagnose issues, and gain valuable insights into its behavior.