private static void ProcessCounterEmit(CounterEmit emit) { // This is an expensive call, so make sure that we only make it once string counterName = emit.GetCounterName(); int hashCode = CounterInstance.GetCounterHashCode(emit.Name, emit.Dimensions); CounterInstance instance; if (!instanceByNameCache.TryGetValue(counterName, out instance)) { // The counter is not in the cache, so we need to get/create is in the database using (var db = new CounterDatabase()) { if (!TryGetInstanceFromDatabase(emit, hashCode, db, out instance)) { CounterInstanceData counterInstanceData = new CounterInstanceData() { Name = emit.Name, InstanceHashCode = hashCode }; if (counterInstanceData.Dimensions == null) { counterInstanceData.Dimensions = new List <CounterDimensionData>(); } foreach (KeyValuePair <string, string> emitDimension in emit.Dimensions) { counterInstanceData.Dimensions.Add( new CounterDimensionData(emitDimension.Key, emitDimension.Value)); } db.Instances.Add(counterInstanceData); db.SaveChanges(); instance = new CounterInstance(counterInstanceData); } // Add the newly created/retrieved counter instance to the cache // TODO: Where does the TTL go??? instanceByNameCache.TryAdd(counterName, instance); } } long ts = Convert.ToInt64(Math.Floor(emit.Timestamp.Subtract(Epoch).TotalSeconds)); CounterValueSet valueSet; // Check if there is a valueSet for this particular timestamp. If not, add one if (!instance.Values.TryGetValue(ts, out valueSet)) { valueSet = new CounterValueSet(emit.Value, 1); instance.Values.Add(ts, valueSet); return; } valueSet.Sum += emit.Value; valueSet.Count++; }
private static void FlushCountersToDatabase() { DateTime now = DateTime.UtcNow; long timestampThreadhold = Convert.ToInt64(Math.Floor(now.Subtract(Epoch).TotalSeconds)) - 2; using (var db = new CounterDatabase()) { bool valuesAdded = false; foreach (string counterName in instanceByNameCache.Keys) { CounterInstance instance = instanceByNameCache[counterName]; // Push any values older than the threshold into the db and remove from the cache List <long> removeList = new List <long>(); foreach (long timestamp in instance.Values.Keys) { if (timestamp < timestampThreadhold) { CounterValueSet valueSet = instance.Values[timestamp]; db.Values.Add( new CounterValueData() { Count = valueSet.Count, CounterInstanceId = instance.Id, Flags = (int)CounterValueFlags.Aggregate1Second, Timestamp = timestamp, Value = valueSet.Sum }); // Remove the value set from the instance, since we already pushed it to the DB removeList.Add(timestamp); valuesAdded = true; } } foreach (long timestamp in removeList) { instance.Values.Remove(timestamp); } if (instance.CacheExpiryDateTime < now && !instance.Values.Any()) { instanceByNameCache.TryRemove(counterName, out CounterInstance _); } } if (valuesAdded) { db.SaveChanges(); } } }