| 90 | } |
| 91 | |
| 92 | pub async fn save(name: &str, record: &Record, aggregations: &[Aggregation]) -> Result<()> { |
| 93 | if record.metrics.is_empty() { |
| 94 | return Ok(()); |
| 95 | } |
| 96 | |
| 97 | let mut pipe = redis::pipe(); |
| 98 | pipe.atomic(); |
| 99 | |
| 100 | for a in aggregations { |
| 101 | let ttl = get_ttl(*a); |
| 102 | |
| 103 | let ts: NaiveDateTime = match a { |
| 104 | Aggregation::MINUTE => { |
| 105 | NaiveDate::from_ymd_opt(record.time.year(), record.time.month(), record.time.day()) |
| 106 | .ok_or_else(|| anyhow!("Invalid date"))? |
| 107 | .and_hms_opt(record.time.hour(), record.time.minute(), 0) |
| 108 | .ok_or_else(|| anyhow!("Invalid time"))? |
| 109 | } |
| 110 | Aggregation::HOUR => { |
| 111 | NaiveDate::from_ymd_opt(record.time.year(), record.time.month(), record.time.day()) |
| 112 | .ok_or_else(|| anyhow!("Invalid date"))? |
| 113 | .and_hms_opt(record.time.hour(), 0, 0) |
| 114 | .ok_or_else(|| anyhow!("Invalid time"))? |
| 115 | } |
| 116 | Aggregation::DAY => { |
| 117 | NaiveDate::from_ymd_opt(record.time.year(), record.time.month(), record.time.day()) |
| 118 | .ok_or_else(|| anyhow!("Invalid date"))? |
| 119 | .and_hms_opt(0, 0, 0) |
| 120 | .ok_or_else(|| anyhow!("Invalid time"))? |
| 121 | } |
| 122 | Aggregation::MONTH => { |
| 123 | NaiveDate::from_ymd_opt(record.time.year(), record.time.month(), 1) |
| 124 | .ok_or_else(|| anyhow!("Invalid date"))? |
| 125 | .and_hms_opt(0, 0, 0) |
| 126 | .ok_or_else(|| anyhow!("Invalid time"))? |
| 127 | } |
| 128 | }; |
| 129 | |
| 130 | let key = get_key(name, *a, ts); |
| 131 | |
| 132 | for (k, v) in &record.metrics { |
| 133 | // Passing a reference to hincr will return a runtime error. |
| 134 | let k = k.clone(); |
| 135 | let v = *v; |
| 136 | |
| 137 | match record.kind { |
| 138 | Kind::COUNTER => { |
| 139 | pipe.cmd("HSET").arg(&key).arg(k).arg(v).ignore(); |
| 140 | } |
| 141 | Kind::ABSOLUTE => { |
| 142 | pipe.cmd("HINCRBYFLOAT").arg(&key).arg(k).arg(v).ignore(); |
| 143 | } |
| 144 | Kind::GAUGE => { |
| 145 | pipe.cmd("HINCRBYFLOAT") |
| 146 | .arg(&key) |
| 147 | .arg(format!("_{}_count", k)) |
| 148 | .arg(1.0) |
| 149 | .ignore(); |