Skip to content

Commit

Permalink
Include allocation and CPU time in query log
Browse files Browse the repository at this point in the history
  • Loading branch information
thobe committed Apr 4, 2017
1 parent 94b5199 commit f29026a
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 83 deletions.
Expand Up @@ -488,6 +488,12 @@ public class GraphDatabaseSettings implements LoadableConfig
@Description( "Log parameters for executed queries that took longer than the configured threshold." ) @Description( "Log parameters for executed queries that took longer than the configured threshold." )
public static final Setting<Boolean> log_queries_parameter_logging_enabled = setting( "dbms.logs.query.parameter_logging_enabled", BOOLEAN, TRUE ); public static final Setting<Boolean> log_queries_parameter_logging_enabled = setting( "dbms.logs.query.parameter_logging_enabled", BOOLEAN, TRUE );


@Description( "Log detailed time information for executed queries that took longer than the configured threshold." )
public static final Setting<Boolean> log_queries_detailed_time_logging_enabled = setting( "dbms.logs.query.time_logging_enabled", BOOLEAN, FALSE );

@Description( "Log allocated bytes for executed queries that took longer than the configured threshold." )
public static final Setting<Boolean> log_queries_allocation_logging_enabled = setting( "dbms.logs.query.allocation_logging_enabled", BOOLEAN, FALSE );

@Description("If the execution of query takes more time than this threshold, the query is logged - " + @Description("If the execution of query takes more time than this threshold, the query is logged - " +
"provided query logging is enabled. Defaults to 0 seconds, that is all queries are logged.") "provided query logging is enabled. Defaults to 0 seconds, that is all queries are logged.")
public static final Setting<Long> log_queries_threshold = setting("dbms.logs.query.threshold", DURATION, "0s"); public static final Setting<Long> log_queries_threshold = setting("dbms.logs.query.threshold", DURATION, "0s");
Expand Down
Expand Up @@ -243,11 +243,6 @@ ClientConnectionInfo clientConnection()
return clientConnection; return clientConnection;
} }


public String connectionDetailsForLogging()
{
return clientConnection.asConnectionDetails();
}

private LockWaitEvent waitForLock( boolean exclusive, ResourceType resourceType, long[] resourceIds ) private LockWaitEvent waitForLock( boolean exclusive, ResourceType resourceType, long[] resourceIds )
{ {
WaitingOnLockEvent event = new WaitingOnLockEvent( WaitingOnLockEvent event = new WaitingOnLockEvent(
Expand Down
Expand Up @@ -22,20 +22,22 @@
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.OutputStream; import java.io.OutputStream;
import java.time.Clock;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;


import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.helpers.Service; import org.neo4j.helpers.Service;
import org.neo4j.helpers.Strings; import org.neo4j.helpers.Strings;
import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.api.query.ExecutingQuery; import org.neo4j.kernel.api.query.ExecutingQuery;
import org.neo4j.kernel.api.query.QuerySnapshot;
import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.extension.KernelExtensionFactory; import org.neo4j.kernel.extension.KernelExtensionFactory;
import org.neo4j.kernel.impl.logging.LogService; import org.neo4j.kernel.impl.logging.LogService;
Expand All @@ -47,7 +49,6 @@
import org.neo4j.logging.FormattedLog; import org.neo4j.logging.FormattedLog;
import org.neo4j.logging.Log; import org.neo4j.logging.Log;
import org.neo4j.logging.RotatingFileOutputStreamSupplier; import org.neo4j.logging.RotatingFileOutputStreamSupplier;
import org.neo4j.time.Clocks;


import static java.lang.String.format; import static java.lang.String.format;
import static org.neo4j.io.file.Files.createOrOpenAsOuputStream; import static org.neo4j.io.file.Files.createOrOpenAsOuputStream;
Expand All @@ -68,6 +69,24 @@ public interface Dependencies
JobScheduler jobScheduler(); JobScheduler jobScheduler();
} }


enum Flag
{
LOG_PARAMETERS( GraphDatabaseSettings.log_queries_parameter_logging_enabled ),
LOG_DETAILED_TIME( GraphDatabaseSettings.log_queries_detailed_time_logging_enabled ),
LOG_ALLOCATED_BYTES( GraphDatabaseSettings.log_queries_allocation_logging_enabled );
private final Setting<Boolean> setting;

Flag( Setting<Boolean> setting )
{
this.setting = setting;
}

boolean enabledIn( Config config )
{
return config.get( setting );
}
}

public QueryLoggerKernelExtension() public QueryLoggerKernelExtension()
{ {
super( "query-logging" ); super( "query-logging" );
Expand Down Expand Up @@ -99,7 +118,14 @@ public void init() throws Throwable
Long thresholdMillis = config.get( GraphDatabaseSettings.log_queries_threshold ); Long thresholdMillis = config.get( GraphDatabaseSettings.log_queries_threshold );
Long rotationThreshold = config.get( GraphDatabaseSettings.log_queries_rotation_threshold ); Long rotationThreshold = config.get( GraphDatabaseSettings.log_queries_rotation_threshold );
int maxArchives = config.get( GraphDatabaseSettings.log_queries_max_archives ); int maxArchives = config.get( GraphDatabaseSettings.log_queries_max_archives );
boolean logQueryParameters = config.get( GraphDatabaseSettings.log_queries_parameter_logging_enabled ); EnumSet<Flag> flags = EnumSet.noneOf( Flag.class );
for ( Flag flag : Flag.values() )
{
if (flag.enabledIn(config))
{
flags.add( flag );
}
}


FormattedLog.Builder logBuilder = FormattedLog.withUTCTimeZone(); FormattedLog.Builder logBuilder = FormattedLog.withUTCTimeZone();
Log log; Log log;
Expand All @@ -119,7 +145,7 @@ public void init() throws Throwable
closable = rotatingSupplier; closable = rotatingSupplier;
} }


QueryLogger logger = new QueryLogger( Clocks.systemClock(), log, thresholdMillis, logQueryParameters ); QueryLogger logger = new QueryLogger( log, thresholdMillis, flags );
monitoring.addMonitorListener( logger ); monitoring.addMonitorListener( logger );
} }


