Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always create events log when profiling #8337

Merged
merged 2 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/profiler/engine-startup.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Start `project-manager` with following options to record first 20s of the Enso
engine startup sequence:

```
$ project-manager --profiling-events-log-path=start.log --profiling-path=start.npss --profiling-time=20
$ project-manager --profiling-path=start.npss --profiling-time=20
```

Let the IDE connect to just launched `project-manager` - e.g. start the IDE with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class MainModule(serverConfig: LanguageServerConfig, logLevel: Level) {
)

val runtimeEventsMonitor =
languageServerConfig.profiling.runtimeEventsLogPath match {
languageServerConfig.profiling.profilingEventsLogPath match {
case Some(path) =>
val out = new PrintStream(path.toFile, StandardCharsets.UTF_8)
new RuntimeEventsMonitor(out)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,41 @@
package org.enso.languageserver.boot

import org.apache.commons.io.FilenameUtils

import java.nio.file.Path

import scala.concurrent.duration.FiniteDuration

/** Application profiling configuration.
*
* @param runtimeEventsLogPath the path to the runtime events log file
* @param profilingPath the path to the profiling output file
* @param profilingTime limit the profiling duration, as an infinite profiling
* duration may cause out-of-memory errors.
*/
case class ProfilingConfig(
runtimeEventsLogPath: Option[Path] = None,
profilingPath: Option[Path] = None,
profilingTime: Option[FiniteDuration] = None
)
) {

/** Creates the path to the runtime events log with the same name as
* `profilingPath` but with the `.log` extension.
*
* @return the path to the runtime events log file
*/
def profilingEventsLogPath: Option[Path] =
profilingPath.map { path =>
val profilingDirectory = path.getParent
val profilingFileName = path.getFileName.toString
val profilingFileExtension = FilenameUtils.getExtension(profilingFileName)
val eventsLogFileName =
profilingFileName.stripSuffix(
profilingFileExtension
) + ProfilingConfig.EventsLogExtension

profilingDirectory.resolve(eventsLogFileName)
}
}
object ProfilingConfig {

private val EventsLogExtension = "log"
}
23 changes: 2 additions & 21 deletions engine/runner/src/main/scala/org/enso/runner/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ object Main {
private val PROFILING_PATH = "profiling-path"
private val PROFILING_TIME = "profiling-time"
private val LANGUAGE_SERVER_OPTION = "server"
private val LANGUAGE_SERVER_PROFILING_EVENTS_LOG_PATH =
"server-profiling-events-log-path"
private val DAEMONIZE_OPTION = "daemon"
private val INTERFACE_OPTION = "interface"
private val RPC_PORT_OPTION = "rpc-port"
Expand Down Expand Up @@ -201,16 +199,9 @@ object Main {
.longOpt(PROFILING_TIME)
.desc("The duration in seconds limiting the profiling time.")
.build()
val lsProfilingEventsLogPathOption = CliOption.builder
.hasArg(true)
.numberOfArgs(1)
.argName("file")
.longOpt(LANGUAGE_SERVER_PROFILING_EVENTS_LOG_PATH)
.desc("The path to the runtime events log file.")
.build()
val deamonizeOption = CliOption.builder
.longOpt(DAEMONIZE_OPTION)
.desc("Deamonize Language Server")
.desc("Daemonize Language Server")
.build()
val interfaceOption = CliOption.builder
.longOpt(INTERFACE_OPTION)
Expand Down Expand Up @@ -427,7 +418,6 @@ object Main {
.addOption(lsOption)
.addOption(lsProfilingPathOption)
.addOption(lsProfilingTimeOption)
.addOption(lsProfilingEventsLogPathOption)
.addOption(deamonizeOption)
.addOption(interfaceOption)
.addOption(rpcPortOption)
Expand Down Expand Up @@ -1026,16 +1016,7 @@ object Main {
profilingTime <- Either
.catchNonFatal(profilingTimeStr.map(_.toInt.seconds))
.leftMap(_ => "Profiling time should be an integer")
profilingEventsLogPathStr =
Option(line.getOptionValue(LANGUAGE_SERVER_PROFILING_EVENTS_LOG_PATH))
profilingEventsLogPath <- Either
.catchNonFatal(profilingEventsLogPathStr.map(Paths.get(_)))
.leftMap(_ => "Profiling events log path is invalid")
} yield ProfilingConfig(
profilingEventsLogPath,
profilingPath,
profilingTime
)
} yield ProfilingConfig(profilingPath, profilingTime)
}

/** Prints the version of the Enso executable.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import scala.util.Try

object Cli {

val JSON_OPTION = "json"
val HELP_OPTION = "help"
val NO_LOG_MASKING = "no-log-masking"
val VERBOSE_OPTION = "verbose"
val VERSION_OPTION = "version"
val PROFILING_PATH = "profiling-path"
val PROFILING_TIME = "profiling-time"
val PROFILING_EVENTS_LOG_PATH = "profiling-events-log-path"
val JSON_OPTION = "json"
val HELP_OPTION = "help"
val NO_LOG_MASKING = "no-log-masking"
val VERBOSE_OPTION = "verbose"
val VERSION_OPTION = "version"
val PROFILING_PATH = "profiling-path"
val PROFILING_TIME = "profiling-time"

object option {

Expand Down Expand Up @@ -64,16 +63,6 @@ object Cli {
.longOpt(PROFILING_TIME)
.desc("The duration in seconds limiting the application profiling time.")
.build()

val profilingEventsLogPath: cli.Option = cli.Option.builder
.hasArg(true)
.numberOfArgs(1)
.argName("file")
.longOpt(PROFILING_EVENTS_LOG_PATH)
.desc(
"The path to the runtime events log file. Enables the runtime events logging."
)
.build()
}

val options: cli.Options =
Expand All @@ -85,7 +74,6 @@ object Cli {
.addOption(option.noLogMasking)
.addOption(option.profilingPath)
.addOption(option.profilingTime)
.addOption(option.profilingEventsLogPath)

/** Parse the command line options. */
def parse(args: Array[String]): Either[String, cli.CommandLine] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,37 +189,10 @@ object ProjectManager extends ZIOAppDefault with LazyLogging {
)
}

val parseProfilingEventsLogPath = ZIO
.attempt {
Option(options.getOptionValue(Cli.PROFILING_EVENTS_LOG_PATH))
.map(Paths.get(_).toAbsolutePath)
}
.flatMap {
case pathOpt @ Some(path) =>
ZIO.ifZIO(ZIO.attempt(Files.isDirectory(path)))(
onTrue = printLineError(
s"Error: ${Cli.PROFILING_EVENTS_LOG_PATH} is a directory: $path"
) *>
ZIO.fail(new FileAlreadyExistsException(path.toString)),
onFalse = ZIO.succeed(pathOpt)
)
case None =>
ZIO.succeed(None)
}
.catchAll { err =>
printLineError(s"Invalid ${Cli.PROFILING_EVENTS_LOG_PATH} argument.") *>
ZIO.fail(err)
}

for {
profilingEventsLogPath <- parseProfilingEventsLogPath
profilingPath <- parseProfilingPath
profilingTime <- parseProfilingTime
} yield ProjectManagerOptions(
profilingEventsLogPath,
profilingPath,
profilingTime
)
profilingPath <- parseProfilingPath
profilingTime <- parseProfilingTime
} yield ProjectManagerOptions(profilingPath, profilingTime)
}

