Azure function : Appsetting.json is not working with Serilog.Sinks.Sumologic - c#

We are trying to implement logging using Serilog.Sinks.SumoLogic(1.0.1) to Azure function apps (without .NET core). Below is the code and appsetting.json we are using.
Code:
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json",optional: false, reloadOnChange: true)
.Build();
var loggerFromConfig = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
Appsettings.json:
{"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"System": "Warning",
"Microsoft": "Warning"
}
},
"WriteTo": [
{
"Name": "SumoLogic",
"Args": {
"endpointUrl": "https:"
}
}
]
}
}
With above appsetting we are not able to bind the sumologic sink with loggerFromConfig object and _sinks = {Serilog.Core.ILogEventSink[0]} which shows that there is no sink configured.
If we try the same code with a sample project with Microsoft.NET.Core.Apps dependency it is working fine.
It seems that appsettings.json is supported with .NET core apps only.
Please suggest how to write log using Serilog with appsettings.json (without .NET core apps).

As far as I know, the ReadFrom.Configuration method is used to get the setting from appsettings.json in .net core project.
Since the ReadFrom.Configuration method needs IConfiguration object. If you want to use ConfigurationBuilder, you need install the Microsoft.Extensions.Configuration package from the Nuget.
If you install this Nuget Package, you could use the ConfigurationBuilder class. But it will also install the Microsoft.NETCore.Platforms package.
In my opinion, the right way to use the Serilog in .net apps is using LoggerConfiguration().WriteTo.SumoLogic method like this.
var logger = new LoggerConfiguration().WriteTo.SumoLogic(url,
sourceName: "CustomSourceName",
sourceCategory: "CustomSourceCategory",
restrictedToMinimumLevel: LogEventLevel.Debug,
batchSizeLimit: 20,
period: TimeSpan.FromSeconds(1),
textFormatter: new RawFormatter())
More details, you could refer to this codes.
Since the ReadFrom.Configuration method also read the setting from the appsettings.json file then using these setting to create LoggerConfiguration object, I suggest you could directly use the LoggerConfiguration().WriteTo.SumoLogic method.
Besides, if you still want to use appsettings.json, I suggest you could read the appsettings.json's setting by using Newtonsoft package. Then you could pass these settings as parameters into LoggerConfiguration().WriteTo.SumoLogic method.

Related

C# Serilog config in ASP.NET Core 6

I have the following in appsettings.json for Serilog:
"Serilog": {
"Using": [],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft.AspNetCore": "Warning",
"System": "Warning" //Amik ezekből a névterekből jönnek is Informationok lesznek.
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
{ "Name": "Console" }
]
},
I tried to add Serilog for my bootstrap app, but nothing worked well :(.
It is not logging to the console.
I have the following settings in appsettings.json for Serilog. I tried to add Serilog for my bootstrap app, but nothing worked well
It is not logging into console.
Well, its not quite clear if you have followed all the steps accordingly. Based on your shared appsettings.json it appreared that your configuration is partially correct. If you don't define anything inside using block its better to ommit that. In addition to this, you haven't defined your "Args" parameter where need to log what I mean is the path. Furthermore, whether you have install the required nuget package and included the required code snippet in your program.cs file
Therefore, you can follow the steps below to implement it correctly.
Prerequisite:
Serilog Nuget Package
appsettings.json configuration
1. Serilog Nuget Package
To configure Serilog for asp.net core reagrdless of its version, you need to following package in your application reference.
serilog.aspnetcore, serilog.aspnetcore and serilog.expressions
You can add from your Nuget Package Manager as following:
Once all the required package installed accordingly it should look like below:
In addititon, you even can using nuget package manager console command which are like below:
dotnet add package serilog.aspnetcore
dotnet add package serilog.sinks.seq
dotnet add package serilog.expressions
2. appsettings.json configuration
Please replace your appsettings.json file as following for serilog.
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"path": "./logs/log-.txt",
"rollingInterval": "Day"
}
}
]
},
"AllowedHosts": "*"
}
Program.cs file
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console().CreateBootstrapLogger();
Log.Information("Staring up logging");
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, logConfig) => logConfig
.WriteTo.Console()
.ReadFrom.Configuration(context.Configuration));
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseSerilogRequestLogging();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex,"Unhandled Exception");
}
finally
{
Log.Information("Log Complete");
Log.CloseAndFlush();
}
Output:
Note: If you would like to know more details about logging in asp.net core you could check the official document here

Get query logs from MySqlConnector in ASP.NET Core 2.1

