using System; using System.Collections.Generic; using System.Linq; // ReSharper disable PossibleInvalidOperationException namespace Monithor.api.Monitors { public class IcmpMonitor : IMonitor { private readonly string _server; public string Identifier { get; set; } public IcmpMonitor(string identifier, string server) { Identifier = identifier; _server = server; } public string LastValue { get; set; } public DateTime StartedAt { get; set; } public DateTime ResolvedAt { get; set; } public MonitorStatus Status { get; set; } public string Message { get; set; } public IEnumerable GetFluxItems(Influx influx, string timespan) { var query = $"from(bucket: \"{influx.Bucket}\")" + $"|> range(start: -5m)" + $"|> filter(fn: (r) => r[\"_measurement\"] == \"ping\")" + $"|> filter(fn: (r) => r[\"url\"] == \"{_server}\")" + $"|> keep(columns:[\"_field\", \"_time\", \"_value\"])" + $"|> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")" + $"|> sort(columns: [\"_time\"], desc: false)"; var result = influx.Client.GetQueryApi().QueryAsync(query, influx.Org).Result; return (from table in result from record in table.Records select new FluxItem { Time = record.GetTime().Value, Status = record.GetValueByKey("percent_packet_loss") + "%", Message = (Math.Ceiling((double) (record.GetValueByKey("percentile50_ms") ?? -1d)) + " ms").Replace("-1 ms", "n/a") }).ToList(); } public bool Update(IEnumerable data) { if (!data.Any()) { if (Status == MonitorStatus.Down) return false; Status = MonitorStatus.Down; return true; } if (Status == MonitorStatus.Unknown) { Status = MonitorStatus.Up; } var anyDown = data.Any(p => p.Status != "0%"); var allDown = data.All(p => p.Status != "0%"); LastValue = data.Last().Status + " loss"; Message = data.Last().Message; switch (Status) { case MonitorStatus.Down when anyDown && !allDown: Status = MonitorStatus.Recovering; ResolvedAt = DateTime.Now; return true; case MonitorStatus.Down when allDown: return false; case MonitorStatus.Down: Status = MonitorStatus.Up; return true; case MonitorStatus.Validating when anyDown && !allDown: return false; case MonitorStatus.Validating when allDown: Status = MonitorStatus.Down; return true; case MonitorStatus.Validating: Status = MonitorStatus.Up; return false; case MonitorStatus.Recovering when anyDown && !allDown: return false; case MonitorStatus.Recovering when allDown: Status = MonitorStatus.Down; return true; case MonitorStatus.Recovering: Status = MonitorStatus.Up; return true; case MonitorStatus.Up when anyDown && !allDown: Status = MonitorStatus.Validating; StartedAt = DateTime.Now; return false; case MonitorStatus.Up when allDown: Status = MonitorStatus.Down; StartedAt = DateTime.Now; return true; case MonitorStatus.Up: return false; default: Status = MonitorStatus.Up; return false; } } } }