/** The main function of the application, which will be passed the command-line
Expand All @@ -240,7 +213,6 @@ object ProjectManager extends ZIOAppDefault with LazyLogging {
logLevel <- setupLogging(verbosity, logMasking)
procConf = MainProcessConfig(
logLevel,
opts.profilingRuntimeEventsLog,
opts.profilingPath,
opts.profilingTime
)
Expand Down Expand Up @@ -271,7 +243,7 @@ object ProjectManager extends ZIOAppDefault with LazyLogging {
()
}
.catchAll { exception =>
printLineError(s"Failed to setup logger: ${exception.getMessage()}")
printLineError(s"Failed to setup logger: ${exception.getMessage}")
}
.as(level)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ import scala.concurrent.duration.FiniteDuration

/** The runtime options.
*
* @param profilingRuntimeEventsLog the path to the runtime events log file
* @param profilingPath the path to the profiling output file
* @param profilingTime the time limiting the profiling duration
*/
case class ProjectManagerOptions(
profilingRuntimeEventsLog: Option[Path],
profilingPath: Option[Path],
profilingTime: Option[FiniteDuration]
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ object configuration {
* main project manager process.
*
* @param logLevel the logging level
* @param profilingEventsLogPath the path to the runtime events log file
* @param profilingPath the path to the profiling out file
* @param profilingTime the time limiting the profiling duration
*/
case class MainProcessConfig(
logLevel: Level,
profilingEventsLogPath: Option[Path],
profilingPath: Option[Path],
profilingTime: Option[FiniteDuration]
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,12 @@ object ExecutorWithUnlimitedPool extends LanguageServerExecutor {
val profilingTimeArguments =
descriptor.profilingTime.toSeq
.flatMap(time => Seq("--profiling-time", time.toSeconds.toString))
val profilingEventsLogPathArguments =
descriptor.profilingEventsLogPath.toSeq
.flatMap(path =>
Seq("--server-profiling-events-log-path", path.toString)
)
val startupArgs =
if (descriptor.skipGraalVMUpdater) Seq("--skip-graalvm-updater")
else Seq()
val additionalArguments =
profilingPathArguments ++
profilingTimeArguments ++
profilingEventsLogPathArguments ++
startupArgs
val runSettings = runner
.startLanguageServer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ class LanguageServerController(
engineVersion = engineVersion,
jvmSettings = distributionConfiguration.defaultJVMSettings,
discardOutput = distributionConfiguration.shouldDiscardChildOutput,
profilingEventsLogPath = processConfig.profilingEventsLogPath,
profilingPath = processConfig.profilingPath,
profilingTime = processConfig.profilingTime,
deferredLoggingServiceEndpoint = loggingServiceDescriptor.getEndpoint,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import scala.concurrent.duration.FiniteDuration
* @param jvmSettings settings to use for the JVM that will host the engine
* @param discardOutput specifies if the process output should be discarded or
* printed to parent's streams
* @param profilingEventsLogPath the path to the runtime events log file
* @param profilingPath the language server profiling file path
* @param profilingTime the time limiting the profiling duration
* @param deferredLoggingServiceEndpoint a future that is completed once the
Expand All @@ -44,7 +43,6 @@ case class LanguageServerDescriptor(
engineVersion: SemVer,
jvmSettings: JVMSettings,
discardOutput: Boolean,
profilingEventsLogPath: Option[Path],
profilingPath: Option[Path],
profilingTime: Option[FiniteDuration],
deferredLoggingServiceEndpoint: Future[Option[URI]],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,9 @@ class BaseServerSpec extends JsonRpcServerTestKit with BeforeAndAfterAll {

val processConfig: MainProcessConfig =
MainProcessConfig(
logLevel = if (debugLogs) Level.TRACE else Level.ERROR,
profilingPath = profilingPath,
profilingTime = None,
profilingEventsLogPath = None
logLevel = if (debugLogs) Level.TRACE else Level.ERROR,
profilingPath = profilingPath,
profilingTime = None
)

val testClock =
Expand Down
Loading