From 9e60e4bb82deb068ed9c6792f3af9f03397ed28b Mon Sep 17 00:00:00 2001 From: MishaDemianenko Date: Thu, 5 Oct 2017 12:09:09 +0200 Subject: [PATCH] Allow usage of system timezone for database logs Previously all database logs where using UTC only for time in all logs. This PR will allow to change behaviour and use system timezone for all the logs using newly introduced "log_timezone" database setting. Current possible setting values are: UTC(default value) - log in UTC; SYSTEM - log in a system default timezone. --- .../neo4j/bolt/logging/BoltMessageLog.java | 6 +- .../bolt/logging/BoltMessageLogging.java | 8 +- .../consistency/CheckConsistencyCommand.java | 7 +- .../consistency/ConsistencyCheckTool.java | 5 +- .../consistency/ConsistencyCheckToolTest.java | 81 +++++++++++++++++-- .../factory/GraphDatabaseSettings.java | 5 ++ .../main/java/org/neo4j/helpers/Format.java | 28 +++---- .../kernel/impl/factory/PlatformModule.java | 1 + .../kernel/impl/logging/StoreLogService.java | 14 +++- ...onfigurableStandalonePageCacheFactory.java | 5 +- .../SystemTimeZoneLoggingIT.java | 78 ++++++++++++++++++ .../java/org/neo4j/logging/LogTimeZone.java | 45 +++++++++++ .../org/neo4j/server/AbstractNeoServer.java | 2 + .../org/neo4j/server/ServerBootstrapper.java | 1 + .../org/neo4j/server/web/AsyncRequestLog.java | 6 +- .../java/org/neo4j/backup/BackupTool.java | 15 ++-- .../org/neo4j/backup/OnlineBackupCommand.java | 5 +- .../management/impl/DiagnosticsBean.java | 16 +++- .../query/QueryLoggerKernelExtension.java | 4 +- .../kernel/impl/query/QueryLoggerIT.java | 35 ++++++++ .../security/enterprise/log/SecurityLog.java | 8 +- .../enterprise/log/SecurityLogTest.java | 33 ++++++++ .../enterprise/ArbiterBootstrapper.java | 6 +- .../desktop/runtime/DatabaseActions.java | 5 +- 24 files changed, 369 insertions(+), 50 deletions(-) create mode 100644 community/kernel/src/test/java/org/neo4j/kernel/configuration/SystemTimeZoneLoggingIT.java create mode 100644 community/logging/src/main/java/org/neo4j/logging/LogTimeZone.java diff --git a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLog.java b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLog.java index a51d3d107f74..85e9e84c9a3c 100644 --- a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLog.java +++ b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLog.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -42,12 +43,13 @@ public class BoltMessageLog extends LifecycleAdapter private final Log inner; - public BoltMessageLog( FileSystemAbstraction fileSystem, File logFile, Executor executor ) throws IOException + public BoltMessageLog( FileSystemAbstraction fileSystem, ZoneId logTimeZone, File logFile, Executor executor ) throws IOException { RotatingFileOutputStreamSupplier outputStreamSupplier = new RotatingFileOutputStreamSupplier( fileSystem, logFile, ROTATION_THRESHOLD_BYTES, ROTATION_DELAY_MS, MAX_ARCHIVES, executor ); DateTimeFormatter isoDateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; - FormattedLog formattedLog = FormattedLog.withUTCTimeZone().withDateTimeFormatter( isoDateTimeFormatter ) + FormattedLog formattedLog = FormattedLog.withZoneId( logTimeZone ) + .withDateTimeFormatter( isoDateTimeFormatter ) .toOutputStream( outputStreamSupplier ); formattedLog.setLevel( Level.DEBUG ); diff --git a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogging.java b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogging.java index 4fa1ad1cc6ef..3462ba7d0151 100644 --- a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogging.java +++ b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogging.java @@ -19,11 +19,12 @@ */ package org.neo4j.bolt.logging; +import io.netty.channel.Channel; + import java.io.File; +import java.time.ZoneId; import java.util.concurrent.Executor; -import io.netty.channel.Channel; - import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.kernel.configuration.Config; @@ -64,7 +65,8 @@ private static BoltMessageLog createBoltMessageLog( FileSystemAbstraction fs, Jo { File boltLogFile = config.get( GraphDatabaseSettings.bolt_log_filename ); Executor executor = scheduler.executor( JobScheduler.Groups.boltLogRotation ); - return new BoltMessageLog( fs, boltLogFile, executor ); + ZoneId logTimeZoneId = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + return new BoltMessageLog( fs, logTimeZoneId, boltLogFile, executor ); } catch ( Throwable t ) { diff --git a/community/consistency-check/src/main/java/org/neo4j/consistency/CheckConsistencyCommand.java b/community/consistency-check/src/main/java/org/neo4j/consistency/CheckConsistencyCommand.java index 11373f01129a..dc8560ac62ed 100644 --- a/community/consistency-check/src/main/java/org/neo4j/consistency/CheckConsistencyCommand.java +++ b/community/consistency-check/src/main/java/org/neo4j/consistency/CheckConsistencyCommand.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.time.ZoneId; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -36,6 +37,7 @@ import org.neo4j.consistency.checking.full.CheckConsistencyConfig; import org.neo4j.consistency.checking.full.ConsistencyCheckIncompleteException; import org.neo4j.dbms.DatabaseManagementSystemSettings; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.Strings; import org.neo4j.helpers.collection.MapUtil; import org.neo4j.helpers.progress.ProgressMonitorFactory; @@ -180,10 +182,11 @@ public void execute( String[] args ) throws IncorrectUsage, CommandFailed { File storeDir = backupPath.map( Path::toFile ).orElse( config.get( database_path ) ); checkDbState( storeDir, config ); + ZoneId logTimeZone = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); ConsistencyCheckService.Result consistencyCheckResult = consistencyCheckService .runFullConsistencyCheck( storeDir, config, ProgressMonitorFactory.textual( System.err ), - FormattedLogProvider.toOutputStream( System.out ), fileSystem, verbose, - reportDir.toFile(), + FormattedLogProvider.withZoneId( logTimeZone ).toOutputStream( System.out ), + fileSystem, verbose, reportDir.toFile(), new CheckConsistencyConfig( checkGraph, checkIndexes, checkLabelScanStore, checkPropertyOwners ) ); diff --git a/community/consistency-check/src/main/java/org/neo4j/consistency/ConsistencyCheckTool.java b/community/consistency-check/src/main/java/org/neo4j/consistency/ConsistencyCheckTool.java index 69419f7fa5f8..76e16a1ca929 100644 --- a/community/consistency-check/src/main/java/org/neo4j/consistency/ConsistencyCheckTool.java +++ b/community/consistency-check/src/main/java/org/neo4j/consistency/ConsistencyCheckTool.java @@ -22,11 +22,13 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.time.ZoneId; import java.util.List; import java.util.Map; import org.neo4j.consistency.checking.full.CheckConsistencyConfig; import org.neo4j.consistency.checking.full.ConsistencyCheckIncompleteException; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.Args; import org.neo4j.helpers.Strings; import org.neo4j.helpers.collection.MapUtil; @@ -111,7 +113,8 @@ ConsistencyCheckService.Result run( String... args ) throws ToolFailureException checkDbState( storeDir, tuningConfiguration ); - LogProvider logProvider = FormattedLogProvider.toOutputStream( systemOut ); + ZoneId logTimeZone = tuningConfiguration.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + LogProvider logProvider = FormattedLogProvider.withZoneId( logTimeZone ).toOutputStream( systemOut ); try { return consistencyCheckService.runFullConsistencyCheck( storeDir, tuningConfiguration, diff --git a/community/consistency-check/src/test/java/org/neo4j/consistency/ConsistencyCheckToolTest.java b/community/consistency-check/src/test/java/org/neo4j/consistency/ConsistencyCheckToolTest.java index e2c14b1f012b..357851a1276f 100644 --- a/community/consistency-check/src/test/java/org/neo4j/consistency/ConsistencyCheckToolTest.java +++ b/community/consistency-check/src/test/java/org/neo4j/consistency/ConsistencyCheckToolTest.java @@ -19,26 +19,37 @@ */ package org.neo4j.consistency; +import org.apache.commons.lang3.StringUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.RuleChain; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStreamReader; import java.io.PrintStream; +import java.time.ZoneOffset; import java.util.Properties; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.mockito.ArgumentCaptor; +import java.util.TimeZone; import org.neo4j.consistency.ConsistencyCheckTool.ToolFailureException; import org.neo4j.consistency.checking.full.CheckConsistencyConfig; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Transaction; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.progress.ProgressMonitorFactory; import org.neo4j.io.fs.DefaultFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.kernel.configuration.Config; import org.neo4j.logging.LogProvider; +import org.neo4j.logging.LogTimeZone; import org.neo4j.test.TestGraphDatabaseFactory; import org.neo4j.test.rule.TestDirectory; import org.neo4j.test.rule.fs.EphemeralFileSystemRule; @@ -82,6 +93,38 @@ public void runsConsistencyCheck() throws Exception anyBoolean(), any( CheckConsistencyConfig.class ) ); } + @Test + public void consistencyCheckerLogUseSystemTimezoneIfConfigurable() throws Exception + { + TimeZone defaultTimeZone = TimeZone.getDefault(); + try + { + ConsistencyCheckService service = mock( ConsistencyCheckService.class ); + Mockito.when( service.runFullConsistencyCheck( any( File.class ), any( Config.class ), + any( ProgressMonitorFactory.class ), any( LogProvider.class ), any( FileSystemAbstraction.class ), + eq( false ), any( CheckConsistencyConfig.class ) ) ) + .then( (Answer) invocationOnMock -> + { + LogProvider provider = invocationOnMock.getArgumentAt( 3, LogProvider.class ); + provider.getLog( "test" ).info( "testMessage" ); + return ConsistencyCheckService.Result.success( new File( StringUtils.EMPTY ) ); + } ); + File storeDir = storeDirectory.directory(); + File configFile = storeDirectory.file( Config.DEFAULT_CONFIG_FILE_NAME ); + Properties properties = new Properties(); + properties.setProperty( GraphDatabaseSettings.log_timezone.name(), LogTimeZone.SYSTEM.name() ); + properties.store( new FileWriter( configFile ), null ); + String[] args = {storeDir.getPath(), "-config", configFile.getPath()}; + + checkLogRecordTimeZone( service, args, 5, "+0500" ); + checkLogRecordTimeZone( service, args, -5, "-0500" ); + } + finally + { + TimeZone.setDefault( defaultTimeZone ); + } + } + @Test public void appliesDefaultTuningConfigurationForConsistencyChecker() throws Exception { @@ -177,6 +220,24 @@ public void failWhenStoreWasNonCleanlyShutdown() throws Exception runConsistencyCheckToolWith( fs.get(), storeDirectory.graphDbDir().getAbsolutePath() ); } + private void checkLogRecordTimeZone( ConsistencyCheckService service, String[] args, int i, String s ) + throws ToolFailureException, IOException + { + TimeZone.setDefault( TimeZone.getTimeZone( ZoneOffset.ofHours( i ) ) ); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream( outputStream ); + runConsistencyCheckToolWith( service, printStream, args ); + String logLine = readLogLine( outputStream ); + assertTrue( logLine, logLine.contains( s ) ); + } + + private String readLogLine( ByteArrayOutputStream outputStream ) throws IOException + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( outputStream.toByteArray() ); + BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( byteArrayInputStream ) ); + return bufferedReader.readLine(); + } + private void createGraphDbAndKillIt() throws Exception { final GraphDatabaseService db = new TestGraphDatabaseFactory() @@ -203,11 +264,17 @@ private void runConsistencyCheckToolWith( FileSystemAbstraction fileSystem, Stri private void runConsistencyCheckToolWith( ConsistencyCheckService consistencyCheckService, String... args ) throws ToolFailureException, IOException + { + runConsistencyCheckToolWith( consistencyCheckService, mock( PrintStream.class ), args ); + } + + private void runConsistencyCheckToolWith( ConsistencyCheckService + consistencyCheckService, PrintStream printStream, String... args ) throws ToolFailureException, IOException { try ( FileSystemAbstraction fileSystemAbstraction = new DefaultFileSystemAbstraction() ) { - new ConsistencyCheckTool( consistencyCheckService, fileSystemAbstraction, mock( PrintStream.class ), - mock( PrintStream.class ) ).run( args ); + new ConsistencyCheckTool( consistencyCheckService, fileSystemAbstraction, printStream, printStream ) + .run( args ); } } } diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java index 1eb83133faf6..d85f579eaa8c 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java @@ -45,6 +45,7 @@ import org.neo4j.kernel.configuration.ssl.SslPolicyConfigValidator; import org.neo4j.kernel.impl.cache.MonitorGc; import org.neo4j.logging.Level; +import org.neo4j.logging.LogTimeZone; import static org.neo4j.kernel.configuration.Settings.ANY; import static org.neo4j.kernel.configuration.Settings.BOOLEAN; @@ -300,6 +301,10 @@ public class GraphDatabaseSettings implements LoadableConfig public static final Setting store_internal_log_level = setting( "dbms.logs.debug.level", options( Level.class ), "INFO" ); + @Description( "Database logs timezone." ) + public static final Setting log_timezone = + setting( "dbms.logs.timezone", options( LogTimeZone.class ), LogTimeZone.UTC.name() ); + @Description( "Maximum time to wait for active transaction completion when rotating counts store" ) @Internal public static final Setting counts_store_rotation_timeout = diff --git a/community/kernel/src/main/java/org/neo4j/helpers/Format.java b/community/kernel/src/main/java/org/neo4j/helpers/Format.java index 81e98bd4e024..9d776e8f379d 100644 --- a/community/kernel/src/main/java/org/neo4j/helpers/Format.java +++ b/community/kernel/src/main/java/org/neo4j/helpers/Format.java @@ -29,6 +29,20 @@ public class Format { + private static final String[] BYTE_SIZES = { "B", "kB", "MB", "GB" }; + + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSZ"; + public static final String TIME_FORMAT = "HH:mm:ss.SSS"; + + /** + * Default time zone is UTC (+00:00) so that comparing timestamped logs from different + * sources is an easier task. + */ + public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone( "UTC" ); + + private static final ThreadLocalFormat DATE = new ThreadLocalFormat( DATE_FORMAT ); + private static final ThreadLocalFormat TIME = new ThreadLocalFormat( TIME_FORMAT ); + public static String date() { return date( DEFAULT_TIME_ZONE ); @@ -181,20 +195,6 @@ private Format() // No instances } - private static final String[] BYTE_SIZES = { "B", "kB", "MB", "GB" }; - - public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSZ"; - public static final String TIME_FORMAT = "HH:mm:ss.SSS"; - - /** - * Default time zone is UTC (+00:00) so that comparing timestamped logs from different - * sources is an easier task. - */ - public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone( "UTC" ); - - private static final ThreadLocalFormat DATE = new ThreadLocalFormat( DATE_FORMAT ); - private static final ThreadLocalFormat TIME = new ThreadLocalFormat( TIME_FORMAT ); - private static class ThreadLocalFormat extends ThreadLocal { private final String format; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java index 2a89b06e9f0a..32d98a1d807d 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/PlatformModule.java @@ -278,6 +278,7 @@ protected LogService createLogService( LogProvider userLogProvider ) builder.withLevel( debugContext, Level.DEBUG ); } builder.withDefaultLevel( config.get( GraphDatabaseSettings.store_internal_log_level ) ); + builder.withTimeZone( config.get( GraphDatabaseSettings.log_timezone ).getZoneId() ); File logFile = config.get( store_internal_log_path ); if ( !logFile.getParentFile().exists() ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/logging/StoreLogService.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/logging/StoreLogService.java index a76669e30910..6924eabfab83 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/logging/StoreLogService.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/logging/StoreLogService.java @@ -23,6 +23,8 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.time.ZoneId; +import java.time.ZoneOffset; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executor; @@ -53,6 +55,7 @@ public static class Builder }; private Map logLevels = new HashMap<>(); private Level defaultLevel = Level.INFO; + private ZoneId timeZoneId = ZoneOffset.UTC; private File debugLog; private Builder() @@ -94,6 +97,12 @@ public Builder withLevel( String context, Level level ) return this; } + public Builder withTimeZone( ZoneId timeZoneId ) + { + this.timeZoneId = timeZoneId; + return this; + } + public Builder withDefaultLevel( Level defaultLevel ) { this.defaultLevel = defaultLevel; @@ -112,7 +121,7 @@ public StoreLogService build( FileSystemAbstraction fileSystem ) throws IOExcept { throw new IllegalArgumentException( "Debug log can't be null; set its value using `withInternalLog`" ); } - return new StoreLogService( userLogProvider, fileSystem, debugLog, logLevels, defaultLevel, + return new StoreLogService( userLogProvider, fileSystem, debugLog, logLevels, defaultLevel, timeZoneId, internalLogRotationThreshold, internalLogRotationDelay, maxInternalLogArchives, rotationExecutor, rotationListener ); } @@ -143,6 +152,7 @@ private StoreLogService( LogProvider userLogProvider, File internalLog, Map logLevels, Level defaultLevel, + ZoneId logTimeZone, long internalLogRotationThreshold, long internalLogRotationDelay, int maxInternalLogArchives, @@ -154,7 +164,7 @@ private StoreLogService( LogProvider userLogProvider, fileSystem.mkdirs( internalLog.getParentFile() ); } - final FormattedLogProvider.Builder internalLogBuilder = FormattedLogProvider.withUTCTimeZone() + final FormattedLogProvider.Builder internalLogBuilder = FormattedLogProvider.withZoneId( logTimeZone ) .withDefaultLogLevel( defaultLevel ).withLogLevels( logLevels ); FormattedLogProvider internalLogProvider; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/pagecache/ConfigurableStandalonePageCacheFactory.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/pagecache/ConfigurableStandalonePageCacheFactory.java index cb9a8e30793f..2117acff3f03 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/pagecache/ConfigurableStandalonePageCacheFactory.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/pagecache/ConfigurableStandalonePageCacheFactory.java @@ -19,6 +19,8 @@ */ package org.neo4j.kernel.impl.pagecache; +import java.time.ZoneId; + import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; @@ -65,7 +67,8 @@ public static PageCache createPageCache( FileSystemAbstraction fileSystem, PageC PageCursorTracerSupplier pageCursorTracerSupplier, Config config ) { config.augmentDefaults( GraphDatabaseSettings.pagecache_memory, "8M" ); - FormattedLogProvider logProvider = FormattedLogProvider.toOutputStream( System.err ); + ZoneId logTimeZone = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + FormattedLogProvider logProvider = FormattedLogProvider.withZoneId( logTimeZone ).toOutputStream( System.err ); ConfiguringPageCacheFactory pageCacheFactory = new ConfiguringPageCacheFactory( fileSystem, config, pageCacheTracer, pageCursorTracerSupplier, logProvider.getLog( PageCache.class ) ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/configuration/SystemTimeZoneLoggingIT.java b/community/kernel/src/test/java/org/neo4j/kernel/configuration/SystemTimeZoneLoggingIT.java new file mode 100644 index 000000000000..16fdc41dbfc9 --- /dev/null +++ b/community/kernel/src/test/java/org/neo4j/kernel/configuration/SystemTimeZoneLoggingIT.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.configuration; + +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.ZoneOffset; +import java.util.TimeZone; + +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; +import org.neo4j.logging.LogTimeZone; +import org.neo4j.test.TestGraphDatabaseFactory; +import org.neo4j.test.rule.TestDirectory; + +import static org.junit.Assert.assertTrue; + +public class SystemTimeZoneLoggingIT +{ + @Rule + public TestDirectory testDirectory = TestDirectory.testDirectory(); + + @Test + public void databaseLogsUseSystemTimeZoneIfConfigure() throws IOException + { + TimeZone defaultTimeZone = TimeZone.getDefault(); + try + { + checkStartLogLine( 5, "+0500" ); + checkStartLogLine( -7, "-0700" ); + } + finally + { + TimeZone.setDefault( defaultTimeZone ); + } + } + + private void checkStartLogLine( int hoursShift, String timeZoneSuffix ) throws IOException + { + TimeZone.setDefault( TimeZone.getTimeZone( ZoneOffset.ofHours( hoursShift ) ) ); + File storeDir = testDirectory.directory( String.valueOf( hoursShift ) ); + GraphDatabaseService database = new TestGraphDatabaseFactory().newEmbeddedDatabaseBuilder( storeDir ) + .setConfig( GraphDatabaseSettings.log_timezone, LogTimeZone.SYSTEM.name() ).newGraphDatabase(); + database.shutdown(); + Path databasePath = storeDir.toPath(); + Path debugLog = Paths.get( "logs", "debug.log" ); + String debugLogLine = getLogLine( databasePath, debugLog ); + assertTrue( debugLogLine, debugLogLine.contains( timeZoneSuffix ) ); + } + + private String getLogLine( Path databasePath, Path logFilePath ) throws IOException + { + return Files.readAllLines( databasePath.resolve( logFilePath ) ).get( 0 ); + } +} diff --git a/community/logging/src/main/java/org/neo4j/logging/LogTimeZone.java b/community/logging/src/main/java/org/neo4j/logging/LogTimeZone.java new file mode 100644 index 000000000000..045a3031a765 --- /dev/null +++ b/community/logging/src/main/java/org/neo4j/logging/LogTimeZone.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.logging; + +import java.time.ZoneId; +import java.time.ZoneOffset; + +public enum LogTimeZone +{ + UTC + { + @Override + public ZoneId getZoneId() + { + return ZoneOffset.UTC; + } + }, + SYSTEM + { + @Override + public ZoneId getZoneId() + { + return ZoneId.systemDefault(); + } + }; + + public abstract ZoneId getZoneId(); +} diff --git a/community/server/src/main/java/org/neo4j/server/AbstractNeoServer.java b/community/server/src/main/java/org/neo4j/server/AbstractNeoServer.java index 1a57691e0b50..da0559081237 100644 --- a/community/server/src/main/java/org/neo4j/server/AbstractNeoServer.java +++ b/community/server/src/main/java/org/neo4j/server/AbstractNeoServer.java @@ -33,6 +33,7 @@ import java.util.regex.Pattern; import org.neo4j.graphdb.DependencyResolver; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.AdvertisedSocketAddress; import org.neo4j.helpers.ListenSocketAddress; import org.neo4j.helpers.RunCarefully; @@ -362,6 +363,7 @@ private void setUpHttpLogging() throws IOException AsyncRequestLog requestLog = new AsyncRequestLog( dependencyResolver.resolveDependency( FileSystemAbstraction.class ), + config.get( GraphDatabaseSettings.log_timezone ).getZoneId(), config.get( http_log_path ).toString(), config.get( http_logging_rotation_size ), config.get( http_logging_rotation_keep_number ) ); diff --git a/community/server/src/main/java/org/neo4j/server/ServerBootstrapper.java b/community/server/src/main/java/org/neo4j/server/ServerBootstrapper.java index 37ab3223a308..edf80597b8ca 100644 --- a/community/server/src/main/java/org/neo4j/server/ServerBootstrapper.java +++ b/community/server/src/main/java/org/neo4j/server/ServerBootstrapper.java @@ -172,6 +172,7 @@ protected abstract NeoServer createNeoServer( Config config, GraphDatabaseDepend private static LogProvider setupLogging( Config config ) { LogProvider userLogProvider = FormattedLogProvider.withoutRenderingContext() + .withZoneId( config.get( GraphDatabaseSettings.log_timezone ).getZoneId() ) .withDefaultLogLevel( config.get( GraphDatabaseSettings.store_internal_log_level ) ) .toOutputStream( System.out ); JULBridge.resetJUL(); diff --git a/community/server/src/main/java/org/neo4j/server/web/AsyncRequestLog.java b/community/server/src/main/java/org/neo4j/server/web/AsyncRequestLog.java index 2df0c96d21f2..9fbdbc4da3ef 100644 --- a/community/server/src/main/java/org/neo4j/server/web/AsyncRequestLog.java +++ b/community/server/src/main/java/org/neo4j/server/web/AsyncRequestLog.java @@ -27,6 +27,7 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.time.ZoneId; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Consumer; @@ -53,14 +54,15 @@ public class AsyncRequestLog private final ExecutorService asyncLogProcessingExecutor; private final AsyncEvents asyncEventProcessor; - public AsyncRequestLog( FileSystemAbstraction fs, String logFile, long rotationSize, int rotationKeepNumber ) + public AsyncRequestLog( FileSystemAbstraction fs, ZoneId logTimeZone, String logFile, long rotationSize, int rotationKeepNumber ) throws IOException { NamedThreadFactory threadFactory = new NamedThreadFactory( "HTTP-Log-Rotator", true ); ExecutorService rotationExecutor = Executors.newCachedThreadPool( threadFactory ); Supplier outputSupplier = new RotatingFileOutputStreamSupplier( fs, new File( logFile ), rotationSize, 0, rotationKeepNumber, rotationExecutor ); - FormattedLogProvider logProvider = FormattedLogProvider.withUTCTimeZone().toOutputStream( outputSupplier ); + FormattedLogProvider logProvider = FormattedLogProvider.withZoneId( logTimeZone ) + .toOutputStream( outputSupplier ); asyncLogProcessingExecutor = Executors.newSingleThreadExecutor( new NamedThreadFactory( "HTTP-Log-Writer" ) ); asyncEventProcessor = new AsyncEvents<>( this, this ); AsyncLogProvider asyncLogProvider = new AsyncLogProvider( asyncEventProcessor, logProvider ); diff --git a/enterprise/backup/src/main/java/org/neo4j/backup/BackupTool.java b/enterprise/backup/src/main/java/org/neo4j/backup/BackupTool.java index 309a4a731cba..4d9abb463364 100644 --- a/enterprise/backup/src/main/java/org/neo4j/backup/BackupTool.java +++ b/enterprise/backup/src/main/java/org/neo4j/backup/BackupTool.java @@ -24,11 +24,13 @@ import java.io.PrintStream; import java.net.URI; import java.net.URISyntaxException; +import java.time.ZoneId; import java.util.Map; import java.util.NoSuchElementException; import org.neo4j.backup.BackupService.BackupOutcome; import org.neo4j.com.ComException; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.Args; import org.neo4j.helpers.HostnamePort; import org.neo4j.helpers.Service; @@ -135,7 +137,7 @@ private BackupOutcome runBackupWithLegacyArgs( Args args ) throws ToolFailureExc long timeout = args.getDuration( TIMEOUT, BackupClient.BIG_READ_TIMEOUT ); - URI backupURI = resolveBackupUri( from, args ); + URI backupURI = resolveBackupUri( from, args, tuningConfiguration ); HostnamePort hostnamePort = newHostnamePort( backupURI ); @@ -237,7 +239,7 @@ private static Config readConfiguration( Args arguments ) throws ToolFailureExce return Config.defaults( specifiedConfig ); } - private static URI resolveBackupUri( String from, Args arguments ) throws ToolFailureException + private static URI resolveBackupUri( String from, Args arguments, Config config ) throws ToolFailureException { if ( from.contains( "," ) ) { @@ -246,7 +248,7 @@ private static URI resolveBackupUri( String from, Args arguments ) throws ToolFa checkNoSchemaIsPresent( from ); from = "ha://" + from; } - return resolveUriWithProvider( "ha", from, arguments ); + return resolveUriWithProvider( "ha", config, from, arguments ); } if ( !from.startsWith( "single://" ) ) { @@ -277,7 +279,7 @@ private static URI newURI( String uriString ) throws ToolFailureException } } - private static URI resolveUriWithProvider( String providerName, String from, Args args ) + private static URI resolveUriWithProvider( String providerName, Config config, String from, Args args ) throws ToolFailureException { BackupExtensionService service; @@ -292,8 +294,9 @@ private static URI resolveUriWithProvider( String providerName, String from, Arg try { - return service.resolve( from, args, new SimpleLogService( FormattedLogProvider.toOutputStream( System.out ), - NullLogProvider.getInstance() ) ); + ZoneId logTimeZone = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + FormattedLogProvider userLogProvider = FormattedLogProvider.withZoneId( logTimeZone ).toOutputStream( System.out ); + return service.resolve( from, args, new SimpleLogService( userLogProvider, NullLogProvider.getInstance() ) ); } catch ( Throwable t ) { diff --git a/enterprise/backup/src/main/java/org/neo4j/backup/OnlineBackupCommand.java b/enterprise/backup/src/main/java/org/neo4j/backup/OnlineBackupCommand.java index 33bdeac5b5d9..bddaaae48f7d 100644 --- a/enterprise/backup/src/main/java/org/neo4j/backup/OnlineBackupCommand.java +++ b/enterprise/backup/src/main/java/org/neo4j/backup/OnlineBackupCommand.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.time.ZoneId; import java.util.Optional; import org.neo4j.commandline.admin.AdminCommand; @@ -37,6 +38,7 @@ import org.neo4j.consistency.ConsistencyCheckService; import org.neo4j.consistency.ConsistencyCheckSettings; import org.neo4j.consistency.checking.full.CheckConsistencyConfig; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.HostnamePort; import org.neo4j.helpers.TimeUtil; import org.neo4j.helpers.collection.MapUtil; @@ -237,10 +239,11 @@ public void execute( String[] args ) throws IncorrectUsage, CommandFailed try { outsideWorld.stdOutLine( "Doing consistency check..." ); + ZoneId logTimeZone = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); ConsistencyCheckService.Result ccResult = consistencyCheckService .runFullConsistencyCheck( destination, config, ProgressMonitorFactory.textual( outsideWorld.errorStream() ), - FormattedLogProvider.toOutputStream( outsideWorld.outStream() ), + FormattedLogProvider.withZoneId( logTimeZone ).toOutputStream( outsideWorld.outStream() ), outsideWorld.fileSystem(), false, reportDir.toFile(), new CheckConsistencyConfig( checkGraph, checkIndexes, checkLabelScanStore, diff --git a/enterprise/management/src/main/java/org/neo4j/management/impl/DiagnosticsBean.java b/enterprise/management/src/main/java/org/neo4j/management/impl/DiagnosticsBean.java index 39121cbdd917..c2f6308a6c03 100644 --- a/enterprise/management/src/main/java/org/neo4j/management/impl/DiagnosticsBean.java +++ b/enterprise/management/src/main/java/org/neo4j/management/impl/DiagnosticsBean.java @@ -20,19 +20,21 @@ package org.neo4j.management.impl; import java.io.StringWriter; +import java.time.ZoneId; import java.util.ArrayList; import java.util.List; - import javax.management.NotCompliantMBeanException; import org.neo4j.graphdb.DependencyResolver; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.Service; import org.neo4j.jmx.impl.ManagementBeanProvider; import org.neo4j.jmx.impl.ManagementData; import org.neo4j.jmx.impl.Neo4jMBean; -import org.neo4j.logging.FormattedLog; +import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.info.DiagnosticsManager; import org.neo4j.kernel.info.DiagnosticsProvider; +import org.neo4j.logging.FormattedLog; import org.neo4j.management.Diagnostics; @Service.Implementation( ManagementBeanProvider.class ) @@ -52,11 +54,13 @@ protected Neo4jMBean createMBean( ManagementData management ) throws NotComplian private static class DiagnosticsImpl extends Neo4jMBean implements Diagnostics { private final DiagnosticsManager diagnostics; + private Config config; DiagnosticsImpl( ManagementData management ) throws NotCompliantMBeanException { super( management ); DependencyResolver resolver = management.getKernelData().graphDatabase().getDependencyResolver(); + config = resolver.resolveDependency( Config.class ); this.diagnostics = resolver.resolveDependency( DiagnosticsManager.class ); } @@ -87,7 +91,9 @@ public void dumpToLog( String providerId ) public String dumpAll( ) { StringWriter stringWriter = new StringWriter(); - diagnostics.dumpAll( FormattedLog.withUTCTimeZone().toWriter( stringWriter ) ); + ZoneId zoneId = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + FormattedLog.Builder logBuilder = FormattedLog.withZoneId( zoneId ); + diagnostics.dumpAll( logBuilder.toWriter( stringWriter ) ); return stringWriter.toString(); } @@ -95,7 +101,9 @@ public String dumpAll( ) public String extract( String providerId ) { StringWriter stringWriter = new StringWriter(); - diagnostics.extract( providerId, FormattedLog.withUTCTimeZone().toWriter( stringWriter ) ); + ZoneId zoneId = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + FormattedLog.Builder logBuilder = FormattedLog.withZoneId( zoneId ); + diagnostics.extract( providerId, logBuilder.toWriter( stringWriter ) ); return stringWriter.toString(); } } diff --git a/enterprise/query-logging/src/main/java/org/neo4j/kernel/impl/query/QueryLoggerKernelExtension.java b/enterprise/query-logging/src/main/java/org/neo4j/kernel/impl/query/QueryLoggerKernelExtension.java index 809426092169..e450f48d83dc 100644 --- a/enterprise/query-logging/src/main/java/org/neo4j/kernel/impl/query/QueryLoggerKernelExtension.java +++ b/enterprise/query-logging/src/main/java/org/neo4j/kernel/impl/query/QueryLoggerKernelExtension.java @@ -22,6 +22,7 @@ import java.io.Closeable; import java.io.File; import java.io.OutputStream; +import java.time.ZoneId; import java.util.EnumSet; import java.util.function.BooleanSupplier; import java.util.function.LongSupplier; @@ -85,6 +86,7 @@ public void init() throws Throwable BooleanSupplier queryLogEnabled = () -> config.get( GraphDatabaseSettings.log_queries ); Long rotationThreshold = config.get( GraphDatabaseSettings.log_queries_rotation_threshold ); int maxArchives = config.get( GraphDatabaseSettings.log_queries_max_archives ); + ZoneId logTimeZoneId = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); EnumSet flags = EnumSet.noneOf( QueryLogEntryContent.class ); for ( QueryLogEntryContent flag : QueryLogEntryContent.values() ) { @@ -94,7 +96,7 @@ public void init() throws Throwable } } - FormattedLog.Builder logBuilder = FormattedLog.withUTCTimeZone(); + FormattedLog.Builder logBuilder = FormattedLog.withZoneId( logTimeZoneId ); Log log; if ( rotationThreshold == 0 ) { diff --git a/enterprise/query-logging/src/test/java/org/neo4j/kernel/impl/query/QueryLoggerIT.java b/enterprise/query-logging/src/test/java/org/neo4j/kernel/impl/query/QueryLoggerIT.java index 6cdcbe163f2b..8684b2919b7a 100644 --- a/enterprise/query-logging/src/test/java/org/neo4j/kernel/impl/query/QueryLoggerIT.java +++ b/enterprise/query-logging/src/test/java/org/neo4j/kernel/impl/query/QueryLoggerIT.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -38,6 +39,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.TimeZone; import java.util.stream.Collectors; import org.neo4j.graphdb.GraphDatabaseService; @@ -56,6 +58,7 @@ import org.neo4j.kernel.impl.factory.GraphDatabaseFacade; import org.neo4j.kernel.impl.query.clientconnection.ClientConnectionInfo; import org.neo4j.logging.AssertableLogProvider; +import org.neo4j.logging.LogTimeZone; import org.neo4j.server.security.enterprise.auth.EmbeddedInteraction; import org.neo4j.test.TestEnterpriseGraphDatabaseFactory; import org.neo4j.test.rule.TestDirectory; @@ -70,6 +73,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.neo4j.helpers.collection.MapUtil.stringMap; import static org.neo4j.kernel.api.security.AuthSubject.AUTH_DISABLED; @@ -389,6 +393,37 @@ public void canBeEnabledAndDisabledAtRuntime() throws Exception assertEquals( 2, strings.size() ); } + @Test + public void logQueriesWithSystemTimeZoneIsConfigured() throws IOException + { + TimeZone defaultTimeZone = TimeZone.getDefault(); + try + { + TimeZone.setDefault( TimeZone.getTimeZone( ZoneOffset.ofHours( 5 ) ) ); + executeSingleQueryWithTimeZoneLog(); + TimeZone.setDefault( TimeZone.getTimeZone( ZoneOffset.ofHours( -5 ) ) ); + executeSingleQueryWithTimeZoneLog(); + List allQueries = readAllLinesSilent( logFilename ); + assertTrue( allQueries.get( 0 ).contains( "+0500" ) ); + assertTrue( allQueries.get( 1 ).contains( "-0500" ) ); + } + finally + { + TimeZone.setDefault( defaultTimeZone ); + } + } + + private void executeSingleQueryWithTimeZoneLog() + { + GraphDatabaseFacade database = + (GraphDatabaseFacade) databaseBuilder.setConfig( GraphDatabaseSettings.log_queries, Settings.TRUE ) + .setConfig( GraphDatabaseSettings.log_timezone, LogTimeZone.SYSTEM.name() ) + .setConfig( GraphDatabaseSettings.logs_directory, logsDirectory.getPath() ) + .newGraphDatabase(); + database.execute( QUERY ).close(); + database.shutdown(); + } + private void executeQueryAndShutdown( GraphDatabaseService database ) { executeQueryAndShutdown( database, QUERY, Collections.emptyMap() ); diff --git a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/log/SecurityLog.java b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/log/SecurityLog.java index 59792f68b49e..0eec8b3a81ed 100644 --- a/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/log/SecurityLog.java +++ b/enterprise/security/src/main/java/org/neo4j/server/security/enterprise/log/SecurityLog.java @@ -21,18 +21,20 @@ import java.io.File; import java.io.IOException; +import java.time.ZoneId; import java.util.concurrent.Executor; import java.util.function.Consumer; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.kernel.api.security.SecurityContext; import org.neo4j.kernel.configuration.Config; -import org.neo4j.scheduler.JobScheduler; import org.neo4j.kernel.lifecycle.LifecycleAdapter; import org.neo4j.logging.FormattedLog; import org.neo4j.logging.Log; import org.neo4j.logging.Logger; import org.neo4j.logging.RotatingFileOutputStreamSupplier; +import org.neo4j.scheduler.JobScheduler; import org.neo4j.server.security.enterprise.configuration.SecuritySettings; import static org.neo4j.helpers.Strings.escape; @@ -44,9 +46,11 @@ public class SecurityLog extends LifecycleAdapter implements Log public SecurityLog( Config config, FileSystemAbstraction fileSystem, Executor executor ) throws IOException { - FormattedLog.Builder builder = FormattedLog.withUTCTimeZone(); + ZoneId logTimeZoneId = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); File logFile = config.get( SecuritySettings.security_log_filename ); + FormattedLog.Builder builder = FormattedLog.withZoneId( logTimeZoneId ); + rotatingSupplier = new RotatingFileOutputStreamSupplier( fileSystem, logFile, config.get( SecuritySettings.store_security_log_rotation_threshold ), config.get( SecuritySettings.store_security_log_rotation_delay ).toMillis(), diff --git a/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/log/SecurityLogTest.java b/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/log/SecurityLogTest.java index e2f057b7b5d8..a60f952fb97f 100644 --- a/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/log/SecurityLogTest.java +++ b/enterprise/security/src/test/java/org/neo4j/server/security/enterprise/log/SecurityLogTest.java @@ -24,11 +24,15 @@ import java.io.File; import java.io.IOException; +import java.time.ZoneOffset; import java.util.Scanner; +import java.util.TimeZone; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.kernel.configuration.Config; import org.neo4j.logging.Level; +import org.neo4j.logging.LogTimeZone; import org.neo4j.server.security.enterprise.configuration.SecuritySettings; import org.neo4j.test.rule.fs.EphemeralFileSystemRule; @@ -69,6 +73,35 @@ public void shouldRotateLog() throws IOException assertThat( archiveLines, array( containsString( "line 1" ) ) ); } + @Test + public void logUseSystemTimeZoneIfConfigured() throws Exception + { + TimeZone defaultTimeZone = TimeZone.getDefault(); + try + { + checkLogTimeZone( 4, "+0400" ); + checkLogTimeZone( -8, "-0800" ); + } + finally + { + TimeZone.setDefault( defaultTimeZone ); + } + } + + private void checkLogTimeZone( int hoursShift, String timeZoneSuffix ) throws Exception + { + TimeZone.setDefault( TimeZone.getTimeZone( ZoneOffset.ofHours( hoursShift ) ) ); + Config timeZoneConfig = Config.defaults( GraphDatabaseSettings.log_timezone, LogTimeZone.SYSTEM.name() ); + SecurityLog securityLog = new SecurityLog( timeZoneConfig, fileSystemRule.get(), Runnable::run ); + securityLog.info( "line 1" ); + + FileSystemAbstraction fs = fileSystemRule.get(); + File activeLogFile = timeZoneConfig.get( SecuritySettings.security_log_filename ); + String[] activeLines = readLogFile( fs, activeLogFile ); + assertThat( activeLines, array( containsString( timeZoneSuffix ) ) ); + fileSystemRule.clear(); + } + @Test public void shouldHonorLogLevel() throws Throwable { diff --git a/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/ArbiterBootstrapper.java b/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/ArbiterBootstrapper.java index ae0319eb8df3..fc917f839b75 100644 --- a/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/ArbiterBootstrapper.java +++ b/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/ArbiterBootstrapper.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.IOException; +import java.time.ZoneId; import java.util.Map; import java.util.Optional; import java.util.Timer; @@ -32,6 +33,7 @@ import org.neo4j.cluster.client.ClusterClientModule; import org.neo4j.cluster.protocol.election.NotElectableElectionCredentialsProvider; import org.neo4j.function.Predicates; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.DefaultFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemLifecycleAdapter; @@ -129,7 +131,9 @@ private static LogService logService( FileSystemAbstraction fileSystem, Config c File logFile = config.get( store_internal_log_path ); try { - return StoreLogService.withUserLogProvider( FormattedLogProvider.toOutputStream( System.out ) ) + ZoneId zoneId = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + FormattedLogProvider logProvider = FormattedLogProvider.withZoneId( zoneId ).toOutputStream( System.out ); + return StoreLogService.withUserLogProvider( logProvider ) .withInternalLog( logFile ) .build( fileSystem ); } diff --git a/packaging/neo4j-desktop/src/main/java/org/neo4j/desktop/runtime/DatabaseActions.java b/packaging/neo4j-desktop/src/main/java/org/neo4j/desktop/runtime/DatabaseActions.java index d22897e204c4..ab1c5c19d5bb 100644 --- a/packaging/neo4j-desktop/src/main/java/org/neo4j/desktop/runtime/DatabaseActions.java +++ b/packaging/neo4j-desktop/src/main/java/org/neo4j/desktop/runtime/DatabaseActions.java @@ -20,12 +20,14 @@ package org.neo4j.desktop.runtime; import java.net.BindException; +import java.time.ZoneId; import java.util.HashSet; import java.util.Set; import org.neo4j.desktop.model.DesktopModel; import org.neo4j.desktop.model.exceptions.UnableToStartServerException; import org.neo4j.desktop.ui.MainWindow; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.kernel.GraphDatabaseDependencies; import org.neo4j.kernel.StoreLockException; import org.neo4j.kernel.configuration.Config; @@ -61,7 +63,8 @@ public void start() throws UnableToStartServerException Config config = model.getConfig(); Monitors monitors = new Monitors(); - LogProvider userLogProvider = FormattedLogProvider.toOutputStream( System.out ); + ZoneId logTimeZone = config.get( GraphDatabaseSettings.log_timezone ).getZoneId(); + LogProvider userLogProvider = FormattedLogProvider.withZoneId( logTimeZone ).toOutputStream( System.out ); GraphDatabaseDependencies dependencies = GraphDatabaseDependencies.newDependencies() .userLogProvider( userLogProvider ).monitors( monitors );