How to get the query logs from MySqlConnector (used with Dapper) in an ASP.NET Core 2.1 MVC application?
Install MySqlConnector.Logging.Microsoft.Extensions.Logging using NuGet
# Core CLI
dotnet add package MySqlConnector.Logging.Microsoft.Extensions.Logging
# VS package manager
Install-Package MySqlConnector.Logging.Microsoft.Extensions.Logging
and set the provider in Startup.Configure method:
var factory = app.ApplicationServices.GetService<ILoggerFactory>();
MySqlConnectorLogManager.Provider = new MicrosoftExtensionsLoggingLoggerProvider(factory);
UPDATE I found out that this causes The logging provider must be set before any MySqlConnector methods are called errors when you're running DB queries in a hosted service constructor. This could be fixed by adding it at the end of Startup.ConfigureServices instead:
var loggerFactory = provider.GetService<ILoggerFactory>();
MySqlConnectorLogManager.Provider = new MicrosoftExtensionsLoggingLoggerProvider(loggerFactory);
Displaying the logs
To display the logs, it's required to set your log level to debug in appsettings.json. I'd recomment the component based approach, because setting everything to debug would result in a massive amount of logs.
For queries, the TextCommandExecutor is responsible. We can enable logs for him like this:
{
"Logging": {
"LogLevel": {
"Default": "warning",
"TextCommandExecutor": "debug"
}
}
}
Example output:
dbug: TextCommandExecutor[0]
Session1.1 ExecuteBehavior Synchronous CommandText:
SELECT varname, value
FROM setting
WHERE varname IN('bburl', 'recycle_forum', 'maxposts')
Find the component
The component name could be found in two ways:
Look into the source code for calls to the logger like this:
static readonly IMySqlConnectorLogger Log = MySqlConnectorLogManager.CreateLogger(nameof(TextCommandExecutor));
Set the default log level for debug (only in small test environments)
{
"Logging": {
"LogLevel": {
"Default": "debug"
}
}
}
Now you see all logs and find the component after the level like dbug: TextCommandExecutor[0] ....
Source: https://mysqlconnector.net/overview/logging/

Microsoft Service Fabric and logging

