Skip to content

Commit 508a75e

Browse files
authored
Merge pull request #137 from getditto/zan/rotating-logs
Update logExporter to use rotating logs
2 parents 67e01c4 + fbe2648 commit 508a75e

File tree

11 files changed

+126
-122
lines changed

11 files changed

+126
-122
lines changed

Diff for: DittoExportLogs/build.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dependencies {
1818
implementation libs.androidx.compose.material3.material3
1919
implementation libs.androidx.compose.ui.ui
2020
implementation libs.androidx.navigation.navigationCompose
21+
implementation(libs.live.ditto.ditto)
2122
// Dependency constraint for ditto
2223
constraints {
2324
implementation(libs.live.ditto.ditto) {
@@ -26,6 +27,7 @@ dependencies {
2627
}
2728
}
2829
}
30+
2931
implementation libs.live.ditto.exporter
3032
implementation platform(libs.androidx.compose.composeBom)
3133

Diff for: DittoExportLogs/src/main/java/live/ditto/dittoexportlogs/DittoLogManager.kt

-54
This file was deleted.

Diff for: DittoExportLogs/src/main/java/live/ditto/dittoexportlogs/ExportLogs.kt

+78-14
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,90 @@
11
package live.ditto.dittoexportlogs
22

3+
import android.os.Build
4+
import android.os.Environment
5+
import androidx.annotation.RequiresApi
6+
import androidx.compose.foundation.layout.Row
7+
import androidx.compose.foundation.layout.Spacer
8+
import androidx.compose.foundation.layout.size
9+
import androidx.compose.foundation.layout.width
10+
import androidx.compose.material3.AlertDialog
11+
import androidx.compose.material3.Button
12+
import androidx.compose.material3.CircularProgressIndicator
13+
import androidx.compose.material3.MaterialTheme
14+
import androidx.compose.material3.Text
315
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.getValue
17+
import androidx.compose.runtime.mutableStateOf
18+
import androidx.compose.runtime.remember
19+
import androidx.compose.runtime.rememberCoroutineScope
20+
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.platform.LocalContext
422
import androidx.compose.ui.res.stringResource
5-
import live.ditto.exporter.ExportDialog
6-
import java.nio.file.Path
23+
import androidx.compose.ui.unit.dp
24+
import kotlinx.coroutines.launch
25+
import java.io.File
26+
import java.time.LocalDateTime
27+
import java.time.format.DateTimeFormatter
728

29+
@RequiresApi(Build.VERSION_CODES.O)
830
@Composable
9-
fun ExportLogs(onDismiss: () -> Unit) {
10-
ExportDialog(
11-
title = stringResource(R.string.export_logs),
12-
text = stringResource(R.string.do_you_want_to_export_logs),
13-
confirmText = stringResource(R.string.export),
14-
cancelText = stringResource(R.string.cancel),
15-
fileProvider = { getZippedLogs().toFile() },
16-
mimeType = stringResource(R.string.application_x_zip),
17-
onDismiss = onDismiss
31+
fun ExportLogs(onDismiss: () -> Unit, viewModel: ExportLogsViewModel = ExportLogsViewModel()) {
32+
33+
val isLoading by remember { mutableStateOf(viewModel.isLoading)}
34+
35+
val title = stringResource(R.string.export_logs)
36+
37+
val confirmText = stringResource(R.string.export)
38+
val cancelText = stringResource(R.string.cancel)
39+
val context = LocalContext.current
40+
41+
val now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))
42+
val appName = context.applicationInfo.loadLabel(context.packageManager).toString()
43+
44+
val fileName = "$appName-dittologs-$now.jsonl.gz"
45+
val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
46+
val filePath = File(downloadsDir, fileName).absolutePath
47+
48+
AlertDialog(
49+
onDismissRequest = onDismiss,
50+
title = {
51+
Text(title)
52+
},
53+
text = {
54+
Text(stringResource(R.string.export_logs_message, fileName))
55+
},
56+
57+
confirmButton = {
58+
Button(
59+
onClick = {
60+
viewModel.exportLogs(filePath, context, onDismiss)
61+
}
62+
) {
63+
Row {
64+
Text(confirmText)
65+
66+
if (isLoading) {
67+
Spacer(Modifier.width(16.dp))
68+
69+
CircularProgressIndicator(
70+
modifier = Modifier.size(18.dp),
71+
color = MaterialTheme.colorScheme.onPrimary,
72+
strokeWidth = 2.dp
73+
)
74+
}
75+
}
76+
}
77+
},
78+
dismissButton = {
79+
Button(
80+
onClick = onDismiss,
81+
) {
82+
Text(cancelText)
83+
}
84+
}
1885
)
1986
}
2087

21-
private fun getZippedLogs(): Path {
22-
return DittoLogManager.createLogsZip()
23-
}
2488

2589

2690

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package live.ditto.dittoexportlogs
2+
3+
import android.content.Context
4+
import android.util.Log
5+
import android.widget.Toast
6+
import androidx.compose.runtime.getValue
7+
import androidx.compose.runtime.mutableStateOf
8+
import androidx.compose.runtime.setValue
9+
import androidx.lifecycle.ViewModel
10+
import androidx.lifecycle.viewModelScope
11+
import kotlinx.coroutines.launch
12+
import live.ditto.DittoError
13+
import live.ditto.DittoLogger
14+
15+
class ExportLogsViewModel : ViewModel() {
16+
17+
var isLoading by mutableStateOf(false)
18+
private set
19+
20+
fun exportLogs(filePath: String, context: Context, onDismiss: () -> Unit) {
21+
viewModelScope.launch {
22+
isLoading = true
23+
try {
24+
val sizeWritten = DittoLogger.exportToFile(filePath)
25+
26+
val sizeWrittenInKB = (sizeWritten / 1024u).toInt()
27+
val toastText = context.getString(R.string.exported_file_size_kb, sizeWrittenInKB)
28+
Toast.makeText(context, toastText, Toast.LENGTH_LONG).show()
29+
} catch (e: DittoError.IoError) {
30+
Log.e("DittoTools LogExporter", e.reason.toString())
31+
Toast.makeText(context,
32+
context.getString(R.string.error_exporting_logs, e.message), Toast.LENGTH_LONG).show()
33+
} finally {
34+
isLoading = false
35+
onDismiss()
36+
}
37+
}
38+
}
39+
}

Diff for: DittoExportLogs/src/main/res/values/strings.xml

+3
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@
55
<string name="export">Export</string>
66
<string name="cancel">Cancel</string>
77
<string name="application_x_zip">application/x-zip</string>
8+
<string name="export_logs_message">Logs will be exported to: \nDownloads/%1$s\"</string>
9+
<string name="exported_file_size_kb">Exported file size: %1$d kB</string>
10+
<string name="error_exporting_logs">Error exporting logs: %1$s</string>
811
</resources>

Diff for: DittoToolsViewer/src/main/java/live/ditto/dittotoolsviewer/presentation/DittoToolsViewer.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import live.ditto.dittoexportlogs.ExportLogs
2626
import live.ditto.dittotoolsviewer.R
2727
import live.ditto.dittotoolsviewer.presentation.navigation.Screens
2828
import live.ditto.dittotoolsviewer.presentation.viewmodel.ToolsViewerViewModel
29-
import live.ditto.health.ui.composables.HealthScreen
29+
import live.ditto.health.HealthScreen
3030
import live.ditto.presencedegradationreporter.PresenceDegradationReporterScreen
3131

3232
/**

Diff for: Img/exportLogs.png

-98.9 KB
Loading

Diff for: README.md

+2-31
Original file line numberDiff line numberDiff line change
@@ -152,38 +152,9 @@ Maven:
152152
```
153153

154154
### 4. Export Logs
155-
Export Logs allows you to export a file of the logs from your applcation.
155+
Export Logs allows you to export logs from your application into a file.
156156

157-
**Important**
158-
159-
Before calling `ditto.startSync()` we need to set the `DittoLogger.setLogFileURL(<logFileURL>)`. This registers a file path where logs will be written to, whenever Ditto wants to issue a log (on top of emitting the log to the console). Use the `LogFileConfig` struct:
160-
161-
```
162-
object LogFileConfig {
163-
private const val logsDirectoryName = "debug-logs"
164-
private const val logFileName = "logs.txt"
165-
166-
val logsDirectory: Path by lazy {
167-
val directory = Paths.get(System.getProperty("java.io.tmpdir"), logsDirectoryName)
168-
Files.createDirectories(directory)
169-
directory
170-
}
171-
172-
val logFile: Path by lazy {
173-
logsDirectory.resolve(logFileName)
174-
}
175-
}
176-
```
177-
178-
and then before calling `ditto.startSync()` set the log file url with:
179-
180-
```
181-
LogFileConfig.logFile.let { logFile ->
182-
DittoLogger.setLogFile(logFile.toString())
183-
}
184-
```
185-
186-
Now we can call `ExportLogs()`.
157+
Include `ExportLogs()` in your Composable function. You can pass in a lambda function to be called when the dialog is dismissed.
187158

188159
```kotlin
189160
ExportLogs(onDismiss: () -> Unit)

Diff for: app/src/main/java/live/ditto/dittotoolsapp/LogFileConfig.kt

-17
This file was deleted.

Diff for: app/src/main/java/live/ditto/dittotoolsapp/MainActivity.kt

-4
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ class MainActivity : ComponentActivity() {
9595
val ditto = Ditto(androidDependencies, identity)
9696
DittoLogger.minimumLogLevel = DittoLogLevel.DEBUG
9797

98-
LogFileConfig.logFile.let { logFile ->
99-
DittoLogger.setLogFile(logFile.toString())
100-
}
101-
10298
ditto
10399
}
104100

Diff for: gradle/libs.versions.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ androidx-navigation = "2.5.3"
1414
androidx-test-ext = "1.1.5"
1515
androidx-webkit = "1.7.0"
1616
datastorePreferences = "1.0.0"
17-
ditto = "4.7.4"
17+
ditto = "4.8.2"
1818
live-ditto-tools = "2.1.0"
1919

2020
junit = "4.13.2"

0 commit comments

Comments
 (0)