Skip to content

Commit

Permalink
feat(jetbrains): show workspace resources
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrea Falzetti committed Aug 11, 2022
1 parent 6f8ed36 commit 54bdfeb
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,31 @@ class GitpodManager : Disposable {
}
}
}

var resourceStatus: Status.ResourcesStatusResponse? = null

private val metricsJob = GlobalScope.launch {
if (application.isHeadlessEnvironment) {
return@launch
}
val status = StatusServiceGrpc.newFutureStub(supervisorChannel)
while (isActive) {
try {
val f = status.resourcesStatus(Status.ResourcesStatuRequest.getDefaultInstance())
resourceStatus = f.asDeferred().await()
} catch (t: Throwable) {
if (t is CancellationException) {
throw t
}
thisLogger().error("gitpod: failed to retrieve resource status: ", t)
}
delay(1000L)
}
}
init {
lifetime.onTerminationOrNow {
metricsJob.cancel()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

package io.gitpod.jetbrains.remote.latest

import com.jetbrains.ide.model.uiautomation.BeControl
import com.jetbrains.rd.ui.bedsl.dsl.VerticalGridBuilder
import com.jetbrains.rd.ui.bedsl.dsl.verticalGrid
import com.jetbrains.rd.util.lifetime.Lifetime
import com.jetbrains.rd.util.reactive.Property
import com.jetbrains.rdserver.diagnostics.BackendDiagnosticsService
import com.jetbrains.rdserver.unattendedHost.customization.controlCenter.performance.MetricControlProvider
import com.jetbrains.rdserver.unattendedHost.customization.controlCenter.performance.createProgressBar
import com.jetbrains.rdserver.unattendedHost.customization.controlCenter.performance.createProgressRow

class GitpodMetricControlProvider : MetricControlProvider {
override val id: String = "gitpodMetricsControl"
override fun getControl(lifetime: Lifetime): BeControl {
return verticalGrid {
val backendDiagnosticsService = BackendDiagnosticsService.Companion.getInstance()
createCpuControl(this, backendDiagnosticsService, lifetime)
createMemoryControl(this, backendDiagnosticsService, lifetime)
}
}

private fun createCpuControl(ctx: VerticalGridBuilder, backendDiagnosticsService: BackendDiagnosticsService, lifetime: Lifetime) {
val cpuUsed = backendDiagnosticsService.getMetric("gitpod_workspace_cpu_used")
val cpuTotal = backendDiagnosticsService.getMetric("gitpod_workspace_cpu_total")
val cpuPercentage = backendDiagnosticsService.getMetric("gitpod_workspace_cpu_percentage")
val cpuPercentageProperty = Property("$cpuPercentage %")
val label = "Workspace CPU"
val progressBar = createProgressBar(lifetime, cpuPercentage.valueProperty, cpuPercentageProperty)
val labelProperty = Property("")

fun updateLabel() {
labelProperty.set("${cpuUsed}m / ${cpuTotal}m")
}
updateLabel()
cpuUsed.valueProperty.change.advise(lifetime) {
updateLabel()
}
cpuTotal.valueProperty.change.advise(lifetime) {
updateLabel()
}
createProgressRow(ctx, lifetime, label, cpuPercentage.statusProperty, labelProperty, cpuPercentageProperty, progressBar)
}

private fun createMemoryControl(ctx: VerticalGridBuilder, backendDiagnosticsService: BackendDiagnosticsService, lifetime: Lifetime) {
val memoryUsed = backendDiagnosticsService.getMetric("gitpod_workspace_memory_used")
val memoryTotal = backendDiagnosticsService.getMetric("gitpod_workspace_memory_total")
val memoryPercentage = backendDiagnosticsService.getMetric("gitpod_workspace_memory_percentage")
val memoryPercentageProperty = Property("$memoryPercentage %")
val label = "Workspace Memory"
val progressBar = createProgressBar(lifetime, memoryPercentage.valueProperty, memoryPercentageProperty)
val labelProperty = Property("")

fun updateLabel() {
labelProperty.set("${memoryUsed}GB / ${memoryTotal}GB")
}
updateLabel()
memoryUsed.valueProperty.change.advise(lifetime) {
updateLabel()
}
memoryTotal.valueProperty.change.advise(lifetime) {
updateLabel()
}

createProgressRow(ctx, lifetime, label, memoryPercentage.statusProperty, labelProperty, memoryPercentageProperty, progressBar)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

package io.gitpod.jetbrains.remote.latest

import com.intellij.openapi.components.service
import com.jetbrains.rd.platform.codeWithMe.unattendedHost.metrics.Metric
import com.jetbrains.rd.platform.codeWithMe.unattendedHost.metrics.MetricType
import com.jetbrains.rd.platform.codeWithMe.unattendedHost.metrics.MetricsStatus
import com.jetbrains.rd.platform.codeWithMe.unattendedHost.metrics.providers.MetricProvider
import io.gitpod.jetbrains.remote.GitpodManager
import kotlin.math.roundToInt

class GitpodMetricProvider: MetricProvider {
private val manager = service<GitpodManager>()

override val id: String = "gitpodMetricsProvider"
override fun getMetrics(): Map<String, Metric> {
val resourceStatus = manager.resourceStatus

val cpuUsed = resourceStatus?.cpu?.used?.toDouble() ?: 0.0
val cpuTotal = resourceStatus?.cpu?.limit?.toDouble() ?: 0.0
val cpuPercentage = (cpuUsed / cpuTotal) * 100

// TODO: migrate the threashold logic to supervisor
val cpuStatus = if (cpuPercentage >= 95) {
MetricsStatus.DANGER
} else if (cpuPercentage >= 80) {
MetricsStatus.WARNING
} else {
MetricsStatus.NORMAL
}

val memoryUsed = convertBytesToGB(resourceStatus?.memory?.used ?: 0)
val memoryTotal = convertBytesToGB(resourceStatus?.memory?.limit ?: 0)
val memoryPercentage = (memoryUsed / memoryTotal) * 100

// TODO: migrate the threashold logic to supervisor
val memoryStatus = if (memoryPercentage >= 95) {
MetricsStatus.DANGER
} else if (memoryPercentage >= 80) {
MetricsStatus.WARNING
} else {
MetricsStatus.NORMAL
}

return mapOf(
"gitpod_workspace_cpu_used" to Metric(MetricType.PERFORMANCE, MetricsStatus.NORMAL, roundTo(cpuUsed, 0)),
"gitpod_workspace_cpu_total" to Metric(MetricType.PERFORMANCE, MetricsStatus.NORMAL, roundTo(cpuTotal, 0)),
"gitpod_workspace_cpu_percentage" to Metric(MetricType.PERFORMANCE, cpuStatus, (cpuPercentage * 1000.0).roundToInt() / 1000.0),
"gitpod_workspace_memory_used" to Metric(MetricType.PERFORMANCE, MetricsStatus.NORMAL, roundTo(memoryUsed, 2)),
"gitpod_workspace_memory_total" to Metric(MetricType.PERFORMANCE, MetricsStatus.NORMAL, roundTo(memoryTotal, 2)),
"gitpod_workspace_memory_percentage" to Metric(MetricType.PERFORMANCE, memoryStatus, (memoryPercentage * 1000.0).roundToInt() / 1000.0)
)
}

private fun convertBytesToGB(bytes: Long) : Double {
return bytes.div(1073741824.0)
}

private fun roundTo(number: Double, decimals: Int) : String {
return String.format("%.${decimals}f", number)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
<extensions defaultExtensionNs="com.intellij">
<projectService serviceImplementation="io.gitpod.jetbrains.remote.latest.GitpodTerminalService" client="guest" preload="true"/>
<projectService serviceImplementation="io.gitpod.jetbrains.remote.latest.GitpodPortForwardingService" preload="true"/>
<gateway.customization.performance id="gitpodMetricsControl" order="before cpuControl" implementation="io.gitpod.jetbrains.remote.latest.GitpodMetricControlProvider"/>
<gateway.customization.metrics id="gitpodMetricsProvider" implementation="io.gitpod.jetbrains.remote.latest.GitpodMetricProvider" />
</extensions>
</idea-plugin>

0 comments on commit 54bdfeb

Please sign in to comment.