Parses timestamped metric lines. Given metrics lines like: 2017-10-25 10:08:30.961510 87d5562a5fe0ea075ebb2efb0300d10d23bfa474645bb464d222976ed872df2a cpu user 33 system 15 Returns an iterable of (ts, container, user_cpu, system_cpu). It also updates container.peak_total_rss and c
(self, f)
| 235 | return [(container.name,) + split_timestamp(line) for line in interesting_lines] |
| 236 | |
| 237 | def parse_metrics(self, f): |
| 238 | """Parses timestamped metric lines. |
| 239 | |
| 240 | Given metrics lines like: |
| 241 | |
| 242 | 2017-10-25 10:08:30.961510 87d5562a5fe0ea075ebb2efb0300d10d23bfa474645bb464d222976ed872df2a cpu user 33 system 15 |
| 243 | |
| 244 | Returns an iterable of (ts, container, user_cpu, system_cpu). It also updates |
| 245 | container.peak_total_rss and container.total_user_cpu and container.total_system_cpu. |
| 246 | """ |
| 247 | prev_by_container = {} |
| 248 | peak_rss_by_container = {} |
| 249 | for line in f: |
| 250 | ts, rest = split_timestamp(line.rstrip()) |
| 251 | total_rss = None |
| 252 | try: |
| 253 | container, metric_type, rest2 = rest.split(" ", 2) |
| 254 | if metric_type == "cpu": |
| 255 | _, user_cpu_s, _, system_cpu_s = rest2.split(" ", 3) |
| 256 | elif metric_type == "memory": |
| 257 | memory_metrics = rest2.split(" ") |
| 258 | total_rss = int(memory_metrics[memory_metrics.index("total_rss") + 1 ]) |
| 259 | except: |
| 260 | logging.warning("Skipping metric line: %s", line) |
| 261 | continue |
| 262 | |
| 263 | if total_rss is not None: |
| 264 | peak_rss_by_container[container] = max(peak_rss_by_container.get(container, 0), |
| 265 | total_rss) |
| 266 | continue |
| 267 | |
| 268 | prev_ts, prev_user, prev_system = prev_by_container.get( |
| 269 | container, (None, None, None)) |
| 270 | user_cpu = int(user_cpu_s) |
| 271 | system_cpu = int(system_cpu_s) |
| 272 | if prev_ts is not None: |
| 273 | # Timestamps are seconds since the epoch and are floats. |
| 274 | dt = ts - prev_ts |
| 275 | assert type(dt) == float |
| 276 | if dt != 0: |
| 277 | yield ts, container, (user_cpu - prev_user) // dt // USER_HZ,\ |
| 278 | (system_cpu - prev_system) // dt // USER_HZ |
| 279 | prev_by_container[container] = ts, user_cpu, system_cpu |
| 280 | |
| 281 | # Now update container totals |
| 282 | for c in self.containers: |
| 283 | if c.id in prev_by_container: |
| 284 | _, u, s = prev_by_container[c.id] |
| 285 | c.total_user_cpu, c.total_system_cpu = u // USER_HZ, s // USER_HZ |
| 286 | if c.id in peak_rss_by_container: |
| 287 | c.peak_total_rss = peak_rss_by_container[c.id] |
| 288 | |
| 289 | def create(self, output): |
| 290 | # Read logfiles |