/// <summary> /// Record the given value to the given monitor configuration. /// </summary> /// <param name="configName">Name of the config</param> /// <param name="value">Value that is being recorded</param> /// <param name="monitorReductionType">Reduction type that is being used</param> public void Record(string configName, double value, MonitorReductionType monitorReductionType) { Record(configName, DateTime.Now, value, monitorReductionType); }
/// <summary> /// Record the given value to the given monitor configuration, for the given time. /// </summary> /// <param name="configName">Name of the config</param> /// <param name="time">Time of the recrod</param> /// <param name="value">Value that is being recorded</param> /// <param name="monitorReductionType">Reduction type that is being used</param> public void Record(string configName, DateTime time, double value, MonitorReductionType monitorReductionType) { try { configName.ThrowIfNull("configName"); value.ThrowIfNaN("value"); // todo: If this is called too quickly by different threads, there will be a problem.... MonitorInfo monitorInfo = _configSeed.Seed(configName, monitorReductionType); if (monitorInfo == null) throw new Exception("Seed failed to find/create a monitorInfo: \"" + configName + "\""); MonitorConfig monitorConfig = monitorInfo.MonitorConfig; ReduceLevel reduceLevel = monitorInfo.FirstReduceLevel; IReduceMethod<double> reduceMethod = reduceLevel.AggregationClass; IList<MonitorRecord<double>> updateList = monitorInfo.MonitorRecords; MonitorRecord<double> next; lock (updateList) { if (reduceLevel.Resolution == 0) { next = reduceMethod.IntervalAggregate(time, _cache.Empty, value); updateList.Add(next); } else { DateTime timeBin; DateTime recordTime; //The core purpose of this logic is just to group all events into one or more time buckets. //As a result the actual time that the record occurd is irrelevent. The only time that //matters is the first time that occured since the last reduce and even this is rounded //in accordance with the resolution of the reduceLevel. var last = updateList.LastOrDefault(); if (last == null) { //Starting bucket for the events to be aggregated into timeBin = Support.RoundToResolution(time, reduceLevel.Resolution); //As we doing have a previous event to work off recordTime = timeBin.AddMilliseconds((long)(reduceLevel.Resolution / 2)); } else { recordTime = last.TimeStamp; //Since the we didn't keep a record of the original timeBin that was worked out //when "last == null", we need to derive the original timeBin from the recorded TimeStamp. timeBin = recordTime.AddMilliseconds(-(long)(reduceLevel.Resolution / 2)); } //This logic seems off - it will group like items together per timebin but when the //event time changes beyound the threshold of the current timebin, the timebin isn't //the one that matches the event time, its simply one increment from the last timebin if (last != null && time.Ticks < timeBin.AddMilliseconds(reduceLevel.Resolution).Ticks) { next = reduceMethod.IntervalAggregate(recordTime, last, value); updateList[updateList.Count - 1] = next; } else { if (last != null) recordTime = recordTime.AddMilliseconds(reduceLevel.Resolution); next = reduceMethod.IntervalAggregate(recordTime, _cache.Empty, value); updateList.Add(next); } } } } catch (Exception e) { _logger.Fatal("Exception swallowed: ", e); if (_settings.Debug) throw; } }
/// <summary> /// Record the ocurrance of a given monitor configuration. /// </summary> /// <param name="configName">Name of the config</param> /// <param name="monitorReductionType">Reduction type that is being used</param> public void RecordEvent(string configName, MonitorReductionType monitorReductionType) { Record(configName, DateTime.Now, 1.0, monitorReductionType); }
/// <summary> /// Seed the local data for a monitor configuration. /// </summary> /// <param name="configName"></param> /// <param name="monitorReductionType"></param> /// <returns></returns> public MonitorInfo Seed(string configName, MonitorReductionType monitorReductionType) { configName.ThrowIfNull("configName"); monitorReductionType.ThrowIfNull("monitorReductionType"); MonitorInfo monitorInfo = null; bool tablesCreated = false; configName = Support.ValidateConfigName(configName); // Look for static cached data/state (i.e. its already been seeded) if (!_cache.MonitorInfo.TryGetValue(configName, out monitorInfo)) { // Look for an existing monitor configuration MonitorConfig monitorConfig; if (!_cache.MonitorConfigs.TryGetValue(configName, out monitorConfig)) { // Create new monitorconfig record (will get inserted into db during Flush()) var aggregationClassName = monitorReductionType == MonitorReductionType.DefaultAccumulate ? "ZocMonLib.ReduceMethods.ReduceMethodAccumulate" : "ZocMonLib.ReduceMethods.ReduceMethodAverage"; var aggregationClass = _settings.ReduceMethodProvider.Retrieve(aggregationClassName); monitorConfig = new MonitorConfig { Name = configName, MonitorReductionType = monitorReductionType, ReduceLevels = new List<ReduceLevel> { new ReduceLevel { MonitorConfigName = configName, Resolution = 60 * 1000, HistoryLength = 7 * 24 * 60 * 60 * 1000, AggregationClassName = aggregationClassName, AggregationClass = aggregationClass }, new ReduceLevel { MonitorConfigName = configName, Resolution = 5 * 60 * 1000, HistoryLength = 7 * 24 * 60 * 60 * 1000, AggregationClassName = aggregationClassName, AggregationClass = aggregationClass }, new ReduceLevel { MonitorConfigName = configName, Resolution = 60 * 60 * 1000, HistoryLength = 7 * 24 * 60 * 60 * 1000, AggregationClassName = aggregationClassName, AggregationClass = aggregationClass }, new ReduceLevel { MonitorConfigName = configName, Resolution = 24 * 60 * 60 * 1000, HistoryLength = 7 * 24 * 60 * 60 * 1000, AggregationClassName = aggregationClassName, AggregationClass = aggregationClass } } }; } else { // If this monitor already exists in monitorconfigs, we know the tables have already been created tablesCreated = true; } // Don't validate custom configs (as they could be anything....) if (!MonitorReductionType.Custom.Equals(monitorReductionType)) { if (!monitorReductionType.Equals(monitorConfig.MonitorReductionType)) throw new DataException("Wrong reduction type for monitor \"" + configName + "\""); } // WTF why only the first var reduceLevel = monitorConfig.ReduceLevels.First(); monitorInfo = new MonitorInfo { MonitorConfig = monitorConfig, FirstReduceLevel = reduceLevel, MonitorRecords = new List<MonitorRecord<double>>(), TablesCreated = tablesCreated }; _cache.MonitorInfo.AddOrUpdate(configName, monitorInfo, (key, oldValue) => monitorInfo); } return monitorInfo; }
/// <summary> /// Seed the local data for a monitor configuration. /// </summary> /// <param name="configName"></param> /// <param name="monitorReductionType"></param> /// <returns></returns> public static MonitorInfo Seed(string configName, MonitorReductionType monitorReductionType) { return Settings.ConfigSeed.Seed(configName, monitorReductionType); }
/// <summary> /// Record the ocurrance of a given monitor configuration. /// </summary> /// <param name="configName">Name of the config</param> /// <param name="monitorReductionType">Reduction type that is being used</param> public static void RecordEvent(string configName, MonitorReductionType monitorReductionType) { Settings.Recorder.RecordEvent(configName, monitorReductionType); }
/// <summary> /// Record the given value to the given monitor configuration, for the given time. /// </summary> /// <param name="configName">Name of the config</param> /// <param name="time">Time of the recrod</param> /// <param name="value">Value that is being recorded</param> /// <param name="monitorReductionType">Reduction type that is being used</param> public static void Record(string configName, DateTime time, double value, MonitorReductionType monitorReductionType) { Settings.Recorder.Record(configName, time, value, monitorReductionType); }