Skip to content

Commit

Permalink
LogSink-ish
Browse files Browse the repository at this point in the history
  • Loading branch information
Danil0v3s committed Jan 21, 2025
1 parent d20292f commit 54f0588
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import app.cleanmeter.core.common.reporting.setDefaultUncaughtExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.FileOutputStream
import java.io.PrintStream
import java.net.ServerSocket
import java.util.*
import kotlin.system.exitProcess

fun singleInstance(args: Array<out String>, block: () -> Unit) {
Expand All @@ -20,13 +17,6 @@ fun singleInstance(args: Array<out String>, block: () -> Unit) {

setDefaultUncaughtExceptionHandler()

if (ApplicationParams.isVerbose) {
val startTime = Date().time
val printStream = PrintStream(FileOutputStream("out.$startTime.txt", true))
System.setOut(printStream)
System.setErr(printStream)
}

block()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ object ApplicationParams {
val isAutostart: Boolean
get() = _isAutoStart

private var _isVerbose = false
val isVerbose: Boolean
get() = _isVerbose

fun parse(args: Array<out String>) {
_isAutoStart = args.contains("--autostart")
_isVerbose = args.contains("--verbose")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,7 @@ object SocketClient {
println("Connected ${socket.isConnected}")
} catch (ex: Exception) {
println("Couldn't connect ${ex.message}")
if (ex !is SocketException) {
ex.printStackTrace()
}
ex.printStackTrace()
} finally {
delay(pollingRate)
continue
Expand All @@ -88,6 +86,7 @@ object SocketClient {
try {
val command = getCommand(inputStream)
val size = getSize(inputStream)
println("Received $command with $size bytes")
when (command) {
Command.Data -> packetChannel.trySend(Packet.Data(inputStream.readNBytes(size)))
Command.PresentMonApps -> packetChannel.trySend(Packet.PresentMonApps(inputStream.readNBytes(size)))
Expand All @@ -96,6 +95,7 @@ object SocketClient {
Command.SelectPollingRate -> Unit
}
} catch (e: SocketException) {
println("Error while listening for packets")
socket.close()
socket = Socket()
e.printStackTrace()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ data class OverlaySettings(
val isPositionLocked: Boolean = true,
val opacity: Float = 1f,
val pollingRate: Long = 500,
val isLoggingEnabled: Boolean = false,
val sensors: Sensors = Sensors(),
) {
@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.toUpperCase
import app.cleanmeter.target.desktop.ui.components.SectionTitle
import app.cleanmeter.target.desktop.ui.components.Toggle

Expand All @@ -21,7 +22,7 @@ fun ToggleSection(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
SectionTitle(title = title)
SectionTitle(title = title.uppercase())
Toggle(
checked = isEnabled,
onCheckedChange = onSwitchToggle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ private fun TabContent(
)

2 -> AppSettingsUi(overlaySettings = settingsState.overlaySettings!!, onEvent = viewModel::onEvent)
3 -> HelpSettingsUi()
3 -> HelpSettingsUi(overlaySettings = settingsState.overlaySettings!!, onEvent = viewModel::onEvent, logSink = settingsState.logSink)
else -> Unit
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import app.cleanmeter.core.os.PreferencesRepository
import app.cleanmeter.target.desktop.model.OverlaySettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
Expand All @@ -24,14 +26,23 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.util.Scanner

sealed interface Log {
@JvmInline value class Info(val value: String)
@JvmInline value class Error(val value: String)
}

data class SettingsState(
val overlaySettings: OverlaySettings? = null,
val hardwareData: HardwareMonitorData? = null,
val isRecording: Boolean = false,
val adminConsent: Boolean = false,
val isRuntimeAvailable: Boolean = false,
val logSink: String = ""
)

sealed class SettingsEvent {
Expand All @@ -50,10 +61,15 @@ sealed class SettingsEvent {
data class BoundarySet(val sensorType: SensorType, val boundaries: OverlaySettings.Sensor.GraphSensor.Boundaries) : SettingsEvent()
data class PollingRateSelect(val pollingRate: Long) : SettingsEvent()
data object ConsentGiven : SettingsEvent()
data object ToggleLoggingEnabled : SettingsEvent()
}

class SettingsViewModel : ViewModel() {

private val _oldOut = System.out;
private val _oldErr = System.err;
private var _loggerJob: Job? = null;

private val _state: MutableStateFlow<SettingsState> = MutableStateFlow(SettingsState())
val state: Flow<SettingsState>
get() = _state
Expand All @@ -67,6 +83,7 @@ class SettingsViewModel : ViewModel() {
observeRecordingState()
sendInitialPollingRate()
checkForNetCoreRuntime()
checkIfLoggingIsEnabled()

_state.update {
it.copy(
Expand All @@ -75,6 +92,34 @@ class SettingsViewModel : ViewModel() {
}
}

private fun checkIfLoggingIsEnabled() {
CoroutineScope(Dispatchers.IO).launch {
val settings = OverlaySettingsRepository.data.first()

if (settings.isLoggingEnabled) {
enableLogSink()
}
}
}

private fun enableLogSink() {
_loggerJob?.cancel()
_loggerJob = CoroutineScope(Dispatchers.IO).launch {
val byteArrayOutputStream = ByteArrayOutputStream()
val printStream = PrintStream(byteArrayOutputStream)
System.setOut(printStream)
System.setErr(printStream)

while (true) {
val output = byteArrayOutputStream.toString()
if (output.isNotEmpty()) {
_state.update { it.copy(logSink = output) }
}
delay(500)
}
}
}

private fun checkForNetCoreRuntime() {
CoroutineScope(Dispatchers.IO).launch {
val isRuntimeAvailable = HardwareMonitorProcessManager.checkRuntime()
Expand Down Expand Up @@ -166,7 +211,25 @@ class SettingsViewModel : ViewModel() {
is SettingsEvent.BoundarySet -> onBoundarySet(event.sensorType, event.boundaries, this)
is SettingsEvent.ConsentGiven -> onConsentGiven()
is SettingsEvent.PollingRateSelect -> onPollingRateSelect(event.pollingRate, this)
is SettingsEvent.ToggleLoggingEnabled -> onToggleLoggingEnabled(this)
}
}

private fun onToggleLoggingEnabled(settingsState: SettingsState) {
if (settingsState.overlaySettings == null) return
val newSettings = settingsState.overlaySettings.copy(
isLoggingEnabled = !settingsState.overlaySettings.isLoggingEnabled
)

if (newSettings.isLoggingEnabled) {
enableLogSink()
} else {
_loggerJob?.cancel()
System.setOut(_oldOut)
System.setErr(_oldErr)
}

OverlaySettingsRepository.setOverlaySettings(newSettings)
}

private fun onPollingRateSelect(pollingRate: Long, settingsState: SettingsState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@ package app.cleanmeter.target.desktop.ui.settings.tabs

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Icon
import androidx.compose.material.Text
Expand All @@ -38,11 +43,18 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.cleanmeter.core.designsystem.LocalColorScheme
import app.cleanmeter.core.designsystem.LocalTypography
import app.cleanmeter.target.desktop.model.OverlaySettings
import app.cleanmeter.target.desktop.ui.components.HotKeySymbol
import app.cleanmeter.target.desktop.ui.components.section.CollapsibleSection
import app.cleanmeter.target.desktop.ui.components.section.ToggleSection
import app.cleanmeter.target.desktop.ui.settings.SettingsEvent

@Composable
internal fun HelpSettingsUi() {
internal fun HelpSettingsUi(
logSink: String,
overlaySettings: OverlaySettings,
onEvent: (SettingsEvent) -> Unit
) {
Column(
modifier = Modifier.padding(bottom = 8.dp, top = 20.dp).verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(16.dp)
Expand Down Expand Up @@ -115,6 +127,24 @@ internal fun HelpSettingsUi() {
Hotkey(label = "Toggle the overlay", "F10")
Hotkey(label = "Toggle data recording", "F11")
}

ToggleSection(
title = "Application Logs",
isEnabled = overlaySettings.isLoggingEnabled,
onSwitchToggle = { onEvent(SettingsEvent.ToggleLoggingEnabled) }
) {
SelectionContainer {
Text(
text = logSink,
style = LocalTypography.current.labelM,
color = LocalColorScheme.current.text.heading,
modifier = Modifier
.fillMaxWidth()
.background(LocalColorScheme.current.background.surfaceSunkenSubtle)
.padding(8.dp)
)
}
}
}
}

Expand Down

0 comments on commit 54f0588

Please sign in to comment.