Log event datetime with.Net Core Console logger - datetime

I'm using logging to Console output, that built-in to .Net Core framework.
Here initialization of the logger:
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton(new LoggerFactory()
.AddConsole());
Also for logging I'm using Microsoft.Extensions.Logging.LoggerExtensions class with methods Log...
Here an example of logging in my App:
_logger.LogInformation(eventId, "Action is started.");
Where _logger is instance of ILogger<T> class and initialized in the class constructor with built-in dependency injection.
As result of calling of the above method Console output shows following string:
info: NameSpaceName.ClassName[eventId] Action is started.
I would like to display date-time in the Console output, that points to time, when the Log method is executed, but it seems that Log.. methods don't contain any methods that allow to display date time.
Does it exist some method or additioanl classes-formatters that allow to display the action datetime in console output without passing it to the method as part of the message?

The feature was added into version 3 of the Microsoft.Extensions.Logging.Console(here is the pr). You can activate this with setting the TimestampFormat:
new ServiceCollection()
.AddLogging(opt =>
{
opt.AddConsole(c =>
{
c.TimestampFormat = "[HH:mm:ss] ";
});
})

Example in .NET 5 (ASP.NET Core):
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging(options =>
{
options.AddSimpleConsole(c =>
{
c.TimestampFormat = "[yyyy-MM-dd HH:mm:ss] ";
// c.UseUtcTimestamp = true; // something to consider
});
});
// ...
}
Output example:
[2020-12-13 12:55:44] info: Microsoft.Hosting.Lifetime[0] Application is shutting down...

For ASP.NET Core, you might prefer to use configuration file appsettings.json over wiring it directly into the code.
{
"Logging": {
"Console": {
"TimestampFormat": "[yyyy-MM-dd HH:mm:ss] "
}
}
}
This works out of the box, provided that Host.CreateDefaultBuilder() is invoked in Program.cs

Built-in .NET Core console logger doesn't log date-time. Track this issue to get more details. The easiest workaround is:
logger.Log(LogLevel.Information, 1, someObj, null, (s, e) => DateTime.Now + " " + s.ToString());
I wrote a custom console logger to automatically log the timestamp and do other useful tricks:
[2017.06.15 23:46:44] info: WebHost[1] Request starting HTTP/1.1 GET http://localhost:6002/hc

Related

Cannot modify managed objects outside of a write transaction || Realm .Net SDK

Realms.Exception.RealmInvalidTransactionException: Cannot modify managed objects outside of a write transaction
I was using Ream .Net SDK 10.13 and recently updated it to 10.19.0. After, the update I am frequently getting the above error.
Here is an example of how I am using it in my Xamarin Forms project
public class TestClass: RealmObject
{
//Class properties are defined
// as per the realm docs, proper attributes
//are added for Kets and mapping
}
Now in some class/view models, where I have an instance of the TestClass injected through the constructor
public async Task<SomeUserDefinedType> SomeMethod(TestClass item){
var realm = Realms.Realm.GetInstance();
await realm.WriteAsync(async()=>{
// setting property of the TestClass
item.SomeProperty = "Some Value";
});
return <Instance of SomeUserDefinedType>;
}
The above method call gives an exception. Above code is modified as per the new version.
The below code was as per the older version which was working fine but it started giving the same exception after the update
public async Task<SomeUserDefinedType> SomeMethod(TestClass item){
await item.WriteAsync(async i =>{
// setting property of the TestClass
i.SomeProperty = "Some Value";
});
return <Instance of SomeUserDefinedType>;
}
I tried many ways to resolve this issue but none is working.
Any Suggestions/Help will be highly appreciated.

ASP.Net Identity SecurityStampValidator is not called if using custom CookieAuthenticationEvents

