How does Serilog calculate Elapsed in Web API? - c#

For Web API in .NET 6, I'm configuring Serilog request logging.
app.UseSerilogRequestLogging(options =>
{
options.MessageTemplate = "Elapsed: {Elapsed:0.0000} ms";
});
How is Elapsed calculated exactly?

Serilog has custom RequestLoggingMiddleware which is injected into pipeline via UseSerilogRequestLogging call (that's why it is important to call this method as early as possible cause otherwise it will not take into account time consumed by components that appear before it in the pipeline, as mentioned in the docs). The implementation is pretty straightforward - sample time at the start of logging middleware, invoke the rest of pipeline, sample time at the end, calculate the difference. Currently calculation looks somewhat like this:
var start = Stopwatch.GetTimestamp();
var Elapsed = GetElapsedMilliseconds(start, Stopwatch.GetTimestamp());
static double GetElapsedMilliseconds(long start, long stop)
{
return (stop - start) * 1000 / (double)Stopwatch.Frequency;
}

Related

How to run functionality only sometimes in an Azure function

I have an Azure function with a trigger to make it run once every 15 minutes:
TimerTrigger("0 */15 * * * *", RunOnStartup =false)
Within this function, there is some functionality that I only want to run once per hour. I am currently checking the minute of the current time to see whether it should run or not. But as I understand it, Azure function triggers are not always precise (this is running on a consumption-based app service), so instead I am checking for a range of minutes.
int currentMinute = DateTime.Now.Minute;
bool extraFunctionality = (currentMinute >= 58 && currentMinute <= 2);
This seems like it will work; only running this functionality during the ":00" runs, once per hour. However, it looks like bad code to me, for a couple reasons:
The up to 2 minutes early and 2 minutes late number was chosen pretty much arbitrarily; I don't have a good idea of what sort of time span to use there.
It relies on using DateTime.Now which will return different results depending on server settings, even though I don't care about anything other than the current minute.
The code simply doesn't read like the intent is to get it to run once per hour.
Is there a better / more proper way to do this within Azure functions? Can I either get information from the TimerInfo parameter or the ExecutionContext parameter about which 15-minute trigger caused the function to run? Or can I have a separate TimerTrigger which runs once per hour, and then have different functionality based on which of the 2 timers caused the function to trigger? Or is there some way to have the TimerTrigger itself pass in a parameter telling me which 15-minute window it is in?
Or, is my code fine as-is; perhaps with some adjustment to the number of minutes I allow it to be off?
You could create two Azure Functions, one which runs at 15, 30, 45 minutes past the hour and another which runs on the hour. Then in each of these functions set a variable for if it's runnin on the hour.
[FunctionName("HourlyFunction")]
public static void RunHourly([TimerTrigger("0 0 15,30,45 * * *")]TimerInfo myTimer, ILogger log)
{
_myService.Run(true);
}
[FunctionName("FifteenMinuteFunction")]
public static void RunEveryFifteen([TimerTrigger("0 0 * * * *")]TimerInfo myTimer, ILogger log)
{
_myService.Run(false);
}
Then have a separate service which can be called by those functions:
public class MyService : IMyService
{
public async Task Run(bool isHourlyRun)
{
// Do work here
}
}
* I'm not sure those cron expressions are correct

Identify execution time and Tracing of each API in ASP.NET WEB API and log to files using log4net using C#

Currently , I am capturing execution time of each API using log4net and explicitly mentioning the start time and end time at the beginning and end of each API and writing into log file, as below
[HttpGet]
Public IHttpActionResult GetProducts()
{
Log.info("API Execution Started at " + DateTime.Now());
Var Products = UnitOfWork.GenericRepo.GetProducts();
Log.Info("API Execution Completed at "+ DateTime.Now());
Return Ok(Products);
}
Is there a better way to capture the execution time of each API and write that into a log file ?
Also, Please provide me an insight on how to capture Tracing information of all APIs and writing that into different log files. For Example , Execution time of each API should be written into "ExecutionLog.txt" and Tracing infomration into "TracingLog.txt". I should also be able to enable or disable this features during run time.
Thanks in advance
#Mahesh, You don't need to write it in each API. You can use ActionFIlter and ResultFilter and write a single code block to trace all actions in your API
Have a look at this
https://jmperezperez.com/tracking-action-execution-time-in-asp-net-mvc/
Use Stopwatch from System.Diagnostics namespace
see this for an example Example
MSDN
In, System.Diagnostics namespace, you have a class named StopWatch. You can use this for checking function execution time. Use the Start() and Stop() methods for finding the total execution time.
Here is a simple example taken from dotnet pearl website
Stopwatch stopwatch = new Stopwatch();
// Begin timing.
stopwatch.Start();
// Do something.
for (int i = 0; i < 1000; i++)
{
Thread.Sleep(1);
}
// Stop timing.
stopwatch.Stop();
// Write result.
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);

Send notification on specific date and time

