PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/community/kernel/src/test/java/org/neo4j/qa/tooling/DumpProcessInformation.java

https://github.com/apcj/neo4j
Java | 159 lines | 120 code | 16 blank | 23 comment | 10 complexity | b16991c1ccfc7b66b58fdc80c163f2d9 MD5 | raw file
Possible License(s): AGPL-1.0, MPL-2.0-no-copyleft-exception, GPL-2.0, JSON, LGPL-2.1, GPL-3.0, MIT, BSD-3-Clause, Apache-2.0, AGPL-3.0, CC-BY-SA-3.0
  1. /**
  2. * Copyright (c) 2002-2013 "Neo Technology,"
  3. * Network Engine for Objects in Lund AB [http://neotechnology.com]
  4. *
  5. * This file is part of Neo4j.
  6. *
  7. * Neo4j is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. package org.neo4j.qa.tooling;
  21. import java.io.BufferedReader;
  22. import java.io.File;
  23. import java.io.InputStreamReader;
  24. import java.io.PrintStream;
  25. import java.util.ArrayList;
  26. import java.util.Collection;
  27. import org.neo4j.helpers.Args;
  28. import org.neo4j.helpers.Pair;
  29. import org.neo4j.helpers.Predicate;
  30. import org.neo4j.kernel.impl.util.StringLogger;
  31. import org.neo4j.kernel.logging.Logging;
  32. import org.neo4j.kernel.logging.SystemOutLogging;
  33. import static org.neo4j.helpers.Format.time;
  34. import static org.neo4j.helpers.Predicates.in;
  35. public class DumpProcessInformation
  36. {
  37. public static void main( String[] args ) throws Exception
  38. {
  39. Args arg = new Args( args == null ? new String[0] : args );
  40. boolean doHeapDump = arg.getBoolean( "heap", false, true );
  41. String[] containing = arg.orphans().toArray( new String[arg.orphans().size()] );
  42. String dumpDir = arg.get( "dir", "data" );
  43. new DumpProcessInformation( new SystemOutLogging(), new File( dumpDir ) ).dumpRunningProcesses(
  44. doHeapDump, containing );
  45. }
  46. private final StringLogger logger;
  47. private final File outputDirectory;
  48. public DumpProcessInformation( Logging logging, File outputDirectory )
  49. {
  50. this.logger = logging.getMessagesLog( getClass() );
  51. this.outputDirectory = outputDirectory;
  52. }
  53. public void dumpRunningProcesses( boolean includeHeapDump, String... javaPidsContainingClassNames )
  54. throws Exception
  55. {
  56. outputDirectory.mkdirs();
  57. for ( Pair<Long, String> pid : getJPids( in( javaPidsContainingClassNames ) ) )
  58. {
  59. doThreadDump( pid );
  60. if ( includeHeapDump )
  61. {
  62. doHeapDump( pid );
  63. }
  64. }
  65. }
  66. public File doThreadDump( Pair<Long, String> pid ) throws Exception
  67. {
  68. File outputFile = new File( outputDirectory, fileName( "threaddump", pid ) );
  69. logger.info( "Creating thread dump of " + pid + " to " + outputFile.getAbsolutePath() );
  70. String[] cmdarray = new String[] {"jstack", "" + pid.first()};
  71. Process process = Runtime.getRuntime().exec( cmdarray );
  72. writeProcessOutputToFile( process, outputFile );
  73. return outputFile;
  74. }
  75. public void doHeapDump( Pair<Long, String> pid ) throws Exception
  76. {
  77. File outputFile = new File( outputDirectory, fileName( "heapdump", pid ) );
  78. logger.info( "Creating heap dump of " + pid + " to " + outputFile.getAbsolutePath() );
  79. String[] cmdarray = new String[] {"jmap", "-dump:file=" + outputFile.getAbsolutePath(), "" + pid.first() };
  80. Runtime.getRuntime().exec( cmdarray ).waitFor();
  81. }
  82. public void doThreadDump( Predicate<String> processFilter ) throws Exception
  83. {
  84. for ( Pair<Long,String> pid : getJPids( processFilter ) )
  85. {
  86. doThreadDump( pid );
  87. }
  88. }
  89. public Collection<Pair<Long, String>> getJPids( Predicate<String> filter ) throws Exception
  90. {
  91. Process process = Runtime.getRuntime().exec( new String[] { "jps", "-l" } );
  92. BufferedReader reader = new BufferedReader( new InputStreamReader( process.getInputStream() ) );
  93. String line = null;
  94. Collection<Pair<Long, String>> jPids = new ArrayList<>(), excludedJPids = new ArrayList<>();
  95. while ( (line = reader.readLine()) != null )
  96. {
  97. int spaceIndex = line.indexOf( ' ' );
  98. String name = line.substring( spaceIndex + 1 );
  99. // Work-around for a windows problem where if your java.exe is in a directory
  100. // containing spaces the value in the second column from jps output will be
  101. // something like "C:\Program" if it was under "C:\Program Files\Java..."
  102. // If that's the case then use the PID instead
  103. if ( name.contains( ":" ) )
  104. {
  105. String pid = line.substring( 0, spaceIndex );
  106. name = pid;
  107. }
  108. Pair<Long, String> pid = Pair.of( Long.parseLong( line.substring( 0, spaceIndex ) ), name );
  109. if ( name.contains( DumpProcessInformation.class.getSimpleName() ) ||
  110. name.contains( "Jps" ) ||
  111. name.contains( "eclipse.equinox" ) ||
  112. !filter.accept( name ) )
  113. {
  114. excludedJPids.add( pid );
  115. continue;
  116. }
  117. jPids.add( pid );
  118. }
  119. process.waitFor();
  120. logger.info( "Found jPids:" + jPids + ", excluded:" + excludedJPids );
  121. return jPids;
  122. }
  123. private void writeProcessOutputToFile( Process process, File outputFile ) throws Exception
  124. {
  125. BufferedReader reader = new BufferedReader( new InputStreamReader( process.getInputStream() ) );
  126. String line = null;
  127. try ( PrintStream out = new PrintStream( outputFile ) )
  128. {
  129. while ( (line = reader.readLine()) != null )
  130. {
  131. out.println( line );
  132. }
  133. }
  134. process.waitFor();
  135. }
  136. private static String fileName( String category, Pair<Long,String> pid )
  137. {
  138. return time().replace( ':', '_' ).replace( '.', '_' ) +
  139. "-" + category +
  140. "-" + pid.first() +
  141. "-" + pid.other();
  142. }
  143. }