I am investigating the best way to implement logging for my Service Fabric Stateless API and have been somewhat overwhelmed by the varying different solutions for what appears to be a relatively simple requirement.
I have implemented logging using the WebHostBuilder().ConfigureLogging and have successfully logged my trace messages to the Debug window and via Serilog.Extensions.Logging.File I have also managed to dump this log to a file, this all being controlled via a #if DEBUG directive and this I was happy with.
Then I needed to configure what would happen when deployed to a cluster within Azure and this is when I became overwhelmed!!!
I thought that I could register ServiceEventSource type logger in the same manner as I did with AddDebug however it was not this simple.
So I have managed to get my logs to appear within the diagnostic window using the ServiceEventSource.Current.Message but these logs are not integrated within the ASP.NET logging framework :/
My continued investigation has led me to understand that Service Fabric logging should be directed towards Application Insights albeit many, many articles having varying degrees of detail and applicability to the latest framework.
My current thinking is that I need to remove the ASP.NET logging and implement something such as EventFlow to allow my trace messages to be generated and subsequently piped through to Application Insights for interrogation at a later date, is my thinking correct??
Or am I currently going off at a tangent?
UPDATE 15/05/2019
After deploying this to Azure Service Fabric the log files were not populated, this appears to be an incompatibility between the Serilog.Sinks.AzureBlobStorage NUGET package and the .NET Core version 2.2.0 that my project was targeting.
I have posted a ticket on the GitHub page and await a response, in the short term you can download the source code and migrate the project to a Microsoft.NETCore.App 2.2.0 project and directly reference this and everything works perfectly.
ORIGINAL ANSWER
I seem to do this quite a lot, answering my own question but here goes again. It's taken me a day or two to get to the bottom of this so I thought I would share my findings and solution with the community in-case it might help somebody else in the future and/or somebody might have something to add or even contradict me which I'd welcome any input.
My development environment is as follows: -
Microsoft Visual Studio 15.9.11
Windows 10 Professional
SDK: Microsoft.NETCore.App 2.2.0
I created a new Service Fabric Stateless Service the purpose of this service is to provide RESTful endpoints to a Angular 7 front end web application.
My requirement was to provide logging information in both my development environment via the Debug window and to also provide similar logging information whilst my apps are being hosted within a Service Fabric Cluster on Azure.
NUGET Package Installations
Microsoft.Extensions.Logging (2.2.0)
Serilog.AspNetCore (2.1.1)
Serilog.Enrichers.Environment (2.1.3)
Serilog.Settings.Configuration (3.0.1)
Serilog.Sinks.Debug (1.0.1)
Serilog.Sinks.AzureBlobStorage (1.3.0)
Controlling Development & Production Environments
I control the development & production environments using the DEBUG pre-processor directive to include either the appsettings.json or appsettings.Development.json file.
My appSettings.Development.json file is like this: -
{
"AppSettings": {
// My app settings not applicable to this
},
"Serilog": {
"Using": [ "Serilog.Sinks.Debug" ],
"MinimumLevel": {
"Default": "Verbose",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {MachineName} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": ["WithMachineName"]
}
}
My appSettings.json file is like this: -
{
"AppSettings": {
// My app settings not applicable to this
},
"Serilog": {
"Using": [ "Serilog.Sinks.AzureBlobStorage" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "AzureBlobStorage",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {MachineName} {Level:u3}] {Message:lj}{NewLine}{Exception}",
"connectionString": "[Connection String]",
"storageContainerName": "app",
"storageFileName": "{yyyy}-{MM}-{dd}.log"
}
}
],
"Enrich": [ "WithMachineName" ]
}
}
As you can see from the above settings files I output to the Debug window when in development and I have chosen to output to Azure Blob Storage when deployed to a Service Fabric Cluster in Azure.
To implement the Serilog logging simple review my Stateless Service class implementation below, which shows how to toggle the two different appSettings.json files dependent upon the environment and also how the Serilog logger is inserted into the dependency injection system via the use of the UseSerilog extension method.
using System.Collections.Generic;
using System.Fabric;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ServiceFabric.Services.Communication.AspNetCore;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;
using Serilog;
namespace Caboodal.Manatee.ServiceFabric.Api.Identity
{
internal sealed class Identity : StatelessService
{
public Identity(StatelessServiceContext context)
: base(context)
{
}
private string AppSettingsFilename
{
get
{
#if DEBUG
return "appsettings.Development.json";
#else
return "appsettings.json";
#endif
}
}
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
var appSettings = GetAppSettings();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(appSettings)
.CreateLogger();
return new[]
{
new ServiceInstanceListener(
serviceContext =>
new KestrelCommunicationListener(
serviceContext,
"ServiceEndpoint",
(url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel()
.ConfigureAppConfiguration(
(builderContext, config) =>
{
config.AddJsonFile(AppSettingsFilename, false, true);
})
.ConfigureServices(
services => services
.AddSingleton(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseSerilog()
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
};
}
private IConfigurationRoot GetAppSettings()
{
return new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(AppSettingsFilename)
.Build();
}
}
}
Using the Logger within a controller
Because the ILogger instance is configured as a Dependency Injected instance it can simply be accessed within your Controller classes like any other dependency e.g.
[Authorize]
[ApiController]
[Route("[controller]")]
public class UserController : ApiController
{
private readonly IUserService _userService;
private readonly ILogger<UserController> _logger;
public UserController(IUserService userService, ILogger<UserController> logger)
{
_userService = userService;
_logger = logger;
}
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody] DtoAuthenticateRequest request)
{
// Adding log entries
_logger.Log(LogLevel.Debug, "Here is a log entry");
// Some code in here
return Ok(response);
}
}
I got very sidetracked with the ServiceEventSource.cs class but with the usage of Serilog I have now ignored this aspect of the project template.
If you wish to output your logs to other data consumers or simply into different formats then just review the Serilog website here for a complete list of the Sinks available, with Application Insights being one of the many.

AWS Logging not working

I created a very simple Console app which is supposed to log the messages to the AWS Logs but although the app runs I can't find any log on AWS.
I think publishing the app code does not make sense: I presume it's ok and it does not throw any exception.
I think the problem is located in the AWS settings. This is what I did in AWS:
created some role , not sure why but did it almost close to what aws poor and messy documentation says. So the role is created, not exactly as it was supposed in the "documentation" but it contains the required permissions for the logs. Why I created it? - I don't have a clue - my app does not use it!
Created the Log Group - ok, this parameter is what I put into the config of my app
Not sure I need t create the log stream, but ok, I created it, but when I click on it it says "No events found." and "It appears you have not installed a CloudWatch Logs agent .."
Why do I need some agent? what is it? how to install? - absolutely not clear and pointing to the poor aws "documentation" is useless.
I guess these are the major things done in the AWS but..still no result - nothing works, I cant see the logs.
Searched for the answer in google, youtube, etc - no result.
Found some code which is similar to mine but it's no enought - it seems there are some settings required to be done on AWS.
What's wrong?
You have two options:
Write log files to disk and use CloudWatch Agent to submit these logs to CloudWatch: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/QuickStartWindows2016.html
With this option you don't need to configure anything related to AWS in the program, but you have to install and configure the Agent.
Use AWS.Logger NuGet package and configure it to send the logs to CloudWatch, in this case you don't need to use the Agent: https://github.com/aws/aws-logging-dotnet/tree/master/samples/AspNetCore
With this option you must create AWS API user with CloudWatch Log writing permission and put this user credentials into AWS.Logger configuration. Show the configuring code you used if you need an advice on this.
I had a similar problem, which turned out to be more config-related.
Firstly, make sure that you have AWS Toolkit for Visual Studio installed and set up with the appropriate user. I use an IAM User with the correct policy permissions to read and write Cloudwatch logs.
Here's a copy of my basic console test that works correctly:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace Runner
{
class Program
{
public static async Task Main(string[] args)
{
var services = ConfigureServices(new ServiceCollection())
.BuildServiceProvider();
await services.GetService<App>().RunAsync();
}
private static IServiceCollection ConfigureServices(IServiceCollection services)
{
var configuration = ConfigurationFactory.GetConfiguration();
services
.AddSingleton(configuration)
.AddLogging(builder =>
{
var config = configuration.GetSection("Logging");
builder
.AddConfiguration(configuration.GetSection("Logging"))
.AddConsole()
.AddDebug()
.AddAWSProvider(configuration.GetAWSLoggingConfigSection().Config);
})
// add app
services.AddTransient<App>();
return services;
}
}
public class App
{
private ILogger<App> Logger;
public App(ILogger<App> logger)
{
Logger = logger;
}
public async Task RunAsync()
{
try
{
Logger.LogTrace("LogTrace", "{\"Test\":1}");
Logger.LogInformation("LogInformation", "{\"Test\":2}");
Logger.LogWarning("LogWarning", "{\"Test\":3}");
Logger.LogDebug("LogDebug", "{\"Test\":4}");
Logger.LogError("LogError", "{\"Test\":5}");
Logger.LogCritical("LogCritical", "{\"Test\":6}");
Thread.Sleep(3000);
Debugger.Break();
}
catch (Exception ex)
{
throw;
}
}
}
}
And my appsettings.json file is:
{
"Logging": {
"Region": "eu-west-1",
"LogGroup": "/dev/runner",
"IncludeLogLevel": true,
"IncludeCategory": true,
"IncludeNewline": true,
"IncludeException": true,
"IncludeEventId": false,
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console": {
"LogLevel": {
"Default": "Error",
"System": "Information",
"Microsoft": "Information"
}
},
"Debug": {
"LogLevel": {
"Default": "Trace",
"System": "Information",
"Microsoft": "Information"
}
}
}
}
The Thread.Sleep is to allow the console logger to catch up with itself - if you just break you often don't see anything.
Similarly, if you quit the program executing at the breakpoint the AWS logger won't flush its buffers to Cloudwatch (it will just create the logstream and leave it empty), so let the program run to completion to populate the logstream itself.

Serilog JsonFormatter in an ASP.Net Core 2 not being applied from appsettings file

I have an ASP.Net Core 2 web application where I'm trying to configure SeriLog to output in JSON format, configured via an appsettings.json file. I cannot get this to work with either the standard Serilog.Formatting.Json.JsonFormatter or the compact Serilog.Formatting.Compact.CompactJsonFormatter.
I see there's a similar question asked here, but there seems to be no conclusive answer using appsettings.json, and the thread has gone quiet for over a year (and I don't have enough reputation to comment to nudge further responses).
I'm using the following SeriLog packages:
Serilog.AspNetCore - 2.1.0
Serilog.Enrichers.Environment - 2.1.2
Serilog.Enrichers.Thread - 3.0.0
Serilog.Formatting.Compact - 1.0.0
Serilog.Settings.Configuration - 2.4.0
Serilog.Sinks.RollingFile - 3.3.0
The SeriLog section of my appsettings.json file reads:
"Serilog": {
"Using": ["Serilog.Sinks.RollingFile"],
"MinimumLevel": {
"Default": "Verbose",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "RollingFile",
"Args": {
"pathFormat": "C:\\Logs\\MLSBPortal-{Date}.txt",
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
"restrictedToMinimumLevel": "Debug",
"retainedFileCountLimit": "10",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{ThreadId}] [{SourceContext}] [{SessionId}] [{UserName}]: {Message}{NewLine}{Exception}"
}
}
],
with the formatter line modified to the following when testing with the default JSON formatter:
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
As suggested in multiple other places.
My output is being written fine, but the formatter setting does not appear to be making any difference to the output.
Am I doing something wrong here, or is this functionality not implemented via a configuration file read yet?
Thanks in advance for any help.
It turns out that it is not (currently) possible to specify both a formatter and outputTemplate at the same time (as clarified at https://github.com/serilog/serilog-aspnetcore/issues/31 ).
Hopefully this situation may change in the future...

Categories

Resources