26

log4net 1.2.11.0

I am trying to get anything that will allow me to log with a unique value for each ASP.NET request.

I tried %thread, but threads appear to be reused.

I've tried %aspnet-request and %aspnet-session which don't have anything meaningful within them.

I looked at ThreadContext.Properties and LogicalThreadContext.Properties but they don't have anything in them either.

Anyone have a trick to get this done? I need the ability to pick a particular request's logs out of the log file.

LiteWait
  • 584
  • 4
  • 21
  • 42
  • That isn't helpful. A method I have that I hope works is to have an thread interlocked counter and I use that to set the thread name on each request and %thread seems to output correctly. This is making the huge assumption that my request runs end to end on a single thread. – LiteWait Apr 06 '13 at 13:57
  • Even worse since things run on a thread pool you can only set the Thread Name once! (strangely this seems to work on .Net and fails on Mono) – LiteWait Apr 06 '13 at 14:27
  • 1
    You can implement a httpmodule which intercepts every request and adds a guid to context then all logs in that request will be logged with the same unique id. – adt Apr 12 '13 at 19:39
  • Actually yes, but I am using .asmx SOAP services and the only place I think I can get at this is via a SoapExtension. – LiteWait Apr 13 '13 at 00:12

4 Answers4

23

.asmx files will still call Application_BeginRequest event where you can store your unique GUID in HttpContext.Current.Items (using this collection avoid the odd problem when the request processing jumps threads). Only if you were using WCF (and also then it depends on configuration) this would not work.

If you would like not to touch the application itself, you can use HttpContext.Current.Timestamp that returns the time when the request processing started. Join that with your existing approach of getting the ID of the thread and you will get a unique value.

Knaģis
  • 20,827
  • 7
  • 66
  • 80
10

HttpContext.Current.Items - is a good idea.

Try to add something like thit:

HttpContext.Current.Items.Add("RequestIdentity", Guid.NewGuid().ToString())

In .NET Core you can access it this way (from your controllers) HttpContext.Items and using HttpContextAccessor from anywhere else.

All the details here.

Andrei
  • 42,814
  • 35
  • 154
  • 218
6

clock tick + process ID + thread ID as stored when your request starts should be sufficient, I think (assuming each thread handles 1 request at a time).

Mark Leighton Fisher
  • 5,609
  • 2
  • 18
  • 29
2

Here's some extension methods that I created for this purpose:

public static Guid GetId(this HttpContext ctx) => new HttpContextWrapper(ctx).GetId();

public static Guid GetId(this HttpContextBase ctx)
{
    const string key = "tq8OuyxHpDgkRg54klfpqg== (Request Id Key)";

    if (ctx.Items.Contains(key))
        return (Guid) ctx.Items[key];

    var mutex = string.Intern($"{key}:{ctx.GetHashCode()}");
    lock (mutex)
    {
        if (!ctx.Items.Contains(key))
            ctx.Items[key] = Guid.NewGuid();

        return (Guid) ctx.Items[key];
    }
}
Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346