Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Sunday, 4 March 2018

Request Linking in asp.net core


In systems where events are processed in several microservices is useful to maintain a request identifier to be able to link logs from each microservice to do some investigation or to measure performance.
So far we have relied in a custom http header and owin middleware to read, add a new segment to this request identifier and then set it in the log4net context so it can be written when logging an event.
For a new asp.net core service I'm working, I have quickly put together new middleware to do the same operation using the documentation, but instead of using log4net I have found that it is easier to use NLog to capture the TraceIdentifier property in the HttpContext.

Middleware

public class TransactionLinkingMiddleware{
private readonly RequestDelegate _next;
public const string ParentTransactionHttpHeader = "Transaction-Link";
public TransactionLinkingMiddleware(RequestDelegate next)
{
 
_next = next;   
}
public Task Invoke(HttpContext context)
{
if (context.Request.Headers.TryGetValue(ParentTransactionHttpHeader, out var headerValues)
                                    && headerValues.Any())
{
context.TraceIdentifier = $"{headerValues.First()}/{context.TraceIdentifier}";
}
// Call the next delegate/middleware in the pipeline
return this._next(context);
}
}

public static class TransactionLinkingMiddlewareExtensions{   
public static IApplicationBuilder UseTransactionLinking(this IApplicationBuilder builder)
                  {        
return builder.UseMiddleware<TransactionLinkingMiddleware>();
}
 
}

Startup.cs

public Startup(IConfiguration configuration, IHostingEnvironment env)
{   
Configuration = configuration;    env.ConfigureNLog("NLog.config");
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory,    IApplicationLifetime applicationLifetime)
{
if (env.IsDevelopment())
{       
app.UseDeveloperExceptionPage();
}
app.UseTransactionLinking();
loggerFactory.AddNLog();
app.UseMvc();
}

NLog.config

<?xml version="1.0" encoding="utf-8" ?><nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"> 
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<targets>
<target xsi:type="File" name="File"
fileName="${basedir}/logs/log.txt"
layout="TimeStamp=${longdate} Level=${uppercase:${level}} Transaction=${aspnet-TraceIdentifier} Message=${message}" />
</
targets> 
<rules>
<logger name="*" minlevel="Debug" writeTo="File" />
</rules>
</nlog> 

NLog.Web and NLog.Web.AspNetCore packages need to be installed https://github.com/NLog/NLog.Web

Tuesday, 6 February 2018

Span the best part of the .net core 2.1 roadmap

The newly announced .net core 2.1 performance enhancements in build time and Http Client are great, but the best addition is the Span<T> and Memory<T> types in C# 7.2 that follow the low memory allocation fashion started with ValueTask<T> in C#7.
The .net environment has became one of the top contenders performance-wise, and although this new features won't probably be extensively used by most .net developers; now, I can only think of all the services where I could have or will use them.

Sunday, 21 January 2018

Asynchronously wait for Task to complete with timeout

This week I found the following code in Stack Overflow to await for the completion of an async operation with a timeout and really liked the solution.

  int timeout = 1000;
  var task = SomeOperationAsync();
  if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
      // task completed within timeout
  } else {
      // timeout logic  
  }

Monday, 9 October 2017

C# 7 value tuples and enumerables

Today I found myself fighting with Visual Studio about how to check if the result of a FirstOrDefault operation on a list of a value type was null. Tried all the following and nothing worked, even with several results from stack overflow.
I created a quick test harness to try to find a "solution" to my problem:

My first reflex was to check if it was null as we usually do with generic lists of non value types.


Then I realized that I was so used to work with enumerables of reference types that I had completely overlooked the name of this new types  value tuple, so I tried to check for defaults.So I tried with default, default of value type and default of tuple, none of them work.



For this last one I also switched from C# 7 to 7.1, but the compiler continued complaining.


After a bit of google I noticed that I was not the only one with this kind of problem as it seems that the new value tuples don't play well with enumerable just yet. So I went back to use reference types for this case as the solution I found is far from elegant and error prone:


Sunday, 1 October 2017

DateTime.UTCNow please

Last week at work we were migrating some servers to a new network/virtual infrastructure. The migration is going to be gradual, so this time we were moving only services in four boxes out of a pool of more than twenty.
A couple of guys in the team and myself woke up early to do the deployment and as far we could tell everything was OK, the services in the new boxes were processing requests and there was almost no downtime.
We were not aware of this at first, but at that time one of the DevOps found out that the services in the new boxes were not writing anything to splunk; and after some investigation he found out that the new windows servers had the timezone set to BST unlike the other existing servers that were set to UTC. So he quickly changed those servers and the terraform template to UTC, job done, time for breakfast...
Not quite, after a while one of the QAs noticed that the times in some of the websites were jumping back and forth one hour. Thankfully we still are in daylight saving time, if this had happened during the winter we would not have noticed until Spring, and by then the investigation would have been so much more difficult because the lack of context.
The guys couldn't understand what was going on, all the servers were set to use UTC (we didn't know that the timezone had been changed few minutes ago). Fortunately it wasn't the first time I saw something like that, so logged to one of the boxes and checked the windows event viewer, and there it was, the timezone change. Restarted the services and after forcing some updates in the affected entities everything was fine again.
Going back home I remembered reading about this in the great book CLR via c#, processes and threads hold to their own locale. So I wrote an small program to write DateTime.Now and Date time.Now in a loop, as I know that writing it will help me remember it quickly next time.

This is the output with the timezone set to BST.


And this is the output with the timezone set to UTC again, note that the first instance still uses BST, while the new instance has picked up the update.



Now is time to address this technical debt, we have to use DateTime.UTCNow everywhere in the backend and also send dates with timezone between services and frontend to avoid this kind of problems.