Using Microsoft.AspNetCore.Identity (.net 7 at time of writing), the default security stamp validation is not done anymore if I use a custom CookieAuthenticationEvents. Configuring the SecurityStampValidatorOptions has no effect either.
Why is this happening and what can be done to enable the security stamp validation?
program.cs
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.ConfigureApplicationCookie(options =>
options.EventsType = typeof(CustomCookieAuthenticationEvents)
);//this prevents securityStampValidation from occurring.
//set a small interval between validations so we can debug
builder.Services.Configure<SecurityStampValidatorOptions>(o => o.ValidationInterval = TimeSpan.FromSeconds(10));
builder.Services.Configure<SecurityStampValidatorOptions>(o => o.OnRefreshingPrincipal = c =>
{
//breakpoint here is hit if ConfigureApplicationCookie(options.EventsType) is NOT set
return Task.FromResult(0);
});
builder.Services.AddScoped<CustomCookieAuthenticationEvents>();
CustomCookieAuthenticationEvents.cs is an empty class for now
public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{ }
This behavior should be documented as it falls between two products.
The doc says
Events: The Provider may be assigned to an instance of an object created by the application at startup time. The handler calls methods on the provider which give the application control at certain points where processing is occurring. If it is not provided a default instance is supplied which does nothing when the methods are called.
EventsType: If set, will be used as the service type to get the Events instance instead of the property.
Fine, but let's not be misleaded by the events definition, as it is part of the namespace Microsoft.AspNetCore.Authentication.Cookies which is not the Identity namespace.
Instead, let's look at the code for IdentityServiceCollectionExtensions, which, among other things, does for AddIdentity
.AddCookie(IdentityConstants.ApplicationScheme, o =>
{
o.LoginPath = new PathString("/Account/Login");
o.Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
};
})
So the cookie Events is set when adding Identity, and when we add our custom options.EventsType = typeof(CustomCookieAuthenticationEvents), the Events property is dismissed.
By looking at this code, we see that OnValidatePrincipal is the only event that is set, so we shouldn't have other unexpected missing functionalities. We also see that a static class is used to call the validation, so we can copy that into our CustomCookieAuthenticationEvents.
public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
public async override Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
await SecurityStampValidator.ValidatePrincipalAsync(context);
//optional custom code
}
}

Application Insights for .NET Core Azure WebJob

When I try to setup my .NET Core WebJob to use Application Insights, I get the following Exception on startup:
System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.AspNetCore.Hosting.IHostingEnvironment' while attempting to activate 'Microsoft.AspNetCore.Hosting.DefaultApplicationInsightsServiceConfigureOptions'.'
I'm sure I'm overlooking something, but I can't find it out. My Main method is like in many examples, like here
public static void Main(string[] args)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
Configuration.EnvironmentName = environment;
Configuration.IsDevelopment = string.Equals(environment, "Development");
var host = new HostBuilder()
.UseEnvironment("Development")
.ConfigureWebJobs(b =>
{
b.UseHostId("ecad61-62cf-47f4-93b4-6efcded6")
.AddAzureStorageCoreServices()
.AddAzureStorage()
.AddTimers()
.AddEventHubs();
})
.ConfigureServices(x => ConfigureServices(x))
.ConfigureAppConfiguration(b =>
{
b.AddJsonFile("appsettings.json", false, false);
b.AddJsonFile($"appsettings.{environment}.json", true);
b.AddEnvironmentVariables();
Configuration.Config = b.Build();
})
.ConfigureLogging((context, b) =>
{
b.AddConfiguration(Configuration.Config);
b.SetMinimumLevel(LogLevel.Trace);
b.AddConsole();
b.AddDebug();
//TODO fix applicationInsights
string appInsightsKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
if (!string.IsNullOrEmpty(appInsightsKey))
{
b.AddApplicationInsights(o => o.InstrumentationKey = appInsightsKey);
}
})
.Build();
using (host)
{
host.Run();
}
}
At first glance (and true shot in the dark), I would check to see if context.Configuration this throwing the exception because APPINSIGHTS_INSTRUMENTATIONKEY doesn't exist in the collection. The missing key could be throwing an exception that's bubbling up to your DI container.
EDIT: Trying giving this package a try and let me know if works. It's currently in pre-release. https://www.nuget.org/packages/Microsoft.Extensions.Logging.ApplicationInsights/
EDIT: The call to AddApplicationInsightsTelemetry uses DefaultApplicationInsightsServiceConfigureOptions is dependent on IHostingEnvironment. IHostingEnvironment isn't used by the WebJobsSDK which is causing your exception. The WebJobsSDK has it's on usage of Application Insights and you should be able to use it similarily to https://github.com/Azure/azure-webjobs-sdk/tree/dev/sample/SampleHost sample

