public void TestLogDurationWithMinimum() { if (log == null) { Assert.Inconclusive($"{loggerName} Logger disabled"); } else { var activityID = Guid.NewGuid(); using (var durationLog = new DurationLogger(log, new LogInformation() { ActivityID = activityID, Type = LogType.Debug, Category = "Duration", UserName = "", Message = $"{this.GetType().Name}" }, TimeSpan.FromSeconds(10))) { System.Threading.Thread.Sleep(1000); } using (var db = new VoatDataContext()) { var entry = db.EventLog.FirstOrDefault(x => x.ActivityID == activityID.ToString().ToUpper()); Assert.IsNull(entry, "Should not have log entry with specified minimum"); } } }
public override async Task Invoke(HttpContext context) { var logger = EventLogger.Instance; var logLevel = LogType.Information; var logInfo = context.GetLogInformation("RequestDuration", logLevel); using (var duration = new DurationLogger(logger, logInfo, _timeSpan)) { await base.Invoke(context); } }
public override async Task <T> ExecuteAsync() { T result = default(T); var policy = CachingPolicy; if (policy != null && policy.IsValid) { using (var durationLog = new DurationLogger(EventLogger.Instance, new LogInformation() { Type = LogType.Debug, Origin = Settings.Origin.ToString(), Category = "Duration", UserName = UserName, Message = $"{this.GetType().Name} ({FullCacheKey})" }, TimeSpan.FromSeconds(1))) { CacheHit = true; //If cache is loaded, GetFreshData method will change this to false //Bypass CacheHandler.Register (trouble shooting) //if (!CacheHandler.Instance.Exists(FullCacheKey)) //{ // CacheHit = false; // result = await GetData().ConfigureAwait(false); // if (!result.IsDefault()) // { // CacheHandler.Instance.Replace(FullCacheKey, result, policy.Duration); // } //} //else //{ // CacheHit = true; // result = CacheHandler.Instance.Retrieve<T>(FullCacheKey); //} //Async result = await CacheHandler.Instance.Register <T>(FullCacheKey.ToLower(), new Func <Task <T> >(GetFreshData), CachingPolicy.Duration, CachingPolicy.RefetchLimit); } } else { CacheHit = true; result = await GetFreshData().ConfigureAwait(false); } return(result); }
public void TestLogDuration() { if (log == null) { Assert.Inconclusive("Log4Net Logger disabled"); } else { var activityID = Guid.NewGuid(); using (var durationLog = new DurationLogger(log, new LogInformation() { ActivityID = activityID, Type = LogType.Debug, Category = "Duration", UserName = "", Message = $"{this.GetType().Name}" })) { System.Threading.Thread.Sleep(1000); } using (var db = new voatEntities()) { var entry = db.EventLogs.FirstOrDefault(x => x.ActivityID == activityID.ToString().ToUpper()); Assert.IsNotNull(entry, "Well, that didn't work now did it"); } } }
public void TestLogDuration() { if (log == null) { Assert.Inconclusive($"{loggerName} Logger disabled"); } else { var activityID = Guid.NewGuid(); using (var durationLog = new DurationLogger(log, new LogInformation() { ActivityID = activityID, Type = LogType.Debug, Category = "Duration", UserName = "", Message = $"{this.GetType().Name}", Data = new { testNested = true, doesItWork = "Who knows" } })) { System.Threading.Thread.Sleep(1000); } System.Threading.Thread.Sleep(1000);// batched logger writes on seperate thread, need to wait a bit using (var db = new VoatDataContext()) { var entry = db.EventLog.FirstOrDefault(x => x.ActivityID.ToUpper() == activityID.ToString().ToUpper()); Assert.IsNotNull(entry, "Well, that didn't work now did it"); } } }
/// <summary> /// Registers a function for cache. Locks by key and generates data for return from function /// </summary> /// <param name="key">Unique Cache Keys</param> /// <param name="getData">Function that returns data to be placed in cache</param> /// <param name="cacheTime">The timespan in which to update or remove item from cache</param> /// <param name="refetchLimit">Value indicating refresh behavior. -1: Do not refresh, 0: Unlimited refresh (use with caution), x > 0: Number of times to refresh cached data</param> /// <returns></returns> public async Task <T> Register <T>(string cacheKey, Func <Task <T> > getData, TimeSpan cacheTime, int refetchLimit = -1) { cacheKey = StandardizeCacheKey(cacheKey); //allow devs to turn off local cache for testing if (!CacheEnabled) { return(await getData()); } if (!Exists(cacheKey)) { //Log the duration this takes to pull fresh using (var duration = new DurationLogger(EventLogger.Instance, new LogInformation() { Type = LogType.Debug, Origin = Configuration.VoatSettings.Instance.Origin.ToString(), Category = "Duration", Message = $"Cache Load ({cacheKey})" }, TimeSpan.FromSeconds(1))) { var o = _semaphoreSlimLockStore.GetLockObject(cacheKey); await o.WaitAsync(); try { if (!Exists(cacheKey)) { try { var data = await getData().ConfigureAwait(CONSTANTS.AWAIT_CAPTURE_CONTEXT); if (data != null || data == null && !_ignoreNulls) { EventLogger.Instance.Log(new LogInformation() { Type = LogType.Debug, Category = "Cache", Message = $"Inserting Cache ({cacheKey})", Origin = Configuration.VoatSettings.Instance.Origin.ToString() }); //Debug.WriteLine("Inserting Cache: " + cacheKey); SetItem(cacheKey, data, cacheTime); //Refetch Logic if (RefetchEnabled && refetchLimit >= 0) { _meta[cacheKey] = new RefetchEntryTask <T>(getData) { CacheTime = cacheTime, CurrentCount = 0, MaxCount = refetchLimit }; AddEvictionTracker(cacheKey, new object(), cacheTime.Subtract(_refreshOffset), new PostEvictionDelegate(RefetchItem)); //AddEvictionTracker(cacheKey, new object(), Repository.CurrentDate.Add(cacheTime.Subtract(_refreshOffset)), new PostEvictionDelegate(RefetchItem)); //var cache = System.Runtime.Caching.MemoryCache.Default; //var policy = new CacheItemPolicy() //{ // AbsoluteExpiration = Repository.CurrentDate.Add(cacheTime.Subtract(_refreshOffset)), // UpdateCallback = new CacheEntryUpdateCallback(RefetchItem) //}; //cache.Set(cacheKey, new object(), policy); } else if (RequiresExpirationRemoval) { AddEvictionTracker(cacheKey, new object(), cacheTime, new PostEvictionDelegate(ExpireItem)); //AddEvictionTracker(cacheKey, new object(), Repository.CurrentDate.Add(cacheTime), new PostEvictionDelegate(ExpireItem)); //var cache = System.Runtime.Caching.MemoryCache.Default; //cache.Add(cacheKey, new object(), new CacheItemPolicy() { AbsoluteExpiration = Repository.CurrentDate.Add(cacheTime), RemovedCallback = new CacheEntryRemovedCallback(ExpireItem) }); } } return(data); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); //Cache now supports Tasks which throw aggregates, if agg has only 1 inner, throw it instead var aggEx = ex as AggregateException; if (aggEx != null && aggEx.InnerExceptions.Count == 1) { throw aggEx.InnerException; } else { throw ex; } } } } finally { o.Release(); } } } var cacheItem = GetItem(cacheKey); return(Convert <T>(cacheItem)); }
/// <summary> /// Registers a function for cache. Locks by key and generates data for return from function /// </summary> /// <param name="key">Unique Cache Keys</param> /// <param name="getData">Function that returns data to be placed in cache</param> /// <param name="cacheTime">The timespan in which to update or remove item from cache</param> /// <param name="refetchLimit">Value indicating refetch behavior. -1: Do not refresh, 0: Unlimited refresh (use with caution), x > 0: Number of times to refresh cached data</param> /// <returns></returns> public T Register <T>(string cacheKey, Func <T> getData, TimeSpan cacheTime, int refetchLimit = -1) { cacheKey = StandardizeCacheKey(cacheKey); //allow devs to turn off local cache for testing if (!CacheEnabled) { return(getData()); } if (!Exists(cacheKey)) { ////BLOCK: Temp work around for blocking exploration ////Not thread safe //bool isRefetchRequest = (RefetchEnabled && cacheTime > TimeSpan.Zero && refetchLimit >= 0); //if (!isRefetchRequest) //{ // var data = getData(); // if (data != null || data == null && !_ignoreNulls) // { // SetItem(cacheKey, data, cacheTime); // } // return data; //} //Log the duration this takes to pull fresh using (var duration = new DurationLogger(EventLogger.Instance, new LogInformation() { Type = LogType.Debug, Origin = Configuration.VoatSettings.Instance.Origin.ToString(), Category = "Duration", Message = $"Cache Load ({cacheKey})" }, TimeSpan.FromSeconds(1))) { var sema = _semaphoreSlimLockStore.GetLockObject(cacheKey); sema.Wait(); try { //object o = _lockStore.GetLockObject(cacheKey); //lock (o) //{ if (!Exists(cacheKey)) { try { var data = getData(); if (data != null || data == null && !_ignoreNulls) { EventLogger.Instance.Log(new LogInformation() { Type = LogType.Debug, Category = "Cache", Message = $"Inserting Cache ({cacheKey})", Origin = Configuration.VoatSettings.Instance.Origin.ToString() }); //Debug.WriteLine("Inserting Cache: " + cacheKey); SetItem(cacheKey, data, cacheTime); //Refetch Logic if (RefetchEnabled && refetchLimit >= 0) { _meta[cacheKey] = new RefetchEntryFunc <T>(getData) { CacheTime = cacheTime, CurrentCount = 0, MaxCount = refetchLimit }; AddEvictionTracker(cacheKey, new object(), cacheTime.Subtract(_refreshOffset), new PostEvictionDelegate(RefetchItem)); } else if (RequiresExpirationRemoval) { AddEvictionTracker(cacheKey, new object(), cacheTime, new PostEvictionDelegate(ExpireItem)); //AddEvictionTracker(cacheKey, new object(), Repository.CurrentDate.Add(cacheTime), new PostEvictionDelegate(ExpireItem)); //cache.Add(cacheKey, new object(), new CacheItemPolicy() { AbsoluteExpiration = Repository.CurrentDate.Add(cacheTime), RemovedCallback = new CacheEntryRemovedCallback(ExpireItem) }); } } return(data); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); //Cache now supports Tasks which throw aggregates, if agg has only 1 inner, throw it instead var aggEx = ex as AggregateException; if (aggEx != null && aggEx.InnerExceptions.Count == 1) { throw aggEx.InnerException; } else { throw ex; } } } //} } finally { sema.Release(); } } } var cacheItem = GetItem(cacheKey); return(Convert <T>(cacheItem)); }