import re
import argparse
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
from pathlib import Path
def parse_args():
parser = argparse.ArgumentParser(description='Latency log analyzer with tag support')
parser.add_argument('--log', required=True,
help='Input log file path')
parser.add_argument('--output-img', default='latency_by_tag.png',
help='Output image path (default: latency_by_tag.png)')
parser.add_argument('--output-report',
help='Output report file path (optional)')
return parser.parse_args()
def parse_log_line(line):
pattern = r"\[TAG=([^$$]+)\]\[TS=(\d+)\]\[LAT=(\d+)us\]"
if match := re.search(pattern, line):
return {
"tag": match.group(1),
"timestamp": datetime.fromtimestamp(int(match.group(2))/1e9),
"latency": int(match.group(3))
}
return None
def load_log_data(log_path):
try:
with open(log_path, 'r') as f:
records = []
for line in f:
if record := parse_log_line(line.strip()):
records.append(record)
return pd.DataFrame(records)
except FileNotFoundError:
raise SystemExit(f"Error: Log file {log_path} not found")
def generate_latency_plot(df, output_path):
plt.figure(figsize=(15, 8))
colors = plt.cm.tab10.colors
for idx, (tag, group) in enumerate(df.groupby('tag')):
group = group.sort_values('timestamp')
plt.plot(group['timestamp'], group['latency'],
color=colors[idx % 10],
marker='o', markersize=3,
linestyle='-', linewidth=1,
label=tag)
plt.title('Latency Timeline by Tag')
plt.xlabel('Timestamp')
plt.ylabel('Latency (μs)')
plt.legend(loc='upper left', bbox_to_anchor=(1, 1))
plt.grid(True, alpha=0.3)
plt.xticks(rotation=45)
plt.tight_layout()
Path(output_path).parent.mkdir(parents=True, exist_ok=True)
plt.savefig(output_path, dpi=300, bbox_inches='tight')
plt.close()
def generate_stat_report(df, output_path=None):
stats = []
for tag, group in df.groupby('tag'):
desc = group['latency'].describe(percentiles=[.5, .95, .99])
stats.append({
'Tag': tag,
'Count': desc['count'],
'Mean': desc['mean'],
'Min': desc['min'],
'50%': desc['50%'],
'95%': desc['95%'],
'99%': desc['max'],
'Max': desc['max']
})
report_df = pd.DataFrame(stats)
report_str = report_df.to_string(index=False, float_format='%.2f')
if output_path:
Path(output_path).parent.mkdir(parents=True, exist_ok=True)
with open(output_path, 'w') as f:
f.write("=== Latency Statistics Report ===\n")
f.write(report_str)
print(f"Report saved to {output_path}")
else:
print("\n" + report_str)
def main():
args = parse_args()
df = load_log_data(args.log)
if df.empty:
raise SystemExit("Error: No valid records found in log file")
generate_latency_plot(df, args.output_img)
print(f"Visualization saved to {args.output_img}")
if args.output_report:
generate_stat_report(df, args.output_report)
else:
generate_stat_report(df)
if __name__ == "__main__":
main()