blob: 76fdcb31e117a3b818f7141ba36e5409b1e562a9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.core.logger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.interceptor.Interceptor;
import org.apache.directory.server.core.interceptor.NextInterceptor;
import org.apache.directory.server.core.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.interceptor.context.BindOperationContext;
import org.apache.directory.server.core.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
import org.apache.directory.server.core.interceptor.context.GetRootDSEOperationContext;
import org.apache.directory.server.core.interceptor.context.ListOperationContext;
import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.interceptor.context.UnbindOperationContext;
import org.apache.directory.shared.ldap.model.entry.Entry;
import org.apache.directory.shared.ldap.model.exception.LdapException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An interceptor used to log times to process each operation.
*
* The way it works is that it gathers the time to process an operation
* into a global counter, which is logged every 1000 operations (when
* using the OPERATION_STATS logger). It's also possible to get the time for
* each single operation if activating the OPERATION_TIME logger.
*
* Thos two loggers must be set to DEBUG.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class TimerInterceptor implements Interceptor
{
/** A aggregating logger */
private static final Logger OPERATION_STATS = LoggerFactory.getLogger( "OPERATION_STATS" );
/** An operation logger */
private static final Logger OPERATION_TIME = LoggerFactory.getLogger( "OPERATION_TIME" );
/** Speedup for logs */
private static final boolean IS_DEBUG_STATS = OPERATION_STATS.isDebugEnabled();
private static final boolean IS_DEBUG_TIME = OPERATION_TIME.isDebugEnabled();
/** The Logger's name */
private String name;
/** Stats for the add operation */
private static AtomicLong totalAdd = new AtomicLong( 0 );
private static AtomicInteger nbAddCalls = new AtomicInteger( 0 );
/** Stats for the bind operation */
private static AtomicLong totalBind = new AtomicLong( 0 );
private static AtomicInteger nbBindCalls = new AtomicInteger( 0 );
/** Stats for the compare operation */
private static AtomicLong totalCompare = new AtomicLong( 0 );
private static AtomicInteger nbCompareCalls = new AtomicInteger( 0 );
/** Stats for the delete operation */
private static AtomicLong totalDelete = new AtomicLong( 0 );
private static AtomicInteger nbDeleteCalls = new AtomicInteger( 0 );
/** Stats for the GetRootDSE operation */
private static AtomicLong totalGetRootDSE = new AtomicLong( 0 );
private static AtomicInteger nbGetRootDSECalls = new AtomicInteger( 0 );
/** Stats for the HasEntry operation */
private static AtomicLong totalHasEntry = new AtomicLong( 0 );
private static AtomicInteger nbHasEntryCalls = new AtomicInteger( 0 );
/** Stats for the list operation */
private static AtomicLong totalList = new AtomicLong( 0 );
private static AtomicInteger nbListCalls = new AtomicInteger( 0 );
/** Stats for the lookup operation */
private static AtomicLong totalLookup = new AtomicLong( 0 );
private static AtomicInteger nbLookupCalls = new AtomicInteger( 0 );
/** Stats for the modify operation */
private static AtomicLong totalModify = new AtomicLong( 0 );
private static AtomicInteger nbModifyCalls = new AtomicInteger( 0 );
/** Stats for the move operation */
private static AtomicLong totalMove = new AtomicLong( 0 );
private static AtomicInteger nbMoveCalls = new AtomicInteger( 0 );
/** Stats for the moveAndRename operation */
private static AtomicLong totalMoveAndRename = new AtomicLong( 0 );
private static AtomicInteger nbMoveAndRenameCalls = new AtomicInteger( 0 );
/** Stats for the rename operation */
private static AtomicLong totalRename = new AtomicLong( 0 );
private static AtomicInteger nbRenameCalls = new AtomicInteger( 0 );
/** Stats for the search operation */
private static AtomicLong totalSearch = new AtomicLong( 0 );
private static AtomicInteger nbSearchCalls = new AtomicInteger( 0 );
/** Stats for the unbind operation */
private static AtomicLong totalUnbind = new AtomicLong( 0 );
private static AtomicInteger nbUnbindCalls = new AtomicInteger( 0 );
/**
*
* Creates a new instance of TimerInterceptor.
*
* @param name This interceptor's name
*/
public TimerInterceptor( String name )
{
this.name = name;
}
/**
* {@inheritDoc}
*/
public void add( NextInterceptor next, AddOperationContext addContext ) throws LdapException
{
long t0 = System.nanoTime();
next.add( addContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbAddCalls.incrementAndGet();
totalAdd.getAndAdd( delta );
if ( nbAddCalls.get() % 1000 == 0 )
{
long average = totalAdd.get()/(nbAddCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average add = {} microseconds, nb adds = {}", average, nbAddCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta add = {}", name, delta );
}
}
/**
* {@inheritDoc}
*/
public void bind( NextInterceptor next, BindOperationContext bindContext ) throws LdapException
{
long t0 = System.nanoTime();
next.bind( bindContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbBindCalls.incrementAndGet();
totalBind.getAndAdd( delta );
if ( nbBindCalls.get() % 1000 == 0 )
{
long average = totalBind.get()/(nbBindCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average bind = {} microseconds, nb binds = {}", average, nbBindCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta bind = {}", name, delta );
}
}
/**
* {@inheritDoc}
*/
public boolean compare( NextInterceptor next, CompareOperationContext compareContext ) throws LdapException
{
long t0 = System.nanoTime();
boolean compare = next.compare( compareContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbCompareCalls.incrementAndGet();
totalCompare.getAndAdd( delta );
if ( nbCompareCalls.get() % 1000 == 0 )
{
long average = totalCompare.get()/(nbCompareCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average compare = {} microseconds, nb compares = {}", average, nbCompareCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta compare = {}", name, delta );
}
return compare;
}
/**
* {@inheritDoc}
*/
public void delete( NextInterceptor next, DeleteOperationContext deleteContext ) throws LdapException
{
long t0 = System.nanoTime();
next.delete( deleteContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbDeleteCalls.incrementAndGet();
totalDelete.getAndAdd( delta );
if ( nbDeleteCalls.get() % 1000 == 0 )
{
long average = totalDelete.get()/(nbDeleteCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average delete = {} microseconds, nb deletes = {}", average, nbDeleteCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta delete = {}", name, delta );
}
}
/**
* {@inheritDoc}
*/
public void destroy()
{
}
/**
* {@inheritDoc}
*/
public String getName()
{
return name;
}
/**
* {@inheritDoc}
*/
public Entry getRootDSE( NextInterceptor next, GetRootDSEOperationContext getRootDseContext )
throws LdapException
{
long t0 = System.nanoTime();
Entry rootDSE = next.getRootDSE( getRootDseContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbGetRootDSECalls.incrementAndGet();
totalGetRootDSE.getAndAdd( delta );
if ( nbGetRootDSECalls.get() % 1000 == 0 )
{
long average = totalGetRootDSE.get()/(nbGetRootDSECalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average getRootDSE = {} microseconds, nb getRootDSEs = {}", average, nbGetRootDSECalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta getRootDSE = {}", name, delta );
}
return rootDSE;
}
/**
* {@inheritDoc}
*/
public boolean hasEntry( NextInterceptor next, EntryOperationContext hasEntryContext ) throws LdapException
{
long t0 = System.nanoTime();
boolean hasEntry = next.hasEntry( hasEntryContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbHasEntryCalls.incrementAndGet();
totalHasEntry.getAndAdd( delta );
if ( nbHasEntryCalls.get() % 1000 == 0 )
{
long average = totalHasEntry.get()/(nbHasEntryCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average hasEntry = {} microseconds, nb hasEntrys = {}", average, nbHasEntryCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta hasEntry = {}", name, delta );
}
return hasEntry;
}
/**
* {@inheritDoc}
*/
public void init( DirectoryService directoryService ) throws LdapException
{
}
/**
* {@inheritDoc}
*/
public EntryFilteringCursor list( NextInterceptor next, ListOperationContext listContext ) throws LdapException
{
long t0 = System.nanoTime();
EntryFilteringCursor cursor = next.list( listContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbListCalls.incrementAndGet();
totalList.getAndAdd( delta );
if ( nbListCalls.get() % 1000 == 0 )
{
long average = totalList.get()/(nbListCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average list = {} microseconds, nb lists = {}", average, nbListCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta list = {}", name, delta );
}
return cursor;
}
/**
* {@inheritDoc}
*/
public Entry lookup( NextInterceptor next, LookupOperationContext lookupContext ) throws LdapException
{
long t0 = System.nanoTime();
Entry entry = next.lookup( lookupContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbLookupCalls.incrementAndGet();
totalLookup.getAndAdd( delta );
if ( nbLookupCalls.get() % 1000 == 0 )
{
long average = totalLookup.get()/(nbLookupCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average lookup = {} microseconds, nb lookups = {}", average, nbLookupCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta lookup = {}", name, delta );
}
return entry;
}
/**
* {@inheritDoc}
*/
public void modify( NextInterceptor next, ModifyOperationContext modifyContext ) throws LdapException
{
long t0 = System.nanoTime();
next.modify( modifyContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbModifyCalls.incrementAndGet();
totalModify.getAndAdd( delta );
if ( nbModifyCalls.get() % 1000 == 0 )
{
long average = totalModify.get()/(nbModifyCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average modify = {} microseconds, nb modifys = {}", average, nbModifyCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta modify = {}", name, delta );
}
}
/**
* {@inheritDoc}
*/
public void move( NextInterceptor next, MoveOperationContext moveContext ) throws LdapException
{
long t0 = System.nanoTime();
next.move( moveContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbMoveCalls.incrementAndGet();
totalMove.getAndAdd( delta );
if ( nbMoveCalls.get() % 1000 == 0 )
{
long average = totalMove.get()/(nbMoveCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average move = {} microseconds, nb moves = {}", average, nbMoveCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta move = {}", name, delta );
}
}
/**
* {@inheritDoc}
*/
public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
{
long t0 = System.nanoTime();
next.moveAndRename( moveAndRenameContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbMoveAndRenameCalls.incrementAndGet();
totalMoveAndRename.getAndAdd( delta );
if ( nbMoveAndRenameCalls.get() % 1000 == 0 )
{
long average = totalMoveAndRename.get()/(nbMoveAndRenameCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average moveAndRename = {} microseconds, nb moveAndRenames = {}", average, nbMoveAndRenameCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta moveAndRename = {}", name, delta );
}
}
/**
* {@inheritDoc}
*/
public void rename( NextInterceptor next, RenameOperationContext renameContext ) throws LdapException
{
long t0 = System.nanoTime();
next.rename( renameContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbRenameCalls.incrementAndGet();
totalRename.getAndAdd( delta );
if ( nbRenameCalls.get() % 1000 == 0 )
{
long average = totalRename.get()/(nbRenameCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average rename = {} microseconds, nb renames = {}", average, nbRenameCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta rename = {}", name, delta );
}
}
/**
* {@inheritDoc}
*/
public EntryFilteringCursor search( NextInterceptor next, SearchOperationContext searchContext ) throws LdapException
{
long t0 = System.nanoTime();
EntryFilteringCursor cursor = next.search( searchContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbSearchCalls.incrementAndGet();
totalSearch.getAndAdd( delta );
if ( nbSearchCalls.get() % 1000 == 0 )
{
long average = totalSearch.get()/(nbSearchCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average search = {} microseconds, nb searches = {}", average, nbSearchCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta search = {}", name, delta );
}
return cursor;
}
/**
* {@inheritDoc}
*/
public void unbind( NextInterceptor next, UnbindOperationContext unbindContext ) throws LdapException
{
long t0 = System.nanoTime();
next.unbind( unbindContext );
long delta = System.nanoTime() - t0;
if ( IS_DEBUG_STATS )
{
nbUnbindCalls.incrementAndGet();
totalUnbind.getAndAdd( delta );
if ( nbUnbindCalls.get() % 1000 == 0 )
{
long average = totalUnbind.get()/(nbUnbindCalls.get() * 1000);
OPERATION_STATS.debug( name + " : Average unbind = {} microseconds, nb unbinds = {}", average, nbUnbindCalls.get() );
}
}
if ( IS_DEBUG_TIME )
{
OPERATION_TIME.debug( "{} : Delta unbind = {}", name, delta );
}
}
}