001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.batch.phases;
021
022 import com.google.common.collect.Lists;
023 import org.apache.commons.lang.StringUtils;
024 import org.apache.commons.lang.SystemUtils;
025 import org.slf4j.Logger;
026 import org.slf4j.LoggerFactory;
027 import org.sonar.api.batch.Decorator;
028 import org.sonar.api.batch.events.DecoratorExecutionHandler;
029 import org.sonar.api.batch.events.DecoratorsPhaseHandler;
030 import org.sonar.api.batch.events.SensorExecutionHandler;
031 import org.sonar.api.batch.events.SensorsPhaseHandler;
032 import org.sonar.api.utils.TimeProfiler;
033
034 import java.util.IdentityHashMap;
035 import java.util.List;
036 import java.util.Map;
037
038 public class PhasesTimeProfiler implements SensorExecutionHandler, DecoratorExecutionHandler, DecoratorsPhaseHandler, SensorsPhaseHandler {
039
040 private static final Logger LOG = LoggerFactory.getLogger(PhasesTimeProfiler.class);
041
042 private TimeProfiler profiler = new TimeProfiler(LOG);
043 private DecoratorsProfiler decoratorsProfiler = new DecoratorsProfiler();
044
045 public void onSensorsPhase(SensorsPhaseEvent event) {
046 if (event.isStart()) {
047 LOG.debug("Sensors : {}", StringUtils.join(event.getSensors(), " -> "));
048 }
049 }
050
051 public void onSensorExecution(SensorExecutionEvent event) {
052 if (event.isStart()) {
053 profiler.start("Sensor " + event.getSensor());
054 } else {
055 profiler.stop();
056 }
057 }
058
059 public void onDecoratorExecution(DecoratorExecutionEvent event) {
060 if (event.isStart()) {
061 decoratorsProfiler.start(event.getDecorator());
062 } else {
063 decoratorsProfiler.stop();
064 }
065 }
066
067 public void onDecoratorsPhase(DecoratorsPhaseEvent event) {
068 if (event.isStart()) {
069 LOG.info("Execute decorators...");
070 if (LOG.isDebugEnabled()) {
071 LOG.debug("Decorators: {}", StringUtils.join(event.getDecorators(), " -> "));
072 }
073 } else {
074 decoratorsProfiler.log();
075 }
076 }
077
078 static class DecoratorsProfiler {
079 List<Decorator> decorators = Lists.newArrayList();
080 Map<Decorator, Long> durations = new IdentityHashMap<Decorator, Long>();
081 long startTime;
082 Decorator currentDecorator;
083
084 DecoratorsProfiler() {
085 }
086
087 void start(Decorator decorator) {
088 this.startTime = System.currentTimeMillis();
089 this.currentDecorator = decorator;
090 }
091
092 void stop() {
093 final Long cumulatedDuration;
094 if (durations.containsKey(currentDecorator)) {
095 cumulatedDuration = durations.get(currentDecorator);
096 } else {
097 decorators.add(currentDecorator);
098 cumulatedDuration = 0L;
099 }
100 durations.put(currentDecorator, cumulatedDuration + (System.currentTimeMillis() - startTime));
101 }
102
103 void log() {
104 LOG.debug(getMessage());
105 }
106
107 String getMessage() {
108 StringBuilder sb = new StringBuilder("Decorator time:").append(SystemUtils.LINE_SEPARATOR);
109 for (Decorator decorator : decorators) {
110 sb.append("\t").append(decorator.toString()).append(": ").append(durations.get(decorator)).append("ms")
111 .append(SystemUtils.LINE_SEPARATOR);
112 }
113 return sb.toString();
114 }
115 }
116
117 }