ITelemetryProcessor behavior when deployed to AppService

I have created a custom telemetry processor which is adding customer properties to the telemetry items. When running locally, I don’t see any issue and I am seeing the properties being added(both in release and debug mode) and logged to the AppInsights.
When deployed to app service, I am seeing the logs, but the properties being added by the telemetry processor are missing.
I am using .Net Core 2.1 and the Application insights NuGet version is 2.3.0. Is there a way to debug why this is happening? Also is anyone aware if this is a known issue?
Can you share your code which adds application insights and the telemetry processor? It should be something like this:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddApplicationInsightsTelemetry();
services.AddApplicationInsightsTelemetryProcessor<MyFirstCustomTelemetryProcessor>();
// If you have more processors:
services.AddApplicationInsightsTelemetryProcessor<MySecondCustomTelemetryProcessor>();
// ...
}
Can you try to print the list of TelemetryProcessors registered with the TelemetryConfiguration instance? You can constructor inject TelemetryConfiguration to a controller class, and print out the list. Something like shown below.
string tpList;
public ValuesController(TelemetryConfiguration tc)
{
var tps = tc.TelemetryProcessors;
foreach(var tp in tps)
{
var s = tp.GetType().ToString();
tpList += s;
}
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", tpList };
}
This should confirm if the TelemetryProcessor is even in the config.
Also, when you say works local - do you mean when running from Visual Studio? VS alters behavior, so can try to run locally outside of VS, and see if it reproes.

Use session variables in to Hangfire Recurring Job

I have integrated hangfire in to Asp.net web application and trying to use session variables in to Hangfire Recurring Job as like below :
public class Startup
{
public void Configuration(IAppBuilder app)
{
HangfireSyncServices objSync = new HangfireSyncServices();
var options = new DashboardOptions
{
Authorization = new[] { new CustomAuthorizationFilter() }
};
app.UseHangfireDashboard("/hangfire", options);
app.UseHangfireServer();
//Recurring Job
RecurringJob.AddOrUpdate("ADDRESS_SYNC", () => objSync.ADDRESS_SYNC(), Cron.MinuteInterval(30));
}
}
My “HangfireSyncServices” class as below:
public partial class HangfireSyncServices : APIPageClass
{
public void ADDRESS_SYNC()
{
string userName = Convert.ToString(Session[Constants.Sessions.LoggedInUser]).ToUpper();
//Exception throwing on above statement..
//........Rest code.......
}
}
public abstract class APIPageClass : System.Web.UI.Page
{
//common property & methods...
}
but I am getting run time exception as below at the time of getting value in to “userName”:
Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the
section in the application configuration.
I have tried to resolve above error using this LINK & other solution also but not able to resolved yet. can anyone help me on this issue.
Thanks in advance,
Hiren
Hangfire jobs don't run in the same context as asp.net, it has it's own thread pool. In fact, Hangfire jobs may even execute on a different server than the one that queued the job if you have multiple servers in your hangfire pool.
Any data that you want to have access to from within the job needs to be passed in as a method parameter. For example:
public partial class HangfireSyncServices //: APIPageClass <- you can't do this..
{
public void ADDRESS_SYNC(string userName)
{
//........Rest code.......
}
}
string userName = Convert.ToString(Session[Constants.Sessions.LoggedInUser]).ToUpper();
RecurringJob.AddOrUpdate("ADDRESS_SYNC", () => objSync.ADDRESS_SYNC(userName), Cron.MinuteInterval(30));
Note that doing the above creates a recurring task that will always execute for the same user, the one that was triggered the web request that created the job.
Next problem: you're trying to create this job in the server startup, so there is no session yet. You only get a session when a web request is in progress. I can't help you with that because I don't have any idea what you're actually trying to do.

Resources