/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.portal.livetrace; import java.util.List; import java.util.concurrent.atomic.AtomicLong; import javax.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.google.common.base.Preconditions; import com.enonic.cms.core.portal.datasource.DataSourceType; import com.enonic.cms.core.structure.page.WindowKey; import com.enonic.cms.core.time.TimeService; /** * Oct 6, 2010 */ @Service("livePortalTraceService") public class LivePortalTraceServiceImpl implements LivePortalTraceService { private static final Logger LOG = LoggerFactory.getLogger( LivePortalTraceServiceImpl.class ); private static AtomicLong requestCounter = new AtomicLong(); private TimeService timeService; private boolean enabled = false; private int historySize; private int longestSize; private CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); private CompletedPortalRequests completedPortalRequests; private LongestPortalRequests longestPortalPageRequests; private LongestPortalRequests longestPortalAttachmentRequests; private LongestPortalRequests longestPortalImageRequests; private final static ThreadLocal<CurrentTrace> CURRENT_TRACE = new ThreadLocal<CurrentTrace>(); @PostConstruct public void init() { if ( enabled ) { LOG.info( "Live Portal Tracing is enabled [historySize=" + historySize + ", longestSize=" + longestSize + "]" ); longestPortalPageRequests = new LongestPortalRequests( longestSize ); longestPortalAttachmentRequests = new LongestPortalRequests( longestSize ); longestPortalImageRequests = new LongestPortalRequests( longestSize ); completedPortalRequests = new CompletedPortalRequests( historySize ); } else { LOG.info( "Live Portal Tracing is not enabled" ); } } public boolean tracingEnabled() { return enabled; } public PortalRequestTrace startPortalRequestTracing( final String url ) { checkEnabled(); final long requestNumber = requestCounter.incrementAndGet(); PortalRequestTrace portalRequestTrace = new PortalRequestTrace( requestNumber, url ); currentPortalRequests.add( portalRequestTrace ); portalRequestTrace.setStartTime( timeService.getNowAsDateTime() ); final CurrentTrace currentTrace = new CurrentTrace(); currentTrace.setPortalRequestTrace( portalRequestTrace ); CURRENT_TRACE.set( currentTrace ); currentTrace.setPageRenderingTrace( null ); return portalRequestTrace; } public PageRenderingTrace startPageRenderTracing( final PortalRequestTrace portalRequestTrace ) { Preconditions.checkNotNull( portalRequestTrace ); final PageRenderingTrace pageRenderingTrace = new PageRenderingTrace(); pageRenderingTrace.setStartTime( timeService.getNowAsDateTime() ); portalRequestTrace.setPageRenderingTrace( pageRenderingTrace ); getCurrentTrace().setPageRenderingTrace( pageRenderingTrace ); return pageRenderingTrace; } public WindowRenderingTrace startWindowRenderTracing( final WindowKey windowKey ) { final PortalRequestTrace portalRequestTrace = getCurrentTrace().getPortalRequestTrace(); if ( portalRequestTrace == null ) { return null; } final WindowRenderingTrace windowRenderingTrace = new WindowRenderingTrace( windowKey.toString() ); final ViewFunctionTrace currentViewFunctionTrace = getCurrentTrace().getViewFunctionTrace(); if ( currentViewFunctionTrace != null ) { currentViewFunctionTrace.addTrace( windowRenderingTrace ); } else if ( portalRequestTrace.hasPageRenderingTrace() ) { portalRequestTrace.getPageRenderingTrace().addWindowRenderingTrace( windowRenderingTrace ); } else { portalRequestTrace.setWindowRenderingTrace( windowRenderingTrace ); } windowRenderingTrace.setStartTime( timeService.getNowAsDateTime() ); getCurrentTrace().setWindowRenderingTrace( windowRenderingTrace ); return windowRenderingTrace; } @Override public DatasourceExecutionTrace startDatasourceExecutionTracing( final DataSourceType datasourcesType, final String datasourceMethodName ) { final DatasourceExecutionTrace datasourceExecutionTrace = new DatasourceExecutionTrace( datasourceMethodName ); datasourceExecutionTrace.setStartTime( timeService.getNowAsDateTime() ); if ( datasourcesType == DataSourceType.PAGETEMPLATE ) { final PageRenderingTrace pageRenderingTrace = getCurrentTrace().getPageRenderingTrace(); if ( pageRenderingTrace == null ) { return null; } pageRenderingTrace.addDatasourceExecutionTrace( datasourceExecutionTrace ); } else { final WindowRenderingTrace windowRenderingTrace = getCurrentTrace().getWindowRenderingTrace(); if ( windowRenderingTrace == null ) { return null; } windowRenderingTrace.addDatasourceExecutionTrace( datasourceExecutionTrace ); } getCurrentTrace().setDatasourceExecutionTrace( datasourceExecutionTrace ); return datasourceExecutionTrace; } @Override public ClientMethodExecutionTrace startClientMethodExecutionTracing( final String methodName ) { Preconditions.checkNotNull( methodName ); final DatasourceExecutionTrace currentDatasourceExecutionTrace = getCurrentTrace().getDatasourceExecutionTrace(); if ( currentDatasourceExecutionTrace == null ) { return null; } final ClientMethodExecutionTrace trace = new ClientMethodExecutionTrace(); trace.setMethodName( methodName ); trace.setStartTime( timeService.getNowAsDateTime() ); currentDatasourceExecutionTrace.addClientMethodExecutionTrace( trace ); getCurrentTrace().setClientMethodExecutionTrace( trace ); return trace; } @Override public ContentIndexQueryTrace startContentIndexQueryTracing() { final ContentIndexQuerier currentQuerier = getCurrentTrace().getCurrentContentIndexQuerier(); if ( currentQuerier != null ) { final ContentIndexQueryTrace trace = new ContentIndexQueryTrace(); trace.setStartTime( timeService.getNowAsDateTime() ); currentQuerier.addContentIndexQueryTrace( trace ); return trace; } else { return null; } } @Override public RelatedContentFetchTrace startRelatedContentFetchTracing() { final RelatedContentFetcher relatedContentFetcher = getCurrentTrace().getCurrentRelatedContentFetcher(); if ( relatedContentFetcher != null ) { final RelatedContentFetchTrace trace = new RelatedContentFetchTrace(); trace.setStartTime( timeService.getNowAsDateTime() ); relatedContentFetcher.addRelatedContentFetchTrace( trace ); return trace; } else { return null; } } public ViewTransformationTrace startViewTransformationTracing() { final ViewTransformationTrace trace = new ViewTransformationTrace(); trace.setStartTime( timeService.getNowAsDateTime() ); final WindowRenderingTrace windowRenderingTrace = getCurrentTrace().getWindowRenderingTrace(); if ( windowRenderingTrace != null ) { windowRenderingTrace.setViewTransformationTrace( trace ); getCurrentTrace().setWindowViewTransformationTrace( trace ); } else { final PageRenderingTrace pageRenderingTrace = getCurrentTrace().getPageRenderingTrace(); if ( pageRenderingTrace != null ) { pageRenderingTrace.setViewTransformationTrace( trace ); getCurrentTrace().setPageViewTransformationTrace( trace ); } else { return null; } } return trace; } @Override public XsltCompilationTrace startXsltCompilationTracing( final String template ) { final XsltCompilationTrace trace = new XsltCompilationTrace( template ); trace.setStartTime( timeService.getNowAsDateTime() ); final WindowRenderingTrace windowRenderingTrace = getCurrentTrace().getWindowRenderingTrace(); if ( windowRenderingTrace != null ) { windowRenderingTrace.setXsltCompilationTrace( trace ); getCurrentTrace().setXsltCompilationTrace( trace ); } else { final PageRenderingTrace pageRenderingTrace = getCurrentTrace().getPageRenderingTrace(); if ( pageRenderingTrace != null ) { pageRenderingTrace.setXsltCompilationTrace( trace ); getCurrentTrace().setXsltCompilationTrace( trace ); } else { return null; } } return trace; } public ViewFunctionTrace startViewFunctionTracing( final String functionName ) { final ViewFunctionTrace trace = new ViewFunctionTrace(); trace.setStartTime( timeService.getNowAsDateTime() ); trace.setName( functionName ); ViewTransformationTrace viewTransformationTrace = getCurrentTrace().getPageViewTransformationTrace(); if ( viewTransformationTrace != null ) { viewTransformationTrace.addViewFunctionTrace( trace ); getCurrentTrace().setViewFunctionTrace( trace ); return trace; } else { viewTransformationTrace = getCurrentTrace().getWindowViewTransformationTrace(); if ( viewTransformationTrace != null ) { viewTransformationTrace.addViewFunctionTrace( trace ); getCurrentTrace().setViewFunctionTrace( trace ); return trace; } else { return null; } } } public InstructionPostProcessingTrace startInstructionPostProcessingTracingForWindow() { final WindowRenderingTrace windowRenderingTrace = getCurrentTrace().getWindowRenderingTrace(); if ( windowRenderingTrace == null ) { return null; } final InstructionPostProcessingTrace instructionPostProcessingTrace = new InstructionPostProcessingTrace(); instructionPostProcessingTrace.setStartTime( timeService.getNowAsDateTime() ); windowRenderingTrace.setInstructionPostProcessingTrace( instructionPostProcessingTrace ); return instructionPostProcessingTrace; } public InstructionPostProcessingTrace startInstructionPostProcessingTracingForPage() { final PageRenderingTrace pageRenderingTrace = getCurrentTrace().getPageRenderingTrace(); if ( pageRenderingTrace == null ) { return null; } final InstructionPostProcessingTrace instructionPostProcessingTrace = new InstructionPostProcessingTrace(); instructionPostProcessingTrace.setStartTime( timeService.getNowAsDateTime() ); pageRenderingTrace.setInstructionPostProcessingTrace( instructionPostProcessingTrace ); return instructionPostProcessingTrace; } public AttachmentRequestTrace startAttachmentRequestTracing( final PortalRequestTrace portalRequestTrace ) { Preconditions.checkNotNull( portalRequestTrace ); AttachmentRequestTrace newTrace = new AttachmentRequestTrace(); newTrace.setStartTime( timeService.getNowAsDateTime() ); portalRequestTrace.setAttachmentRequestTrace( newTrace ); return newTrace; } public ImageRequestTrace startImageRequestTracing( final PortalRequestTrace portalRequestTrace ) { Preconditions.checkNotNull( portalRequestTrace ); ImageRequestTrace newTrace = new ImageRequestTrace(); newTrace.setStartTime( timeService.getNowAsDateTime() ); portalRequestTrace.setImageRequestTrace( newTrace ); getCurrentTrace().setImageRequestTrace( newTrace ); return newTrace; } public void stopTracing( final PortalRequestTrace portalRequestTrace ) { checkEnabled(); Preconditions.checkNotNull( portalRequestTrace ); portalRequestTrace.setStopTime( timeService.getNowAsDateTime() ); currentPortalRequests.remove( portalRequestTrace ); portalRequestTrace.postProcess(); completedPortalRequests.add( portalRequestTrace ); if ( portalRequestTrace.hasPageRenderingTrace() || portalRequestTrace.hasWindowRenderingTrace() ) { longestPortalPageRequests.add( portalRequestTrace ); } else if ( portalRequestTrace.hasAttachmentRequsetTrace() ) { longestPortalAttachmentRequests.add( portalRequestTrace ); } else if ( portalRequestTrace.hasImageRequestTrace() ) { longestPortalImageRequests.add( portalRequestTrace ); } getCurrentTrace().setPortalRequestTrace( null ); } public void stopTracing( final PageRenderingTrace pageRenderTrace ) { Preconditions.checkNotNull( pageRenderTrace ); pageRenderTrace.setStopTime( timeService.getNowAsDateTime() ); getCurrentTrace().setPageRenderingTrace( null ); } public void stopTracing( final WindowRenderingTrace windowRenderingTrace ) { Preconditions.checkNotNull( windowRenderingTrace ); windowRenderingTrace.setStopTime( timeService.getNowAsDateTime() ); getCurrentTrace().setWindowRenderingTrace( null ); } public void stopTracing( final AttachmentRequestTrace attachmentRequestTrace ) { Preconditions.checkNotNull( attachmentRequestTrace ); attachmentRequestTrace.setStopTime( timeService.getNowAsDateTime() ); } public void stopTracing( final DatasourceExecutionTrace datasourceExecutionTrace ) { Preconditions.checkNotNull( datasourceExecutionTrace ); datasourceExecutionTrace.setStopTime( timeService.getNowAsDateTime() ); getCurrentTrace().setDatasourceExecutionTrace( null ); } @Override public void stopTracing( final ClientMethodExecutionTrace clientMethodExecutionTrace ) { Preconditions.checkNotNull( clientMethodExecutionTrace ); clientMethodExecutionTrace.setStopTime( timeService.getNowAsDateTime() ); getCurrentTrace().setClientMethodExecutionTrace( null ); } @Override public void stopTracing( final ViewTransformationTrace trace ) { Preconditions.checkNotNull( trace ); trace.setStopTime( timeService.getNowAsDateTime() ); getCurrentTrace().removeCurrentViewTransformationTrace(); } @Override public void stopTracing( final ViewFunctionTrace trace ) { Preconditions.checkNotNull( trace ); trace.setStopTime( timeService.getNowAsDateTime() ); getCurrentTrace().setViewFunctionTrace( null ); } @Override public void stopTracing( final ContentIndexQueryTrace contentIndexQueryTrace ) { Preconditions.checkNotNull( contentIndexQueryTrace ); contentIndexQueryTrace.setStopTime( timeService.getNowAsDateTime() ); } @Override public void stopTracing( final RelatedContentFetchTrace trace ) { Preconditions.checkNotNull( trace ); trace.setStopTime( timeService.getNowAsDateTime() ); } public void stopTracing( final InstructionPostProcessingTrace instructionPostProcessingTrace ) { Preconditions.checkNotNull( instructionPostProcessingTrace ); if ( getCurrentTrace().isInPageRenderingTrace() ) { final Traces<WindowRenderingTrace> windowRenderingTraces = getCurrentTrace().getPageRenderingTrace().getWindowRenderingTraces(); int windowsTotalPeriod = windowRenderingTraces != null ? windowRenderingTraces.getTotalPeriodInMilliseconds() : 0; final long stopTime = timeService.getNowAsDateTime().getMillis(); final long startTime = instructionPostProcessingTrace.getStartTime().getMillis(); final long duration = ( stopTime - startTime ) - windowsTotalPeriod; instructionPostProcessingTrace.setDurationInMilliseconds( duration ); } else if ( getCurrentTrace().getWindowRenderingTrace() != null ) { final long stopTime = timeService.getNowAsDateTime().getMillis(); final long startTime = instructionPostProcessingTrace.getStartTime().getMillis(); final long duration = stopTime - startTime; instructionPostProcessingTrace.setDurationInMilliseconds( duration ); } } public void stopTracing( final XsltCompilationTrace trace ) { Preconditions.checkNotNull( trace ); trace.setStopTime( timeService.getNowAsDateTime() ); } public void stopTracing( final ImageRequestTrace imageRequestTrace ) { Preconditions.checkNotNull( imageRequestTrace ); imageRequestTrace.setStopTime( timeService.getNowAsDateTime() ); } @Override public int getNumberOfPortalRequestTracesInProgress() { checkEnabled(); return currentPortalRequests.getSize(); } public List<PortalRequestTrace> getCurrentPortalRequestTraces() { checkEnabled(); return currentPortalRequests.getList(); } public List<PortalRequestTrace> getLongestTimePortalPageRequestTraces() { checkEnabled(); return longestPortalPageRequests.getList(); } public List<PortalRequestTrace> getLongestTimePortalAttachmentRequestTraces() { checkEnabled(); return longestPortalAttachmentRequests.getList(); } public List<PortalRequestTrace> getLongestTimePortalImageRequestTraces() { checkEnabled(); return longestPortalImageRequests.getList(); } public List<PortalRequestTrace> getCompletedAfter( long historyRecordNumber ) { checkEnabled(); return completedPortalRequests.getCompletedAfter( historyRecordNumber ); } public List<PortalRequestTrace> getCompletedBefore( long historyRecordNumber ) { checkEnabled(); return completedPortalRequests.getCompletedBefore( historyRecordNumber ); } public PortalRequestTrace getCurrentPortalRequestTrace() { if ( !enabled ) { return null; } CurrentTrace currentTrace = CURRENT_TRACE.get(); if ( currentTrace == null ) { return null; } return currentTrace.getPortalRequestTrace(); } @Override public void clearLongestPageRequestsTraces() { longestPortalPageRequests.clear(); } @Override public void clearLongestAttachmentRequestTraces() { longestPortalAttachmentRequests.clear(); } @Override public void clearLongestImageRequestTraces() { longestPortalImageRequests.clear(); } private void checkEnabled() { Preconditions.checkArgument( enabled, "Unexpected call when Live Portal Tracing is disabled" ); } public CurrentTrace getCurrentTrace() { CurrentTrace currentTrace = CURRENT_TRACE.get(); if ( currentTrace == null ) { currentTrace = new CurrentTrace(); CURRENT_TRACE.set( currentTrace ); } return currentTrace; } @Autowired public void setTimeService( TimeService timeService ) { this.timeService = timeService; } @Value("${cms.livePortalTrace.enabled}") public void setEnabled( String enabled ) { this.enabled = Boolean.valueOf( enabled ); } @Value("${cms.livePortalTrace.history.size}") public void setHistorySize( int value ) { this.historySize = value; } @Value("${cms.livePortalTrace.longest.size}") public void setLongestSize( int value ) { this.longestSize = value; } }