001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.log.render.markdown; 020 021import org.jpos.log.LogRenderer; 022import org.jpos.util.Profiler; 023 024import java.io.PrintStream; 025import java.util.Set; 026 027public final class ProfilerMarkdownRenderer implements LogRenderer<Profiler> { 028 public ProfilerMarkdownRenderer() { 029 } 030 031 @Override 032 public void render(Profiler prof, PrintStream ps, String indent) { 033 var events = prof.getEvents(); 034 int width = maxLength(events.keySet()); 035 final String fmt = "| %-" + width + "s | %10.10s | %10.10s |%n"; 036 ps.print (row(fmt, "Checkpoint", "Elapsed", "Total")); 037 ps.print( 038 row(fmt, "-".repeat(width), "---------:", "-------:") 039 ); 040 StringBuilder graph = new StringBuilder(); 041 events.forEach((key, v) -> { 042 ps.print( 043 row(fmt, v.getEventName(), toMillis(v.getDurationInNanos()), toMillis(v.getTotalDurationInNanos())) 044 ); 045 graph.append (" \"%s\" : %s%n".formatted(key, toMillis(v.getDurationInNanos()))); 046 }); 047 ps.println(); 048 ps.println ("```mermaid"); 049 ps.println ("pie title Profiler"); 050 ps.println (graph); 051 ps.println ("```"); 052 053 } 054 public Class<?> clazz() { 055 return Profiler.class; 056 } 057 058 public Type type() { 059 return Type.MARKDOWN; 060 } 061 private String row (String fmt, String c1, String c2, String c3) { 062 return fmt.formatted(c1, c2, c3); 063 } 064 065 private String toMillis(long nanos) { 066 long millis = nanos / Profiler.TO_MILLIS; 067 long fractional = (nanos % Profiler.TO_MILLIS) / (Profiler.TO_MILLIS / 1000); 068 return String.format("%d.%03d", millis, fractional); 069 } 070 private int maxLength (Set<String> keys) { 071 return keys.stream() 072 .mapToInt(String::length) 073 .max() 074 .orElse(0); // R 075 } 076}