Expand All @@ -138,10 +164,9 @@ private Lifecycle createEmptyAdapter()


static class QueryLogger implements QueryExecutionMonitor static class QueryLogger implements QueryExecutionMonitor
{ {
private final Clock clock;
private final Log log; private final Log log;
private final long thresholdMillis; private final long thresholdMillis;
private final boolean logQueryParameters; private final boolean logQueryParameters, logDetailedTime, logAllocatedBytes;


private static final Pattern PASSWORD_PATTERN = Pattern.compile( private static final Pattern PASSWORD_PATTERN = Pattern.compile(
// call signature // call signature
Expand All @@ -151,12 +176,13 @@ static class QueryLogger implements QueryExecutionMonitor
// password parameter, in single, double quotes, or parametrized // password parameter, in single, double quotes, or parametrized
"\\s*('(?:(?<=\\\\)'|[^'])*'|\"(?:(?<=\\\\)\"|[^\"])*\"|\\$\\w*|\\{\\w*\\})\\s*\\)" ); "\\s*('(?:(?<=\\\\)'|[^'])*'|\"(?:(?<=\\\\)\"|[^\"])*\"|\\$\\w*|\\{\\w*\\})\\s*\\)" );


QueryLogger( Clock clock, Log log, long thresholdMillis, boolean logQueryParameters ) QueryLogger( Log log, long thresholdMillis, EnumSet<Flag> flags )
{ {
this.clock = clock;
this.log = log; this.log = log;
this.thresholdMillis = thresholdMillis; this.thresholdMillis = thresholdMillis;
this.logQueryParameters = logQueryParameters; this.logQueryParameters = flags.contains( Flag.LOG_PARAMETERS );
this.logDetailedTime = flags.contains( Flag.LOG_DETAILED_TIME );
this.logAllocatedBytes = flags.contains( Flag.LOG_ALLOCATED_BYTES );
} }


@Override @Override
Expand All @@ -167,23 +193,22 @@ public void startQueryExecution( ExecutingQuery query )
@Override @Override
public void endFailure( ExecutingQuery query, Throwable failure ) public void endFailure( ExecutingQuery query, Throwable failure )
{ {
long time = clock.millis() - query.startTimestampMillis(); log.error( logEntry( query.snapshot() ), failure );
log.error( logEntry( time, query ), failure );
} }


@Override @Override
public void endSuccess( ExecutingQuery query ) public void endSuccess( ExecutingQuery query )
{ {
long time = clock.millis() - query.startTimestampMillis(); QuerySnapshot snapshot = query.snapshot();
if ( time >= thresholdMillis ) if ( snapshot.elapsedTimeMillis() >= thresholdMillis )
{ {
log.info( logEntry( time, query ) ); log.info( logEntry( snapshot ) );
} }
} }


private String logEntry( long time, ExecutingQuery query ) private String logEntry( QuerySnapshot query )
{ {
String sourceString = query.connectionDetailsForLogging(); String sourceString = query.clientConnection().asConnectionDetails();
String queryText = query.queryText(); String queryText = query.queryText();
String metaData = mapAsString( query.transactionAnnotationData() ); String metaData = mapAsString( query.transactionAnnotationData() );


Expand All @@ -208,15 +233,34 @@ else if ( password.charAt( 0 ) == '{' )
} }
} }


if ( logQueryParameters ) StringBuilder result = new StringBuilder();
result.append( query.elapsedTimeMillis() ).append( " ms: " );
if ( logDetailedTime )
{ {
String params = mapAsString( query.queryParameters(), passwordParams ); result.append( "(planning: " ).append( query.planningTimeMillis() );
return format( "%d ms: %s - %s - %s - %s", time, sourceString, queryText, params, metaData ); Long cpuTime = query.cpuTimeMillis();
if ( cpuTime != null )
{
result.append( ", cpu: " ).append( cpuTime );
}
result.append( ", waiting: " ).append( query.waitTimeMillis() );
result.append( ") - " );
} }
else if ( logAllocatedBytes )
{
Long bytes = query.allocatedBytes();
if ( bytes != null )
{
result.append( bytes ).append( " B - " );
}
}
result.append( sourceString ).append( " - " ).append( queryText );
if ( logQueryParameters )
{ {
return format( "%d ms: %s - %s - %s", time, sourceString, queryText, metaData ); result.append( " - " ).append( mapAsString( query.queryParameters(), passwordParams ) );
} }
result.append( " - " ).append( metaData );
return result.toString();
} }


private static String mapAsString( Map<String,Object> params ) private static String mapAsString( Map<String,Object> params )
Expand Down

0 comments on commit f29026a

Please sign in to comment.