-
-
Notifications
You must be signed in to change notification settings - Fork 443
domain: add AppLanguage model and AppLanguages registry #435
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
Changes from all commits
7f23e3b
45178dd
1d3824c
6f48b0c
d01cf7d
22f5abf
10f6767
e19f57c
edc3e8c
82daca6
ad81620
b362dc2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,125 @@ | ||||||||||||||||||||||||||||||||||||
| package zed.rainxch.githubstore | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| import java.io.File | ||||||||||||||||||||||||||||||||||||
| import java.io.FileOutputStream | ||||||||||||||||||||||||||||||||||||
| import java.io.PrintStream | ||||||||||||||||||||||||||||||||||||
| import java.io.PrintWriter | ||||||||||||||||||||||||||||||||||||
| import java.time.Instant | ||||||||||||||||||||||||||||||||||||
| import java.time.ZoneId | ||||||||||||||||||||||||||||||||||||
| import java.time.format.DateTimeFormatter | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| object CrashReporter { | ||||||||||||||||||||||||||||||||||||
| private const val MAX_SESSION_LOG_BYTES = 5L * 1024 * 1024 | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| private val logDir: File by lazy { resolveLogDir().also { it.mkdirs() } } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| fun install() { | ||||||||||||||||||||||||||||||||||||
| val teed = | ||||||||||||||||||||||||||||||||||||
| runCatching { | ||||||||||||||||||||||||||||||||||||
| val file = File(logDir, "session.log") | ||||||||||||||||||||||||||||||||||||
| rotateIfLarge(file) | ||||||||||||||||||||||||||||||||||||
| PrintStream(FileOutputStream(file, true), true, Charsets.UTF_8) | ||||||||||||||||||||||||||||||||||||
| .also { stream -> | ||||||||||||||||||||||||||||||||||||
| System.setOut(TeePrintStream(System.out, stream)) | ||||||||||||||||||||||||||||||||||||
| System.setErr(TeePrintStream(System.err, stream)) | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+16
to
+24
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid persisting unrestricted stdout/stderr by default. Line 21–24 writes every process log line to disk, including anything accidentally printed by dependencies or debug code. Add redaction/retention controls or make session teeing explicitly opt-in while keeping crash dumps enabled. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| }.getOrNull() | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Thread.setDefaultUncaughtExceptionHandler { thread, throwable -> | ||||||||||||||||||||||||||||||||||||
| runCatching { writeCrashDump(thread, throwable) } | ||||||||||||||||||||||||||||||||||||
| runCatching { throwable.printStackTrace(System.err) } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (teed != null) { | ||||||||||||||||||||||||||||||||||||
| println("=== GitHub Store session ${Instant.now()} ===") | ||||||||||||||||||||||||||||||||||||
| println( | ||||||||||||||||||||||||||||||||||||
| "OS=${System.getProperty("os.name")} ${System.getProperty("os.version")} " + | ||||||||||||||||||||||||||||||||||||
| "(${System.getProperty("os.arch")})", | ||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||
| println( | ||||||||||||||||||||||||||||||||||||
| "Java=${System.getProperty("java.version")} (${System.getProperty("java.vendor")})", | ||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||
| println("LogDir=${logDir.absolutePath}") | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| private fun writeCrashDump( | ||||||||||||||||||||||||||||||||||||
| thread: Thread, | ||||||||||||||||||||||||||||||||||||
| throwable: Throwable, | ||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||
| val file = File(logDir, "crash-${timestamp()}.log") | ||||||||||||||||||||||||||||||||||||
| PrintWriter(file, Charsets.UTF_8).use { writer -> | ||||||||||||||||||||||||||||||||||||
| writer.println("=== GitHub Store crash ===") | ||||||||||||||||||||||||||||||||||||
| writer.println("Time: ${Instant.now()}") | ||||||||||||||||||||||||||||||||||||
| writer.println("Thread: ${thread.name}") | ||||||||||||||||||||||||||||||||||||
| writer.println( | ||||||||||||||||||||||||||||||||||||
| "OS: ${System.getProperty("os.name")} ${System.getProperty("os.version")} " + | ||||||||||||||||||||||||||||||||||||
| "(${System.getProperty("os.arch")})", | ||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||
| writer.println( | ||||||||||||||||||||||||||||||||||||
| "Java: ${System.getProperty("java.version")} (${System.getProperty("java.vendor")})", | ||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||
| writer.println() | ||||||||||||||||||||||||||||||||||||
| throwable.printStackTrace(writer) | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| private fun rotateIfLarge(file: File) { | ||||||||||||||||||||||||||||||||||||
| if (!file.exists() || file.length() <= MAX_SESSION_LOG_BYTES) return | ||||||||||||||||||||||||||||||||||||
| val rotated = File(file.parentFile, "session.1.log") | ||||||||||||||||||||||||||||||||||||
| if (rotated.exists()) rotated.delete() | ||||||||||||||||||||||||||||||||||||
| file.renameTo(rotated) | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+67
to
+72
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle failed rotation so
Proposed fallback private fun rotateIfLarge(file: File) {
if (!file.exists() || file.length() <= MAX_SESSION_LOG_BYTES) return
val rotated = File(file.parentFile, "session.1.log")
- if (rotated.exists()) rotated.delete()
- file.renameTo(rotated)
+ if (rotated.exists() && !rotated.delete()) {
+ FileOutputStream(file, false).close()
+ return
+ }
+ if (!file.renameTo(rotated)) {
+ FileOutputStream(file, false).close()
+ }
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| private fun resolveLogDir(): File { | ||||||||||||||||||||||||||||||||||||
| val home = File(System.getProperty("user.home")) | ||||||||||||||||||||||||||||||||||||
| val osName = System.getProperty("os.name").orEmpty().lowercase() | ||||||||||||||||||||||||||||||||||||
| return when { | ||||||||||||||||||||||||||||||||||||
| "mac" in osName -> { | ||||||||||||||||||||||||||||||||||||
| File(home, "Library/Logs/GitHub-Store") | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| "win" in osName -> { | ||||||||||||||||||||||||||||||||||||
| val localAppData = System.getenv("LOCALAPPDATA")?.let(::File) ?: home | ||||||||||||||||||||||||||||||||||||
| File(localAppData, "GitHub-Store/logs") | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| else -> { | ||||||||||||||||||||||||||||||||||||
| val stateHome = | ||||||||||||||||||||||||||||||||||||
| System.getenv("XDG_STATE_HOME")?.let(::File) | ||||||||||||||||||||||||||||||||||||
| ?: File(home, ".local/state") | ||||||||||||||||||||||||||||||||||||
| File(stateHome, "GitHub-Store/logs") | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| private fun timestamp(): String = | ||||||||||||||||||||||||||||||||||||
| DateTimeFormatter | ||||||||||||||||||||||||||||||||||||
| .ofPattern("yyyyMMdd-HHmmss-SSS") | ||||||||||||||||||||||||||||||||||||
| .withZone(ZoneId.systemDefault()) | ||||||||||||||||||||||||||||||||||||
| .format(Instant.now()) | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| private class TeePrintStream( | ||||||||||||||||||||||||||||||||||||
| private val primary: PrintStream, | ||||||||||||||||||||||||||||||||||||
| private val secondary: PrintStream, | ||||||||||||||||||||||||||||||||||||
| ) : PrintStream(primary) { | ||||||||||||||||||||||||||||||||||||
| override fun write(b: Int) { | ||||||||||||||||||||||||||||||||||||
| primary.write(b) | ||||||||||||||||||||||||||||||||||||
| runCatching { secondary.write(b) } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| override fun write( | ||||||||||||||||||||||||||||||||||||
| buf: ByteArray, | ||||||||||||||||||||||||||||||||||||
| off: Int, | ||||||||||||||||||||||||||||||||||||
| len: Int, | ||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||
| primary.write(buf, off, len) | ||||||||||||||||||||||||||||||||||||
| runCatching { secondary.write(buf, off, len) } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| override fun flush() { | ||||||||||||||||||||||||||||||||||||
| primary.flush() | ||||||||||||||||||||||||||||||||||||
| runCatching { secondary.flush() } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.