Detect if Web API request is served by cache

时间:2016-05-13 15:33:11

标签: asp.net asp.net-web-api2 outputcache

We have a Web API 2 application that is using Strathweb.CacheOutput.WebApi2 for caching.

Short question: Is there a way to detect in Application_LogRequest (or anywhere, really) whether a request was served by cache?

Long question: Lately, we've been looking at performance and seeing which API calls we can improve. I pulled a list from our logs (which includes duration) to see what the worst offenders are. By worst offenders, I mean the longest average durations and/or the most number of calls.

But the numbers are misleading because the cached requests are included in the stats. Cached requests are usually served in half a second or less, so they pull average durations down. Also, if a particular call is being made, say 1000 times a minute, but 999 of those are cached, I don't really care.

So I'd like to add a flag in my log that indicates whether the request was served by the cache, so I can exclude those. All our logging is done in the Application_LogRequest event. But even if I can detect it somewhere else, I can store a value in HttpContext.Current.Items that I can retrieve later.

1 个答案:

答案 0 :(得分:1)

Strathweb CacheOutputAttribute不会在http响应或其他地方添加一些可靠的信息,以便知道响应是否是从缓存中提供的。

您可以从中获取,然后用您自己替换CacheOutputAttribute的所有用途。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class YourCustomizedCacheOutputAttribute : CacheOutputAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        base.OnActionExecuting(actionContext);
        // If response is set, it has been retrieved from cache.
        actionContext.Request.Properties["yourCacheHitKey"] = 
            actionContext.Response != null;
    }
}

当然,如果您登录的地方无法访问,请使用HttpRequestMessage.Properties之外的其他内容。

您可以通过示例添加一些自定义标头作为回应,如果泄露给浏览器不是您的问题:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class YourCustomizedCacheOutputAttribute : CacheOutputAttribute
{
    // "X-" prefix is deprecated, but the rational behind this is about wannabe
    // standard header. I do not intend this one to become standard for anything.
    private const string _cacheHeader = "X-Cache";
    protected override void ApplyCacheHeaders(HttpResponseMessage response,
        CacheTime cacheTime)
    {
        base.ApplyCacheHeaders(response, cacheTime);

        if (response.Headers.Contains(_cacheHeader))
            return;

        // At this point, we do not know. miss by default.
        response.Headers.Add(_cacheHeader, "miss");
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        base.OnActionExecuting(actionContext);
        if (actionContext.Response == null)
            return;

        // Response has been retrieved from cache.
        // Headers.Remove does not fail if not already there.
        response.Headers.Remove(_cacheHeader);
        actionContext.Response.Headers.Add(_cacheHeader, "hit");
    }
}