I am attempting to learn about and implement logging in a c# winforms application.
In most/all examples and documentation I have found they use .AddConsole() which provides me with the following error:
'ILoggingBuilder' does not contain a definition for AddConsole and no accessible extention method 'Add Console'...
My current code follows:
using Microsoft.Extensions.DependencyInjection; //<-----was suggested in an example but does nothing--<<<<
using Microsoft.Extensions.Logging;
public partial class FormMain : Form
{
public FormMain()
{
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole() //<-----------------------line with error---------<<<<
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<FormMain>();
logger.LogInformation("Example log message");
InitializeComponent();
...rest of program follows...
Can you assist in pointing out how to get the example code to compile?
If you have a link to where a tutorial/documentation that I can follow, I would greatly appreciate that as well.
I see in the Microsoft Docs that there is an ILoggerFactory.AddProvider(ILoggerProvider) method but I have not had any success with that either.
Thank you for your time.
There are various different logging mechanisms and you don't get them out of the box. You are missing the appropriate nuget package. You need to add a package reference to Microsoft.Extensions.Logging.Console. Once you do that, the extension methods should be available to you.
You can find the package on nuget.org.
Related
I am trying to get application insights to pick up on custom ActivitySource in a library, however the documentation is unclear on how to achieve this.
Currently I have the following:
...
public static readonly ActivitySource Source = new ActivitySource("MyCompany.Library");
...
In the library it is used like this:
using(var activity = Source.StartActivity("Action"))
{
...
}
And in my startup I've added the following:
services.ConfigureTelemetryModule<DependencyTrackingTelemetryModule>(
(m, o) => m.IncludeDiagnosticSourceActivities.Add("MyCompany.Library")
);
services.AddApplicationInsightsTelemetryWorkerService();
However, these activities are not being picked up by application insights.
Is there something else required to make application insights aware of these activities ?
I'd rather not 'pollute' these libraries with application insights code
ApplicationInsights SDKs does not support reporting telemetry from custom ActivitySource.
There is a preview version which supports ActivitySource based telemetry. (Its called OpenTelemetry AzureMonitorExporter)
https://learn.microsoft.com/azure/azure-monitor/app/opentelemetry-enable?tabs=net
Follow the below steps to operate:
Add the OpenTelemetry.Exporter.Console NuGet package.
dotnet add package OpenTelemetry.Exporter.Console
Update Program.cs with additional OpenTelemetry using directives
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
Update Main() to create the OpenTelemetry TracerProvider:
public static async Task Main()
{
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample"))
.AddSource("Sample.DistributedTracing")
.AddConsoleExporter()
.Build();
await DoSomeWork();
Console.WriteLine("Example work done");
}
Now the app collects distributed trace information and displays it to the console:
> dotnet run
You will get the result required.
Follow the below link for further reference:
https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-collection-walkthroughs
I there,
I've a Blazor app here that I would like to add Middleware class to it. but I can't find the startup.cs/IApplicationBuilder to add it.
My project only have a Program.cs class with a void Main method.
So how to configure a Middleware? Just adding a class named Startup.cs did not do the trick.
VS 2022/ .Net 6.0
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.AspNetCore.Mvc.Infrastructure;
// [other using]
public class Program
{
public static void Main(string[] args)
{
var builder = WebAssemblyHostBuilder
.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services
.AddTransient<DevicePresentationService>()
// [other Service registration]
builder.Services.AddOidcAuthentication(options =>
{
builder.Configuration.Bind("Auth0", options.ProviderOptions);
options.ProviderOptions.ResponseType = "code";
});
var webAssemblyHost = builder.Build();
webAssemblyHost.RunAsync();
}
}
So how to configure a Middleware?
Middleware runs on the server. You posted the startup code for the Client.
Middleware is 'not applicable' in a Browser based app.
This is the new structure in .Net 6. You need to add all previous Startup.cs logic to Program.cs
To add your middleware, add:
var app = builder.Build();
and
app.MyMiddleware();
Make sure the entire namespace of the Middleware is added to your usings at the top of your file, or in global usings.
Documentation
EDIT: I didn't see that this a web assembly Blazor application. #Henk Holterman is correct, you cannot use middleware on a client only application. You will need to add the middleware to your Server.
I am attempting to use entity framework against a database in Azure. I have a connection string stored in the local.settings.json, but all of my attempts to reference it from a Startup.cs have failed.
I am able to access my connection string using an IConfiguration DI into a function class and I can successfully access the database with SQL Command using the configuration like:
string connectionString = _configuration.GetConnectionString("cpni");
So I know that the connection string is working and that I can access it.
If I try to use DI with IConfiguration on the Startup class, the compiler does not give me any errors, but once it's running in debug I begin getting the following error:
System.Private.CoreLib: No parameterless constructor defined for type 'CPNI_Functions.Startup'.
Here is what I'm currently successfully using with a hardcoded connectionString (since using DI with IConfiguration isn't working):
builder.Services.AddDbContext<CpniContext>(
options => options.UseSqlServer(connectionString));
And that allows me to work with the database through EF. What I would like to use is some combination of that and something like this:
builder.Services.AddDbContext<CpniContext>(/*options need to go here?*/)
.Configure<IConfiguration>((configuration) =>
{
//Or are options supposed to go here somewhere, or be bound here with some sort of .Bind()?
configuration.GetConnectionString("cpni");
});
If that doesn't make sense or won't work, then please let me know what the recommended way of setting this DI up is. If possible, I want to avoid using configuration lookup through ConfigurationManager.
For reference, here is the full Startup.cs and this works:
using CPNI_Functions.Data;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(CPNI_Functions.Startup))]
namespace CPNI_Functions
{
class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
string connectionString = "myconnectionstringhere";
builder.Services.AddDbContext<CpniContext>(
options => options.UseSqlServer(connectionString));
}
/*
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CpniContext>(configuration.GetConnectionString("cpni"));
}*/
}
}
I'm new to core and I'm new to Azure Functions, so please forgive my ignorance on this. Thank you in advance for your help.
For an Azure function app you could try adding NuGet package:
System.Configuration.ConfigurationManager
local.settings.json:
{
"ConnectionStrings": {
"cpni": "[ConnectionStringDetails]"
}
}
Then hopefully you should be able to access using ConfigurationManager.
services.AddDbContext<CpniContext>(
options => options.UseSqlServer(ConfigurationManager.ConnectionStrings["cpni"].ConnectionString));
I upgraded my project to .NET Core 2.2.x and got an obsolete warning regarding the following code - both lines:
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
The suggestion to fix is The recommended alternative is AddConsole(this ILoggingBuilder builder). I thought that is what I am using.
What am I missing here?
I had the same issue today.
Remove your logging configuration from Startup.cs and go to your Program.cs file and add something like:
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.Build();
This used the 'builder' because the variable 'logging' is an IloggingBuilder (whereas your code is still using ILoggerFactory)
UPDATE: The other method I just tried is to stay inside Startup.cs but move the logging stuff from the 'Configure' method to 'ConfigureServices' like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddConfiguration(Configuration.GetSection("Logging"));
loggingBuilder.AddConsole();
loggingBuilder.AddDebug();
});
}
Perhaps keeps the Program.cs less polluted...
The documentation's recommendation to use AddConsole(this ILoggingBuilder builder) is correct, but for that to work you need to add a reference to the NuGet package Microsoft.Extensions.Logging.Console.
I got the same warning when I was updating logging code from .Net Core 2.1 to 3.0. The recommended way to do the upgrade is documented on MSDN.
In my case, I was trying to get an instance of LoggerFactory for console which is pretty straightforward in .Net Core 3.0:
using (var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()))
{
// use loggerFactory
}
Don't worry about it - this is the dumbest thing ever!
Note
The following code sample uses a ConsoleLoggerProvider constructor
that has been obsoleted in version 2.2. Proper replacements for
obsolete logging APIs will be available in version 3.0. In the
meantime, it is safe to ignore and suppress the warnings.
In case you thought you forgot what Obsolete meant - you hadn't! Don't worry about it and just ignore it for now - or suppress the warning (sorry I don't have the code for that to hand).
(Wish they'd put a better explanation for why this was done - that's what I mean by dumb.)
According to the issue opened on GitHub for this, the replacement methods are already being called if you use CreateDefaultBuilder() method in your Program.cs.
https://github.com/aspnet/Docs/issues/9829
The only issue I have is that I only turned these on for non-Production environments.. and don't see a way to do so going forward.
If you don't have access to the LoggerFactory.Create(), use can still use the ILoggerFactory with the AddProvider() method giving it a ConsoleLoggerProvider() but it is a bit of a pain if you want to do something simple. The problem is, ConsoleLoggerProvider() requires a IOptionsMonitor<ConsoleLoggerOptions> as a parameter and the easiest thing to do if you
you don't have access to the options mechanism in your code base (my problem), or
the real options mechanisms in your existing code base don't match up with IOptionsMonitor<>, or
you have other reasons not to use the ASP.Net options facilities
is to create a dummy class:
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;
class DummyConsoleLoggerOptionsMonitor : IOptionsMonitor<ConsoleLoggerOptions>
{
private readonly ConsoleLoggerOptions option = new ConsoleLoggerOptions();
public DummyConsoleLoggerOptionsMonitor(LogLevel level)
{
option.LogToStandardErrorThreshold = level;
}
public ConsoleLoggerOptions Get(string name)
{
return this.option;
}
public IDisposable OnChange(Action<ConsoleLoggerOptions, string> listener)
{
return new DummyDisposable();
}
public ConsoleLoggerOptions CurrentValue => this.option;
private sealed class DummyDisposable : IDisposable
{
public void Dispose()
{
}
}
}
You can then use your ILoggerFactory like:
factory.AddProvider(
new ConsoleLoggerProvider(
new DummyConsoleLoggerOptionsMonitor(LogLevel.Debug)));
I'm trying to read my configuration from SF configuration using the 'ConfigurationPackage' that is available from any SF service context. My class looks like this:
internal class ServiceFabricDbConfiguration : IDbConnectionConfig
{
private ConfigurationPackage _configurationPackage;
public ServiceFabricDbConfiguration(ServiceContext context)
{
_configurationPackage = context.CodePackageActivationContext.GetConfigurationPackageObject("Config");
}
public string UserName =>
_configurationPackage.Settings.Sections["Db_Configuration"]
.Parameters[
"Username"]
.Value;
}
I'm using autofac as my DI container, and can register the above class by explicitly capturing a reference to the ServiceContext when i register it with the SF runtime:
ServiceRuntime.RegisterServiceAsync("ApiType",
context =>
{
Bootstrapper.SetContext(context);
return new Api(context);
})
.GetAwaiter()
.GetResult();
Is there a way that i can register the ServiceContext with the bootstrapper, ideally within the bootstrapper class?
I'm currently experimenting with using Autofac.ServiceFabric to register my actors/services, but that hides the ServiceContext so makes the above harder to achieve again (though does make it far easier to maintain clean autofac module definitions)
There's the static method GetActivationContext() in FabricRuntime. You could perhaps use this to inject the activation context.
There's also, in development, Autofac.ServiceFabric https://github.com/autofac/Autofac.ServiceFabric which may be of use to you. There's a blog post about it here https://alexmg.com/introducing-the-autofac-integration-for-service-fabric/ which also contains links to sample code! It's in pre-release (beta) at the moment but I have been using it without issue for the past few months.
PR 8 makes the ServiceContext available in Autofac.ServiceFabric