public async Task<bool> StoreHourlyStatsAsync(StatsSensorState statsRecord) { var result = await _client.CreateDocumentAsync(_statsCollectionUri, statsRecord); if(result.StatusCode != HttpStatusCode.Created) _logger.Error($"Document was not stored. The returned status code was {result.StatusCode} for the document:\n{JsonConvert.SerializeObject(statsRecord, Formatting.Indented)}"); return result.StatusCode == HttpStatusCode.Created; }
/// <summary> /// Gets the starting hour for which the statistics will be calculated. /// </summary> /// <param name="latestStatsRecord">The latest (most recent) stats record.</param> /// <param name="oldestSensorHistory">The oldest sensor history.</param> private DateTime? getStartingHour(StatsSensorState latestStatsRecord, Lazy<SensorStateHistory> oldestSensorHistory) { if (latestStatsRecord == null) { // no previously generated statistics for this sensor => get the very first history record if (oldestSensorHistory.Value == null) return null; return new DateTime( oldestSensorHistory.Value.StateChangedTimestamp.Year, oldestSensorHistory.Value.StateChangedTimestamp.Month, oldestSensorHistory.Value.StateChangedTimestamp.Day, oldestSensorHistory.Value.StateChangedTimestamp.Hour, 0, 0, DateTimeKind.Utc); } else { return latestStatsRecord.TimeStampHourResolution.AddHours(1); } }
/// <summary> /// Generates the hourly stats for sensors. /// </summary> /// <param name="now">Current time.</param> /// <returns>Amount os sensors for whom stats were produced</returns> public async Task<int> GenerateHourlyStats(DateTime now) { var recordsGenerated = 0; foreach (var metaClient in _clientsCollection.GetClients()) { foreach (var metaSensor in metaClient.Sensors) { // get previous stats written for this sensor (if any) var previousStats = _statsCollection.GetLatestStatsRecord(metaClient.ClientId, metaSensor.sensorId); // get a starting time of the hour for which stats will be generated var oldestSensorHistory = new Lazy<SensorStateHistory>(() => _sensorsHistory.GetOldestHistoryRecord(metaClient.ClientId, metaSensor.sensorId)); var startingHour = getStartingHour(previousStats, oldestSensorHistory); if (startingHour == null) { _logger.Log($"Sensor {metaSensor.sensorId} in client {metaClient.ClientId} doesn't have any history records"); continue; } if (startingHour.Value.AddHours(1) > now) // too soon to generate stats for this hour continue; // get the actual history records for the given hour // note, there could be no records - sensor was offline the entire hour var clientsHistoryRecords = _clientsHistory.GetHourHistory(metaClient.ClientId, startingHour.Value); var sensorsHistoryRecords = _sensorsHistory.GetHourHistory(metaClient.ClientId, metaSensor.sensorId, startingHour.Value); // get last history records used when calculating previous hour ClientStateHistory previousClientHistory = null; if (previousStats != null && previousStats.ClientPreviousHistoryRecordRowKey != null) previousClientHistory = _clientsHistory.Get($"{metaClient.ClientId}", previousStats.ClientPreviousHistoryRecordRowKey); SensorStateHistory previousSensorHistory = null; if (previousStats != null && previousStats.SensorPreviousHistoryRecordRowKey != null) previousSensorHistory = _sensorsHistory.Get($"{metaClient.ClientId}-{metaSensor.sensorId}", previousStats.SensorPreviousHistoryRecordRowKey); // calculate statistics for the new stats record var newStats = new StatsSensorState { ClientId = metaClient.ClientId, SensorId = metaSensor.sensorId, TimeStampHourResolution = startingHour.Value, States = calculateHourlyStats(clientsHistoryRecords, sensorsHistoryRecords, previousClientHistory, previousSensorHistory) }; // preserve the reference to the last history record used for calculating this stats record newStats.ClientPreviousHistoryRecordRowKey = clientsHistoryRecords.LastOrDefault()?.RowKey ?? previousStats?.ClientPreviousHistoryRecordRowKey; newStats.SensorPreviousHistoryRecordRowKey = sensorsHistoryRecords.LastOrDefault()?.RowKey ?? previousStats?.SensorPreviousHistoryRecordRowKey; if (await _statsCollection.StoreHourlyStatsAsync(newStats)) recordsGenerated++; } } return recordsGenerated; }
public Task<bool> StoreHourlyStatsAsync(StatsSensorState statsRecord) { throw new NotImplementedException(); }