In our App, We are storing questions with Question's startdate, enddate and resultdate. We need to send notification to app (iPhone and Andorid) once startdate of question is arrives.
Can anybody let me know how can we achieve this?
We don't want to use pull method. like in particular time interval it will check for question startdate and send notification.
I have a URL to send Notification for question. I need to call this URL when question's startdate is arrived.
Thanks.
Take a look at Quartz :
Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems
Quartz Enterprise Scheduler .NET
You can create a new Quarts Job, lets call it QuestionSenderJob. Then your application can schedule a task in Quartz scheduler, jobs can have many instances of same Job with custom data - in your case QuestionId.
Additionally it supports storing Job scheduling in your SQL database (there are DDL Scripts included) so you can create some relations if you need for UI for example.
You can find table-creation SQL scripts in the "database/dbtables" directory of the Quartz.NET distribution
Lesson 9: JobStores
This way you leave firing in right moment to Quartz engine.
When you will go through Quartz .NET basics, see this code snippet I made a for your case to schedule job. Perhaps some modifications will be necessary thought.
IDictionary<string, object> jobData = new Dictionary<string, object> { { "QuestionId", questionId } };
var questionDate = new DateTime(2016, 09, 01);
var questionTriggerName = string.Format("Question{0}_Trigger", questionId);
var questionTrigger = TriggerBuilder.Create()
.WithIdentity(questionTriggerName, "QuestionSendGroup")
.StartAt(questionDate)
.UsingJobData(new Quartz.JobDataMap(jobData))
.Build();
scheduler
.ScheduleJob(questionSenderJob, questionTrigger);
Then in Job you will get your questionId through JobExecutionContext.
public class QuestionSenderJob: IJob
{
public void Execute(JobExecutionContext context)
{
JobDataMap dataMap = context.JobDetail.JobDataMap;
// Extract question Id and send message
}
}
What about using the Task Scheduler Managed Wrapper?
You do not want to use pooling, but if you write your own class that will encapsulate Timer (e.g. System.Thread.Timer) and check for the time each second, that will not take much resources. Depending on how exact you need it, you could check also less often, e.g. each minute. Maybe you should reconsider it.
If you use any third party service to manage your push notification such as Azure Notification Hub, Parse.com, ... they offer an integrated way to schedule push notifications. Either by passing in a send date or let them run a job periodically. I'm a user of the Azure service and it works very well.
The best implementation i can advice right now is for you to send the notification from a server.
All you just need is a good scheduler that can dispatch operation.
For me, my server is powered by Javascript (NodeJS) so i use "node-schedule". All i just do is
var schedule = require('node-schedule');
//Reporting rule at minute 1 every hour
var rule = new schedule.RecurrenceRule();
rule.minute = 1;
schedule.scheduleJob(rule, function () {
console.log(new Date().toTimeString() + ' Testing Scheduler! Executing Every other minute');
//sendPush()
});

C# performing a task every hour

I have a CSV importer tool I use at my company that imports 10-20k records at a time but it can take a couple hours, the issue is that the application is connecting to an API that has an OAuth token that expires after an hour.
to me this sounds like a job for timer, but the actual code that imports and needs the oauth token are in modules since each vendor I have to upload have their own mappings to the api we use.
so I need to programmatically need to see if 3590 seconds (or 50 minutes) has passed so that I can refresh my OAuth token.
does anyone know how I can do this? if timer is not the best way to go, what way would you suggest?
it'd be nice if timer has an Elapsed property I could access from my other objects (like I can with background worker).
You could just make it part of your processing loop:
{
DateTime lastReset = DateTime.Min;
TimeSpan resetInterval = TimeSpan.FromMinutes(50);
foreach (var whatever in enumerable)
{
if ((DateTime.Now - lastReset) > resetInterval)
{
ResetAuthToken();
lastReset = DateTime.Now;
}
ProcessWhatever();
}
}
I would suggest that you can use the timer's elapsed event. This will be triggered based on the interval may be 50 minutes etc, which you can read from the configuration file of the windows service.
Then in the timer interval, you can just update a global variable [property] with the Auth token that will be used for the subsequent API calls.
In case you just want to keep the session alive, you can just refresh the token as itmse86 said. However, the timer elapsed event will come handy for you.
Reference here

Scheduling with Network Time Server (SNTP) in Quartz .NET

I need to use network-validated time when scheduling jobs.
Solution?
With the latest .NET Quartz library, does anyone knowledgeable in the inner workings of Quartz .NET know which class(es) actually implement the job to start at the specified time? (details below)
Or is there an alternative C# library / API that already supports NTP queries and that can schedule jobs?
Please note that using the approach of inputting the difference between local time and network time to a non-NTP scheduler does not work for me because I need to prevent users cheating by way of changing their local system time or timezone
Quartz .NET Details - where I got stuck in my investigation
I cannot find how the property StartTimeUtc of ITrigger is used (set with the StartAt method below)?
var sleepTrigger = (ISimpleTrigger)TriggerBuilder.Create()
.WithIdentity("SleepTimeTrigger")
.StartAt(sleepRunTime)
.WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())
.Build();
i.e. I need to check the specific implementation that uses the StartTimeUtc timestamp in order to change the scheduling source code / add an option to schedule independently of local system time and use network time instead.
There is a static class under Quartz namespace which has two methods receiving a Func<DateTimeOffset> that you can use to return your NTP tunned date/time. It is the "official" Quartz date/time source, and is implemented to allow easy unit testing, but could also be used to customize the date/time. Here is a a sample usage:
SystemTime.Now = () => {
//return your custom datetime here
/*
var ntpTime = new NtpTime(server);
return ntpTime.NowDateTimeOffset;
*/
};
SystemTime.UtcNow = () => {
//return your custom datetime here
/*
var ntpTime = new NtpTime(server);
return ntpTime.UtcNowDateTimeOffset;
*/
};
Notice the code above will not compile, you need to implement your own method of getting the current DateTimeOffset for both Now and UtcNow. There are many ways to get the time from a NTP, you can find some approaches here and here. I suggest that your implementation caches the current datetime and increment it locally instead of asking the ntp server on every call, for performance reasons.

Categories

Resources