// Copyright (C) 2017-2019 Guillaume Desmottes // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::collections::HashMap; use std::fs::File; use std::process::exit; use colored::*; use gst_log_parser::parse; use gstreamer::ClockTime; use itertools::Itertools; use structopt::StructOpt; #[derive(StructOpt)] #[structopt( name = "ts-diff", about = "Display the timestamp difference between the previous entry from the thread" )] struct Opt { #[structopt(help = "Input log file")] input: String, #[structopt( short = "p", help = "Percentage of the longest entries to highlight", default_value = "1" )] top: usize, #[structopt(short = "s", help = "Sort by decreasing ts difference")] sort: bool, } struct TsEntry { entry: gst_log_parser::Entry, diff: ClockTime, top: bool, } impl TsEntry { fn new(entry: gst_log_parser::Entry, diff: ClockTime) -> TsEntry { TsEntry { entry, diff, top: false, } } fn new_top(e: TsEntry) -> TsEntry { TsEntry { entry: e.entry, diff: e.diff, top: true, } } } fn generate() -> Result { let opt = Opt::from_args(); let input = File::open(opt.input)?; let parsed = parse(input); let mut previous: HashMap = HashMap::new(); // Compute ts diff let entries = parsed.map(|entry| { let diff = match previous.get(&entry.thread) { Some(p) => entry.ts - *p, None => ClockTime::from_seconds(0), }; previous.insert(entry.thread.clone(), entry.ts); TsEntry::new(entry, diff) }); // Sort by ts diff let entries = entries.sorted_by(|a, b| Ord::cmp(&b.diff, &a.diff)); // Mark the top entries let n = entries.len() * opt.top / 100; let entries = entries .into_iter() .enumerate() .map(|(i, e)| if i < n { TsEntry::new_top(e) } else { e }); let entries = if opt.sort { // Sort by decreasing diff entries.sorted_by(|a, b| Ord::cmp(&b.diff, &a.diff)) } else { // Sort by increasing ts entries.sorted_by(|a, b| Ord::cmp(&a.entry.ts, &b.entry.ts)) }; // Display for e in entries { let diff = { if e.top { e.diff.to_string().red().to_string() } else { e.diff.to_string() } }; println!( "{} ({}) {} {:?} {} {}:{}:{}:<{}> {}", e.entry.ts, diff, e.entry.thread, e.entry.level, e.entry.category, e.entry.file, e.entry.line, e.entry.function, e.entry.object.clone().unwrap_or_default(), e.entry.message ); } Ok(true) } fn main() { if generate().is_err() { exit(1); } }