What is the difference between ILogger<T> and ILogger? Below are two ways the Sample class using ILogger, which one is the best and why!
Method 1
public class Sample
{
private readonly ILogger<Sample> _logger;
public Sample(ILogger<Sample> logger)
{
_logger = logger;
}
public void DoSomething()
{
_logger.LogInformation("The answer is {number}", 42);
}
}
Method 2
public class Sample
{
private readonly ILogger _logger;
public Sample(ILogger logger)
{
_logger = logger;
}
public void DoSomething()
{
_logger.LogInformation("The answer is {number}", 42);
}
}
As per usage of ILogger in your .net core which is depends of your requirements.
ILogger
ILogger is a logger that your code can use to write log messages.
There are three core methods:
IsEnabled tests whether a log level is enabled on that logger;
Log is the core logging method that is used to write log messages;
BeginScope defines a logging scope.
There’s a bunch of logging extension methods that build on that core; the common methods like LogInformation are just wrappers around Log, with the appropriate arguments.
Internally, an ILogger has a “name” (also called a “category”). The idea is that each ILogger instance is used by a different component of the application.
ILogger is a base interface that provides the core logging functionality, but it is seldom used directly. There are some exceptions (e.g., Azure Functions will pass you an ILogger), but most of the time your code will log to an ILogger<T>.
ILogger
ILogger<T> is a logger that is named after a type T. All logs sent to an ILogger<T> (with the default implementation) will have a logger name/category of typeof(T).FullName. ILogger<T> is derived from ILogger and adds no new functionality.
If you’re using dependency injection, an instance of ILogger<T> is usually injected into your type T. So, each time you have a constructor that takes an ILogger<T>, you are defining a “component” for your application.
Majar usage of difference
If you want to log your data as Typed log (serilog, etc., ) you can use ILogger< T> or you want to use untyped logs you can simply use ILogger
ASP.NET Core apps, encourage you to use standard Serilog interfaces like Log, ILogger, and LogContext if they meet your needs.
Alternatively, your app can consume the ILogger interface from the framework via dependency injection. Serilog implements this interface, so the results are identical for practical purposes.
The ILoggerFactory logger factory instance is the boostrapper of the logging system: It is used to attach logger providers and create logger instances - either typed (ILogger<T>) or untyped (ILogger). These logger instances will log to all registered logger providers.
Refer Ilogger best practices & Usage of logging
Related
I have a ServiceStack host which depends on an external class which has a constructor of the form
public class MyClass(ILogger<MyClass) {}
but when I call
container.AddSingleton<ISearchEngine, ElasticSearchEngine>();
ServiceStack is not resolving ILogger, what can I do to get this to work?
ServiceStack.Logging abstraction uses .NET Core's logging provider implementation where you'll end up with the same logging implementation using ServiceStack's logging abstraction:
public class MyClass
{
public ILog Log = LogManager.GetLogger(typeof(MyClass));
}
Alternatively you can register your dependency with ASP.NET Core's IOC to access their ILogger<T> abstraction directly:
builder.Services.AddSingleton<ISearchEngine, ElasticSearchEngine>();
This non static class is required for constructor injection in Azure function and collection of custom telemetry events.
If we create an azure function app in visual studio, it creates default with static keyword like this:
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
telemetryClient.TrackEvent(new Exception("Function started"));
}
But to use constructor dependency injection (for Temeltry client, i am using it), we need to remove static keyword.
public Function1(TelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient;
}
Previously, Azure Functions only supported static classes/methods. This restriction made DI via constructor impossible. However later the support for non-static classes/methods was implemented (see Support Instance Functions).
So if you need to use DI via constructor, just change it to non-static. There are no consequences.
This is not entirely true though - I just ran into some trouble with non static timer triggered functions. In my case I needed dependency injection in terms of entity framework, but this non static instance is now causing me trouble in order to call the admin endpoint to trigger the function when doing development locally.
See more on how to normally invoke static timer triggered functions here:
What is the simplest way to run a timer-triggered Azure Function locally once?
ServiceStack uses a dialect of Funq (no support for metadata), where Kephas uses one of MEF/Autofac (requires metadata support). My question has two parts:
How to make ServiceStack and Kephas use one DI container, if this is possible?
Depending on the answer above: how to make ServiceStack services (like IClientCache) available to Kephas components, knowing that such services may not be annotated with [AppServiceContract]?
You can make ASP.NET and Kephas use one container by choosing to work with Autofac. However, as #mythz pointed out, you will need to provide the Autofac IoC Adapter to the ServiceStack. I don't think you will have any problems with ASP.NET in doing so, as Autofac is the first recommendation of the ASP.NET Core team.
For ASP.NET Core, reference the Kephas.AspNetCore package and inherit from the StartupBase class if you need to be all setup. However, if you need to be in control, have a look at https://github.com/kephas-software/kephas/blob/master/src/Kephas.AspNetCore/StartupBase.cs and write your own Startup class. Another resource that you might find useful is the Kephas.ServiceStack integration package.
Then, additionally to annotating service contracts and service implementations, Kephas allows you to provide service definitions by implementing the IAppServiceInfoProvider interface. These classes are automatically discovered, so this is pretty much everything you have to do.
public class ServiceStackAppServiceInfoProvider : IAppServiceInfoProvider
{
public IEnumerable<(Type contractType, IAppServiceInfo appServiceInfo)> GetAppServiceInfos(IList<Type> candidateTypes, ICompositionRegistrationContext registrationContext)
{
yield return (typeof(IUserAuthRepository),
new AppServiceInfo(
typeof(IUserAuthRepository),
AppServiceLifetime.Singleton));
yield return (typeof(ICacheClient),
new AppServiceInfo(
typeof(ICacheClient),
ctx => new MemoryCacheClient(),
AppServiceLifetime.Singleton));
}
}
Note in the above example that for IUserAuthRepository there is no implementation provided. This indicates Kephas to auto-discover the implementation in the types registered for composition. Alternatively, feel free to use an instance or a factory in the registration, if you need to be deterministic.
I've never heard of Kephas before, but if you're referring to this Kephas Framework on GitHub it says it uses ASP.NET Core in which case it's best if you get them to both use ASP.NET Core's IOC which you can do by either registering your dependencies in ConfigureServices in your App's Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//...
}
}
Or alternatively in ServiceStack's latest v5.6 release for Modular Startup change your ASP.NET Core Startup class to inherit from ModularStartup, e.g:
public class Startup : ModularStartup
{
public Startup(IConfiguration configuration) : base(configuration){}
public new void ConfigureServices(IServiceCollection services)
{
//...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
}
}
In which case you'll be able to Register ASP.NET Core dependencies in AppHost by registering them in your AppHost's Configure(IServiceCollection) where they can be resolved through both ASP.NET Core's IOC + ServiceStack's IOC, e.g:
public class AppHost : AppHostBase
{
public override void Configure(IServiceCollection services)
{
services.AddSingleton<IRedisClientsManager>(
new RedisManagerPool(Configuration.GetConnectionString("redis")));
}
public override void Configure(Container container)
{
var redisManager = container.Resolve<IRedisClientsManager>();
//...
}
}
I followed Alexander Duemont's blog, trying to implement a Java Spring Boot application that consumes Cloud Foundry Destination. The Destination has a custom OData V2 behind it, coming from an On-Premise ERP system. For local dev, when I perform the Maven build, the Integration-Tests module registers failure due to dependency injection
This is part of my Controller
#RestController
#RequestMapping("/resources")
public class ClassificationsController {
private static final Logger logger = CloudLoggerFactory.getLogger(ClassificationsController.class);
private final ClassificationService service;
public ClassificationsController(#Nonnull final ClassificationService service) {
this.service = service;
}
…..
}
The #Nonnull final ClassificationService Service causes org.springframework.beans.factory.UnsatisfiedDependencyException
I cannot use Spring stereotype annotations on generated Service classes (Fluent) to create Beans!
This question is more likely related to Spring Boot configuration.
I'm assuming ClassificationService is an interface and the implementing class exists in the same package.
Please make sure...
... to add the implementing class of ClassificationService to your component scan / test runtime. Feel free to share the integration test code to setup the test environment. Maybe the additional class reference is missing.
... to correctly annotate the respective Application class of your Spring Boot project. For example, assuming your ClassificationService resides in org.example.services.classification, while the rest of your application uses org.example.app. Your basic Application class would look like this, when following the Cloud SDK guide:
#SpringBootApplication
#ComponentScan({"com.sap.cloud.sdk", "org.example.services.classification", "org.example.app"})
#ServletComponentScan({"com.sap.cloud.sdk", "org.example.app"})
public class Application extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure( final SpringApplicationBuilder application )
{
return application.sources(Application.class);
}
public static void main( final String[] args )
{
SpringApplication.run(Application.class, args);
}
}
... to annotate the implementing class of ClassificationService with javax.inject.Named. In case you have multiple implementations of the same interface, make sure to give the not-used class a custom (unique) value for the #Named annotation.
... to look for exceptions (Class not found) in the application log during startup.
I'm trying to initialise my dependency registration for a WCF service running in an Azure Web Role, but I'm seeing a very unusual behaviour whereby the static constructor of my class is being invoked twice.
This is the Dependencies class I'm using as a registry point for the dependencies of the application.
public static class Dependencies
{
private static IUnityContainer container;
static Dependencies()
{
Dependencies.container = new UnityContainer();
}
public static IUnityContainer Container
{
get
{
...
}
set
{
...
}
}
public static void ConfigureContainer()
{
var container = new UnityContainer();
// Configure container.
Dependencies.container = container;
}
}
In my overload of RoleEntryPoint.OnStart(), I make a call to a static ConfigureContainer method to set up the container with my dependencies registered:
public override bool OnStart()
{
// Configure container for dependency resolution.
Dependencies.ConfigureContainer();
return base.OnStart();
}
My expectation is that the static members of the Dependencies class should be initialised by this code and will be available to the components of the application.
What I'm seeing (using a breakpoint and the VS2012 debugger) is that the static constructor of Dependencies is being called twice: once during the original initialisation of the application and again during first request to the service. Subsequent requests don't invoke the static constructor (as expected).
I'd love to hear an explanation of why the runtime is behaving this way and what I should be doing instead to produce my static registry of dependencies.
It's likely because when you host a webrole in full IIS, the RoleEntryPoint code and the rest of the web application run in different AppDomains.
http://blogs.msdn.com/b/windowsazure/archive/2010/12/02/new-full-iis-capabilities-differences-from-hosted-web-core.aspx
By default you use "full IIS" mode in a web role and you get two processes - IIS worker process for handling HTTP requests and role worker process for running RoleEntryPoint descendant code. Depending on how your code is designed you may end up using that static constructor in both processes and then it'll be invoked twice.