package org.sef4j.testwebapp.service; import java.io.Closeable; import org.sef4j.callstack.CallStackElt.StackPopper; import org.sef4j.callstack.CallStackPushPopHandler; import org.sef4j.callstack.LocalCallStack; import org.sef4j.callstack.handlers.CallTreeStatsUpdaterCallStackHandler; import org.sef4j.callstack.stats.ThreadTimeUtils; import org.sef4j.callstack.stats.helpers.PerfStatsDTOMapperUtils; import org.sef4j.callstack.stats.helpers.PropTreeNodeDTOPrinter; import org.sef4j.core.helpers.proptree.dto.PropTreeNodeDTO; import org.sef4j.core.helpers.proptree.model.PropTreeNode; import org.sef4j.core.helpers.proptree.model.PropTreeNodeDTOMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Component public class MetricsStatsTreeRegistry { private static final Logger LOG = LoggerFactory.getLogger(MetricsStatsTreeRegistry.class); private static final PropTreeNode rootWSStatsNode = PropTreeNode.newRoot(); public static PropTreeNode getRootWSStatsNode() { return rootWSStatsNode; } private PropTreeNodeDTOMapper defaultPropTreeNodeDTOMapper = PerfStatsDTOMapperUtils.createDTOMapper(); private PropTreeNodeDTOMapper pendingPropTreeNodeDTOMapper = PerfStatsDTOMapperUtils.createPendingCountFilterDTOMapper(0); // ------------------------------------------------------------------------ public MetricsStatsTreeRegistry() { } public PropTreeNodeDTO findAll() { LOG.info("findAll"); PropTreeNodeDTO res = defaultPropTreeNodeDTOMapper.map(rootWSStatsNode); return res; } public PropTreeNodeDTO findFilterByMin( int filterMinPendingCount, int filterMinCount, long filterMinSumElapsed, long filterMinSumThreadUserTime, long filterMinSumThreadCpuTime ) { LOG.info("findFilterByMin"); PropTreeNodeDTOMapper mapper = PerfStatsDTOMapperUtils.createDTOMapper( filterMinPendingCount, filterMinCount, filterMinSumElapsed, filterMinSumThreadUserTime, filterMinSumThreadCpuTime); PropTreeNodeDTO res = mapper.map(rootWSStatsNode); return res; } @RequestMapping(value="pendingCount", method=RequestMethod.GET) public PropTreeNodeDTO findAllPending() { PropTreeNodeDTO res = pendingPropTreeNodeDTOMapper.map(rootWSStatsNode); long clockNanos = ThreadTimeUtils.getTime(); long clockMillis = ThreadTimeUtils.nanosToMillis(clockNanos); // System.currentTimeMillis(); res.putProp("clockNanos", clockNanos); res.putProp("clockMillis", clockMillis); long timeNowMillis = System.currentTimeMillis(); res.putProp("timeNowMillis", timeNowMillis); LOG.debug("findAllPending => \n" + PropTreeNodeDTOPrinter.recursiveDumpPendingCount(res)); return res; } public PropTreeNode getPropTreeNodeByPathOrNull(String[] path) { return rootWSStatsNode.getChildByPathOrNull(path); } // ------------------------------------------------------------------------ public static StatsHandlerPopper pushTopLevelStats(String className, String categoryMethod, String methodName) { CallTreeStatsUpdaterCallStackHandler threadCallTreeWSStatsHandler = new CallTreeStatsUpdaterCallStackHandler(rootWSStatsNode); return new StatsHandlerPopper(threadCallTreeWSStatsHandler, className, categoryMethod, methodName); } public static class StatsHandlerPopper implements Closeable { CallStackPushPopHandler popHandler; StackPopper toPopCategory; StackPopper toPopMethod; public StatsHandlerPopper(CallStackPushPopHandler popHandler, String className, String categoryMethod, String methodName) { this.popHandler = popHandler; LocalCallStack.get().curr().addRootCallStackHandler(popHandler); this.toPopCategory = LocalCallStack.meth(className, categoryMethod).push(); this.toPopMethod = LocalCallStack.meth(className, methodName).pushWithParentStartTime(); } @Override public void close() { toPopMethod.close(); toPopCategory.close(); LocalCallStack.get().curr().removeRootCallStackHandler(popHandler); } } }