Anixe.IO.Appmetrics
2.1.0
See the version list below for details.
dotnet add package Anixe.IO.Appmetrics --version 2.1.0
NuGet\Install-Package Anixe.IO.Appmetrics -Version 2.1.0
<PackageReference Include="Anixe.IO.Appmetrics" Version="2.1.0" />
paket add Anixe.IO.Appmetrics --version 2.1.0
#r "nuget: Anixe.IO.Appmetrics, 2.1.0"
// Install Anixe.IO.Appmetrics as a Cake Addin #addin nuget:?package=Anixe.IO.Appmetrics&version=2.1.0 // Install Anixe.IO.Appmetrics as a Cake Tool #tool nuget:?package=Anixe.IO.Appmetrics&version=2.1.0
Appmetrics
Anixe.IO.Appmetrics allows you to quickly integrate your asp .net core application with graylog. The module produces json object in GELF format with fields describing inbound communication (incoming HTTP request into the application) and outbound communication (any IO operation made by the application)
How to integrate
add in csproj as a package reference
<PackageReference Include="Anixe.IO.Appmetrics" Version="2.0.11" />
add section to appsettings.json
{
...
"Appmetrics" : {
"LogSender" : {
"Channel": "NLog" // External, NLog, UdpClient
},
"Middleware": { // configuration for inbound http requests
"TenantFieldName": "prof", // url query parameter or routing data or http context's items
"RequestId" : {
"QueryFieldName": "rid", // url query parameter
"HeaderFieldName": "X-RequestId", // request header parameter
"AddToResponse": true // will add the value to the respone header
},
"MethodIdIdFieldName": "mid", // url query parameter
"IncludeMethods": [],
"ExcludeMethods": [ // omit theese requests with http method
"OPTIONS",
"HEAD"
],
"IncludeUrls": [],
"ExcludeUrls": [ // do not log for theese incoming requests urls to avoid measuring healthchecks
"/ping",
"$health$", //$..$ to match all urls which contains health
"/status$" // ...$ to match all urls which start with /status
]
},
"HttpClient": { // configuration for outbound http requests
"TimeoutCustomMessage": "Timeout ocurred", // override OperationCancelledException and TaskCancelledException with this message
"IncludeUrls": [],
"ExcludeUrls": [ // do not log for theese outbound urls to avoid measuring healthchecks
"/_cluster/health"
]
},
"Defaults" : { // each message will have theese defaults
"application_name": "geows-be",
"src": "geows-be", // can be something else eg. module from the monolith (plugin name, startup). Usefull in case of several different metrics outside the convention scope
"platform": "shared-svc",
"product": "geo"
}
}
}
register middleware for inbound HTTP reqests and handling exceptions in DI container in Startup.cs and additional http client handler for collecting metrics from outbound HTTP request, all you need it to define HttpClient
sub-section in Appmetrics
section in appsettings.json and use HttpClientFactory for http client registration; otherwise only middleware will be registered.
public void ConfigureServices(IServiceCollection services)
{
services.UseAnixeAppmetrics(this.config, opts => // use this to provide metrics for inbound http requests and unhandled exception
{
// override any option here
opts.Middleware.HostName = "my machine"; /* providing machine name is on your own */
opts.Middleware.ServerIp = "127.0.0.1"; /* providing machine name is on your own */
})
}
Register NLog target or built-in UDP sender
for NLog just set up appsettings.json
{
...
"Appmetrics" : {
"LogSender" : {
"Channel": "NLog"
},
...
}
}
then use build-in anixe-appmetrics
layout formatter and define an NLog rule with appmetrics
name
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
throwExceptions="true"
autoReload="false"
internalLogLevel="Warn"
internalLogFile="internal-nlog.txt">
<extensions>
<add assembly="Anixe.IO.Appmetrics"/>
</extensions>
<targets>
<target xsi:type="Console" name="appmetrics-console" layout="${anixe-appmetrics}" />
<target xsi:type="Network" address="udp://graylog.com:5558" name="appmetrics" layout="${anixe-appmetrics}" />
</targets>
<rules>
<logger name="appmetrics-console" minlevel="Debug" writeTo="appmetrics-console" final="true">
<filters defaultAction="Ignore">
<when condition="equals('${environment:ASPNETCORE_ENVIRONMENT}','Development')" action="Log"/>
</filters>
</logger>
<logger name="appmetrics" minlevel="Debug" writeTo="appmetrics" final="true">
<filters defaultAction="Ignore">
<when condition="not equals('${environment:ASPNETCORE_ENVIRONMENT}','Development')" action="Log"/>
</filters>
</logger>
</rules>
</nlog>
for build-in UdpSender just set up appsettings.json
{
...
"Appmetrics" : {
"LogSender" : {
"Channel": "UdpClient"
},
...
}
}
and expect IUdpClient
instance from DI container as a dependency. The IUdpClient
instance is a thread-safe singleton.
public class MyCustomLogger
{
private readonly IUdpClient client;
public MyCustomLogger(IUdpClient client)
{
this.client = client;
}
}
for your custom log sender just set up in appsettings.json
{
...
"Appmetrics" : {
"LogSender" : {
"Channel": "External"
},
...
}
}
and register your own IUdpClient
implementation in DI container.
And thats all, it registers default convention made from Appmetrics middleware, filter and http client delegating handler. You don't need to add any additional code.
How to get access to log message within asp .net core processing pipeline
Expect IMessage
in HttpContext.Items[nameof(IMessage)]
. This example describes a controller which uses HttpContext.Items[nameof(IMessage)]
public class LocationsController : ControllerBase
{
private readonly ILocationsService locations;
public LocationsController(ILocationsService locations)
{
this.locations = locations;
}
[Route("locations")]
[HttpGet]
public async Task<IActionResult> GetAllAsync([FromQuery]LocationsRequestModel request)
{
var mgs = this.HttpContext.Items[nameof(IMessage)] as IMessage;
var retval = await locations.FindAllAsync(request, this.HttpContext.RequestAborted);
msg.AddPair("no", retval.locations?.Count ?? 0);
Response.Headers.Add("X-Total", retval.total.GetValueOrDefault().ToString());
Response.Headers.Add("X-Total-Unfiltered", retval.total_unfiltered.GetValueOrDefault().ToString());
return Ok(retval);
}
}
How to manually prepare log message then send it outside asp .net core processing pipeline.
Expect IMetricsCollector
instance which has several logging method. Each method will send log to the graylog after method call ends. This example describes a hosted service.
public class TaskQueueHostedService : BackgroundService
{
private readonly IBackgroundTaskQueue queue;
private readonly IMetricsCollector metricsCollector;
public TaskQueueHostedService(
IBackgroundTaskQueue queue,
IMetricsCollector metricsCollector)
{
this.metricsCollector = metricsCollector;
this.queue = queue;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
Consts.Trace.Value.Info("Starting TaskQueueHostedService");
while (!stoppingToken.IsCancellationRequested)
{
try
{
var job = await this.queue.DequeueAsync(stoppingToken);
await this.metricsCollector.LogAsync(LogInvokeTask, (job, stoppingToken));
}
catch (Exception ex)
{
Consts.Trace.Value.Fatal(ex);
}
}
Consts.Trace.Value.Info("Finished TaskQueueHostedService");
}
private async Task LogInvokeTask(IMessage msg, ((string jobName, Func<CancellationToken, Task<int>> task) job, CancellationToken token) state)
{
var (job, token) = state;
msg.src = Consts.JobFacility;
msg.transaction_name = job.jobName;
var itemsAffected = await job.task?.Invoke(token);
msg.AddPair("no", itemsAffected);
}
}
Configuration fields explanation
- app metrics options
- app metrics middleware options
- app metrics httpclient options
- app metrics message defaults
Example log in GELF format
{
"version": "1.1",
"host": "wm-anx-macbook.local",
"level": 6,
"timestamp": 1562766590.96176,
"_application_name": "geows-be",
"_transaction_name": "locationproducts", // path in request url
"_user": "Mozilla/5.0", // User Agent
"_src": "geows-be",
"_rid": "5680338139043881971", // can be passed from Http request to chain request in one transaction flow or autogenerated if not present
"_mid": "4732771268302683729", // is always autogenerated to distinguish individual requests
"_con": "mpg", // tenant or client-id - something to detect the client
"_st": "OK", // return status (OK or ERR)
"_p": "geo", // product name, several applications can have the same product name
"_env": "development", // environment
"_platform": "shared-svc", // platform name, several products can be bound within one platform
"_host_ip": "192.168.195.81", // IP of host machine
"_rq_mth": "GET", // HTTP request method
"_rq_url": "http://localhost:5000/locationproducts?lang=de&prof=mpg&gp=IT.LI.PSA&product=gegs", // full request url
"_rs_code": 200, // HTTP response code
"_client_ip": "::1", // client IP, it also checks for X-Forwared-For ip collection
"_http__locations_geocodes__count_tt": 97.821, // outbound httpclient requests
"_http__locations_geocodes__search_tt": 52.019,
"_http__all_products_product__search_tt": 27.514,
"tx_bytes": 123, // bytes send by http client
"tx_bytes": 123, // bytes received from http client
"rx_bytes": 3625,
"_tt": 391.937, // HTTP request time taken
"_ttc": 128.025, // time taken spent awaiting for IO operation to complete
"_ttp": 263.912, // HTTP request CPU bound time taken (tt - ttc)
"short_message": "-" // - for OK, error message for ERR status
}
Example error log in GELF format
{
"version": "1.1",
"host": "wm-anx-macbook.local",
"level": 6,
"timestamp": 1562766590.96176,
"_application_name": "geows-be",
"_transaction_name": "locationproducts",
"_user": "Mozilla/5.0",
"_src": "geows-be",
"_rid": "5680338139043881971",
"_mid": "4732771268302683729",
"_con": "mpg",
"_st": "ERR",
"_p": "geo",
"_env": "development",
"_platform": "shared-svc",
"_host_ip": "192.168.195.81",
"_rq_mth": "GET",
"_rq_url": "http",
"_rs_code": 500,
"_client_ip": "::1",
"_http__locations_geocodes__count_tt": 97.821,
"_http__locations_geocodes__search_tt": 52.019,
"_http__all_products_product__search_tt": 27.514,
"_tt": 391.937,
"_ttc": 128.025,
"_ttp": 263.912,
"short_message": "Object reference not set to an instance of an object."
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.1 is compatible. netcoreapp2.2 is compatible. netcoreapp3.0 is compatible. netcoreapp3.1 was computed. |
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Anixe.IO.Appmetrics:
Package | Downloads |
---|---|
Anixe.IO.Appmetrics.Extensions.SqlDB
Package Description |
|
Anixe.IO.Appmetrics.Extensions.Mongodb
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
4.0.0 | 2,760 | 1/8/2024 |
3.0.1 | 615 | 12/4/2023 |
3.0.0 | 3,689 | 12/20/2022 |
2.1.1 | 4,064 | 1/21/2022 |
2.1.0 | 2,824 | 8/31/2021 |
2.0.20 | 786 | 7/8/2021 |
2.0.19 | 2,874 | 3/15/2021 |
2.0.18 | 842 | 1/27/2021 |
2.0.17 | 581 | 11/17/2020 |
2.0.16 | 1,173 | 10/21/2020 |
2.0.15 | 1,838 | 7/9/2020 |
2.0.13 | 1,030 | 4/27/2020 |
2.0.12 | 617 | 2/26/2020 |
2.0.11 | 1,315 | 12/11/2019 |
2.0.10 | 1,337 | 9/5/2019 |
2.0.9 | 566 | 9/2/2019 |
2.0.8 | 2,409 | 9/2/2019 |
2.0.7 | 551 | 8/28/2019 |
2.0.6 | 356 | 8/27/2019 |
2.0.5 | 342 | 8/27/2019 |
2.0.4 | 519 | 8/27/2019 |
2.0.3 | 347 | 8/23/2019 |
2.0.2 | 554 | 7/25/2019 |
2.0.1 | 442 | 7/23/2019 |
2.0.0 | 983 | 7/22/2019 |
1.0.1 | 710 | 7/15/2019 |
1.0.0 | 805 | 7/14/2019 |