1 package com.soebes.maven.extensions;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Collections;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27
28 import javax.inject.Named;
29 import javax.inject.Singleton;
30
31 import org.apache.maven.execution.ExecutionEvent;
32 import org.apache.maven.execution.ExecutionEvent.Type;
33 import org.apache.maven.execution.MavenExecutionRequest;
34 import org.apache.maven.execution.MavenExecutionResult;
35 import org.apache.maven.project.DependencyResolutionRequest;
36 import org.apache.maven.project.DependencyResolutionResult;
37 import org.apache.maven.project.MavenProject;
38 import org.eclipse.aether.RepositoryEvent;
39 import org.eclipse.aether.RepositoryEvent.EventType;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import com.soebes.maven.extensions.artifact.DeployTimer;
44 import com.soebes.maven.extensions.artifact.DownloadTimer;
45 import com.soebes.maven.extensions.artifact.InstallTimer;
46 import com.soebes.maven.extensions.metadata.MetadataDeploymentTimer;
47 import com.soebes.maven.extensions.metadata.MetadataDownloadTimer;
48 import com.soebes.maven.extensions.metadata.MetadataInstallTimer;
49
50
51
52
53 @Named
54 @Singleton
55 public class BuildTimeProfiler
56 extends LifeCycleOrdering
57 {
58 private final Logger LOGGER = LoggerFactory.getLogger( getClass() );
59
60 final List<String> lifeCyclePhases;
61
62 private final DiscoveryTimer discoveryTimer;
63
64 private final GoalTimer goalTimer;
65
66 private final MojoTimer mojoTimer;
67
68 private final ProjectTimer projectTimer;
69
70 private final SessionTimer sessionTimer;
71
72 private final InstallTimer installTimer;
73
74 private final DeployTimer deployTimer;
75
76 private final DownloadTimer downloadTimer;
77
78 private final MetadataDownloadTimer metadataDownloadTimer;
79
80 private final MetadataDeploymentTimer metadataDeploymentTimer;
81
82 private final MetadataInstallTimer metadataInstallTimer;
83
84 private final ForkTimer forkTimer;
85
86 private final ProjectTimer forkProject;
87
88 public BuildTimeProfiler()
89 {
90 LOGGER.debug( "LifeCycleProfiler ctor called." );
91 this.lifeCyclePhases = Collections.<String>synchronizedList( new LinkedList<String>() );
92 this.discoveryTimer = new DiscoveryTimer();
93 this.goalTimer = new GoalTimer();
94 this.mojoTimer = new MojoTimer();
95 this.projectTimer = new ProjectTimer();
96 this.sessionTimer = new SessionTimer();
97 this.installTimer = new InstallTimer();
98 this.deployTimer = new DeployTimer();
99 this.downloadTimer = new DownloadTimer();
100
101 this.metadataDownloadTimer = new MetadataDownloadTimer();
102 this.metadataDeploymentTimer = new MetadataDeploymentTimer();
103 this.metadataInstallTimer = new MetadataInstallTimer();
104 this.forkTimer = new ForkTimer();
105 this.forkProject = new ProjectTimer();
106
107 }
108
109 @Override
110 public void init( Context context )
111 throws Exception
112 {
113 super.init( context );
114 LOGGER.info( "Maven Build Time Profiler started. (Version {})", BuildTimeProfilerVersion.getVersion() );
115
116
117 String workingDirectory = (String) context.getData().get( "workingDirectory" );
118 LOGGER.debug( "MBTP: workingDirectory: " + workingDirectory );
119
120 String multiModuleProjectDirectory = (String) context.getData().get( "multiModuleProjectDirectory" );
121 LOGGER.debug( "MBTP: multiModuleProjectDirectory: " + multiModuleProjectDirectory );
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 }
143
144 @Override
145 public void onEvent( Object event )
146 throws Exception
147 {
148 try
149 {
150 if ( event instanceof ExecutionEvent )
151 {
152 executionEventHandler( (ExecutionEvent) event );
153 }
154 else if ( event instanceof org.eclipse.aether.RepositoryEvent )
155 {
156 repositoryEventHandler( (RepositoryEvent) event );
157 }
158 else if ( event instanceof MavenExecutionRequest )
159 {
160 executionRequestEventHandler( (MavenExecutionRequest) event );
161 }
162 else if ( event instanceof MavenExecutionResult )
163 {
164 executionResultEventHandler( (MavenExecutionResult) event );
165 }
166 else if ( event instanceof DependencyResolutionRequest )
167 {
168 dependencyResolutionRequest( (DependencyResolutionRequest) event );
169 }
170 else if ( event instanceof DependencyResolutionResult )
171 {
172 dependencyResolutionResult( (DependencyResolutionResult) event );
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 else
208 {
209
210 LOGGER.debug( "MBTP: Event {}", event.getClass().getCanonicalName() );
211 }
212 }
213 catch ( Exception e )
214 {
215 LOGGER.error( "MBTP: Exception", e );
216 }
217 }
218
219 @Override
220 public void close()
221 {
222 LOGGER.debug( "MBTP: done." );
223 }
224
225 private void dependencyResolutionResult( DependencyResolutionResult event )
226 {
227 LOGGER.debug( "MBTP: dependencyResolutionResult() {}", event.getResolvedDependencies().size() );
228 }
229
230 private void dependencyResolutionRequest( DependencyResolutionRequest event )
231 {
232 LOGGER.debug( "MBTP: dependencyResolutionRequest()" );
233 }
234
235 private void repositoryEventHandler( org.eclipse.aether.RepositoryEvent repositoryEvent )
236 {
237 EventType type = repositoryEvent.getType();
238 switch ( type )
239 {
240 case ARTIFACT_DOWNLOADING:
241 LOGGER.debug( "MBTP: repositoryEventHandler {}", type );
242 downloadTimer.start( repositoryEvent );
243 break;
244 case ARTIFACT_DOWNLOADED:
245 LOGGER.debug( "MBTP: repositoryEventHandler {}", type );
246 downloadTimer.stop( repositoryEvent );
247 break;
248
249 case ARTIFACT_DEPLOYING:
250 deployTimer.start( repositoryEvent );
251 break;
252 case ARTIFACT_DEPLOYED:
253 deployTimer.stop( repositoryEvent );
254 break;
255
256 case ARTIFACT_INSTALLING:
257 installTimer.start( repositoryEvent );
258 break;
259 case ARTIFACT_INSTALLED:
260 installTimer.stop( repositoryEvent );
261 break;
262
263 case METADATA_DEPLOYING:
264 metadataDeploymentTimer.start( repositoryEvent );
265 break;
266 case METADATA_DEPLOYED:
267 metadataDeploymentTimer.stop( repositoryEvent );
268 break;
269
270 case METADATA_DOWNLOADING:
271 LOGGER.debug( "MBTP: repositoryEventHandler {}", type );
272 metadataDownloadTimer.start( repositoryEvent );
273 break;
274 case METADATA_DOWNLOADED:
275 LOGGER.debug( "MBTP: repositoryEventHandler {}", type );
276 metadataDownloadTimer.stop( repositoryEvent );
277 break;
278
279 case METADATA_INSTALLING:
280 LOGGER.debug( "MBTP: repositoryEventHandler {}", type );
281 metadataInstallTimer.start( repositoryEvent );
282 break;
283 case METADATA_INSTALLED:
284 LOGGER.debug( "MBTP: repositoryEventHandler {}", type );
285 metadataInstallTimer.stop( repositoryEvent );
286 break;
287
288 case ARTIFACT_RESOLVING:
289 case ARTIFACT_RESOLVED:
290 case ARTIFACT_DESCRIPTOR_INVALID:
291 case ARTIFACT_DESCRIPTOR_MISSING:
292 case METADATA_RESOLVED:
293 case METADATA_RESOLVING:
294 case METADATA_INVALID:
295
296 break;
297
298 default:
299 LOGGER.error( "MBTP: repositoryEventHandler {}", type );
300 break;
301 }
302 }
303
304 private void executionEventHandler( ExecutionEvent executionEvent )
305 {
306 LOGGER.debug( "executionEventHandler: {}", executionEvent.getType() );
307 Type type = executionEvent.getType();
308 switch ( type )
309 {
310 case ProjectDiscoveryStarted:
311
312 discoveryTimer.discoveryStart();
313 break;
314 case SessionStarted:
315
316 discoveryTimer.discoveryStop();
317 sessionTimer.sessionStart();
318 break;
319 case SessionEnded:
320
321 sessionTimer.sessionStop();
322 break;
323
324 case ForkStarted:
325 forkTimer.start();
326 break;
327 case ForkFailed:
328 case ForkSucceeded:
329 forkTimer.stop();
330 break;
331
332 case ForkedProjectStarted:
333 forkProject.projectStart( executionEvent );
334 break;
335 case ForkedProjectFailed:
336 case ForkedProjectSucceeded:
337 forkProject.projectStop( executionEvent );
338 break;
339
340 case MojoStarted:
341 String phaseStart = executionEvent.getMojoExecution().getLifecyclePhase();
342
343 if ( phaseStart == null )
344 {
345 goalTimer.mojoStart( executionEvent );
346 }
347 else
348 {
349 collectAllLifeCylcePhases( phaseStart );
350 mojoTimer.mojoStart( executionEvent );
351 }
352 break;
353
354 case MojoFailed:
355 case MojoSucceeded:
356 case MojoSkipped:
357 String phaseStop = executionEvent.getMojoExecution().getLifecyclePhase();
358 if ( phaseStop == null )
359 {
360 goalTimer.mojoStop( executionEvent );
361 }
362 else
363 {
364 mojoTimer.mojoStop( executionEvent );
365 }
366 break;
367
368 case ProjectStarted:
369 projectTimer.projectStart( executionEvent );
370 break;
371
372 case ProjectFailed:
373 case ProjectSucceeded:
374 case ProjectSkipped:
375 projectTimer.projectStop( executionEvent );
376 break;
377
378 default:
379 LOGGER.error( "MBTP: executionEventHandler: {}", type );
380 break;
381 }
382
383 }
384
385 private void executionRequestEventHandler( MavenExecutionRequest event )
386 {
387
388
389
390 LOGGER.debug( "MBTP: executionRequestEventHandler: {}", event.getExecutionListener() );
391 }
392
393 private void executionResultEventHandler( MavenExecutionResult event )
394 {
395 orderLifeCycleOnPreparedOrder( lifeCyclePhases );
396
397 LOGGER.debug( "MBTP: executionResultEventHandler: {}", event.getProject() );
398
399 LOGGER.info( "-- Maven Build Time Profiler Summary --" );
400 LOGGER.info( "------------------------------------------------------------------------" );
401
402 discoveryTimer.report();
403
404 if ( mojoTimer.hasEvents() )
405 {
406 LOGGER.info( "Project Build Time (reactor order):" );
407 LOGGER.info( "" );
408 for ( MavenProject mavenProject : event.getTopologicallySortedProjects() )
409 {
410 LOGGER.info( "{}:", mavenProject.getName() );
411
412 for ( String phase : lifeCyclePhases )
413 {
414 ProjectKey projectKey = mavenProjectToProjectKey( mavenProject );
415
416 if ( !mojoTimer.hasTimeForProjectAndPhase( projectKey, phase ) )
417 {
418 continue;
419 }
420
421 long timeForPhaseAndProjectInMillis =
422 mojoTimer.getTimeForProjectAndPhaseInMillis( projectKey, phase );
423 LOGGER.info( " {} ms : {}", String.format( "%8d", timeForPhaseAndProjectInMillis ), phase );
424
425 }
426
427 }
428 LOGGER.info( "------------------------------------------------------------------------" );
429 LOGGER.info( "Lifecycle Phase summary:" );
430 LOGGER.info( "" );
431 for ( String phase : lifeCyclePhases )
432 {
433 long timeForPhaseInMillis = mojoTimer.getTimeForPhaseInMillis( phase );
434 LOGGER.info( "{} ms : {}", String.format( "%8d", timeForPhaseInMillis ), phase );
435 }
436
437
438 LOGGER.info( "------------------------------------------------------------------------" );
439 LOGGER.info( "Plugins in lifecycle Phases:" );
440 LOGGER.info( "" );
441 for ( String phase : lifeCyclePhases )
442 {
443 LOGGER.info( "{}:", phase );
444 Map<ProjectMojo, SystemTime> plugisInPhase = mojoTimer.getPluginsInPhase( phase );
445 for ( Entry<ProjectMojo, SystemTime> pluginInPhase : plugisInPhase.entrySet() )
446 {
447 LOGGER.info( "{} ms: {}", String.format( "%8d", pluginInPhase.getValue().getElapsedTime() ),
448 pluginInPhase.getKey().getMojo().getFullId() );
449 }
450
451 }
452 LOGGER.info( "------------------------------------------------------------------------" );
453 }
454
455 if ( goalTimer.hasEvents() )
456 {
457 LOGGER.info( "Plugins directly called via goals:" );
458 LOGGER.info( "" );
459 goalTimer.report();
460 LOGGER.info( "------------------------------------------------------------------------" );
461 }
462
463 installTimer.report();
464 downloadTimer.report();
465 deployTimer.report();
466 metadataInstallTimer.report();
467 metadataDownloadTimer.report();
468 metadataDeploymentTimer.report();
469
470 forkTimer.report();
471 forkProject.report();
472 }
473
474 private ProjectKey mavenProjectToProjectKey( MavenProject project )
475 {
476 return new ProjectKey( project.getGroupId(), project.getArtifactId(), project.getVersion() );
477 }
478
479 private void collectAllLifeCylcePhases( String phase )
480 {
481
482
483 if ( phase == null )
484 {
485 return;
486 }
487 LOGGER.debug( "collectAllLifeCyclePhases({})", phase );
488 if ( !lifeCyclePhases.contains( phase ) )
489 {
490 lifeCyclePhases.add( phase );
491 }
492 }
493
494 }