Skip to content

Commit

Permalink
Move RequestIdentifierFeature to HttpContext to allow lighter caching
Browse files Browse the repository at this point in the history
Expose TraceIdentifier on Httpcontext
Also resolves aspnet#412
  • Loading branch information
benaadams committed Oct 10, 2015
1 parent fdb3d54 commit 8caf9c1
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/Microsoft.AspNet.Http.Abstractions/HttpContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public abstract class HttpContext : IDisposable

public abstract ISession Session { get; set; }

public abstract string TraceIdentifier { get; set; }

public abstract void Abort();

public abstract void Dispose();
Expand Down
19 changes: 19 additions & 0 deletions src/Microsoft.AspNet.Http/DefaultHttpContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ private ISessionFeature SessionFeature
_session = value;
}
}
private IHttpRequestIdentifierFeature RequestIdentifierFeature
{
get {
return FeatureHelpers.GetOrCreate(
this,
_features,
() => new DefaultHttpRequestIdentifierFeature());
}
set
{
_features.Set(value);
}
}

public override IFeatureCollection Features { get { return _features; } }

Expand Down Expand Up @@ -167,6 +180,12 @@ public override CancellationToken RequestAborted
set { LifetimeFeature.RequestAborted = value; }
}

public override string TraceIdentifier
{
get { return RequestIdentifierFeature.TraceIdentifier; }
set { RequestIdentifierFeature.TraceIdentifier = value; }
}

public override ISession Session
{
get
Expand Down
64 changes: 64 additions & 0 deletions src/Microsoft.AspNet.Http/DefaultHttpRequestIdentifierFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Threading;

namespace Microsoft.AspNet.Http.Features.Internal
{
public class DefaultHttpRequestIdentifierFeature : HttpRequestIdentifierFeature, IHttpRequestIdentifierFeature
{
// Base64 encoding - but in ascii sort order for easy text based sorting
private static readonly string _encode32Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
// Seed the _requestId for this application instance with
// the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001
// for a roughly increasing _requestId over restarts
private static long _requestId = DateTime.UtcNow.Ticks;

private string _id = null;

public override string TraceIdentifier
{
get
{
// Don't incur the cost of generating the request ID until it's asked for
if (_id == null)
{
_id = GenerateRequestId(Interlocked.Increment(ref _requestId));
}
return _id;
}
set
{
_id = value;
}
}

private static unsafe string GenerateRequestId(long id)
{
// The following routine is ~310% faster than calling long.ToString() on x64
// and ~600% faster than calling long.ToString() on x86 in tight loops of 1 million+ iterations
// See: https://github.com/aspnet/Hosting/pull/385

// stackalloc to allocate array on stack rather than heap
char* charBuffer = stackalloc char[13];

charBuffer[0] = _encode32Chars[(int)(id >> 60) & 31];
charBuffer[1] = _encode32Chars[(int)(id >> 55) & 31];
charBuffer[2] = _encode32Chars[(int)(id >> 50) & 31];
charBuffer[3] = _encode32Chars[(int)(id >> 45) & 31];
charBuffer[4] = _encode32Chars[(int)(id >> 40) & 31];
charBuffer[5] = _encode32Chars[(int)(id >> 35) & 31];
charBuffer[6] = _encode32Chars[(int)(id >> 30) & 31];
charBuffer[7] = _encode32Chars[(int)(id >> 25) & 31];
charBuffer[8] = _encode32Chars[(int)(id >> 20) & 31];
charBuffer[9] = _encode32Chars[(int)(id >> 15) & 31];
charBuffer[10] = _encode32Chars[(int)(id >> 10) & 31];
charBuffer[11] = _encode32Chars[(int)(id >> 5) & 31];
charBuffer[12] = _encode32Chars[(int)id & 31];

// string ctor overload that takes char*
return new string(charBuffer, 0, 13);
}
}
}
15 changes: 15 additions & 0 deletions src/Microsoft.AspNet.Http/Features/FeatureHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ public static T GetAndCache<T>(
return obj;
}

public static T GetOrCreate<T>(
IFeatureCache cache,
IFeatureCollection features,
Func<T> factory)
{
T obj = features.Get<T>();
if (obj == null)
{
obj = factory();
features.Set(obj);
}

return obj;
}

public static T GetOrCreateAndCache<T>(
IFeatureCache cache,
IFeatureCollection features,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace Microsoft.AspNet.Http.Features.Internal
{
public class HttpRequestIdentifierFeature : IHttpRequestIdentifierFeature
{
public string TraceIdentifier { get; set; }
public virtual string TraceIdentifier { get; set; }
}
}
3 changes: 2 additions & 1 deletion src/Microsoft.AspNet.Http/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"url": "git://github.com/aspnet/httpabstractions"
},
"compilationOptions": {
"warningsAsErrors": true
"warningsAsErrors": true,
"allowUnsafe": true
},
"dependencies": {
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
Expand Down

0 comments on commit 8caf9c1

Please sign in to comment.