Skip to content

Commit c232344

Browse files
authored
feat: Add a item to developer menu to export application logs + system info (#723)
1 parent 2eaf658 commit c232344

1 file changed

Lines changed: 65 additions & 12 deletions

File tree

apps/twig/src/main/menu.ts

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,38 @@
11
declare const __BUILD_COMMIT__: string | undefined;
22
declare const __BUILD_DATE__: string | undefined;
33

4+
import { access, readFile, writeFile } from "node:fs/promises";
45
import os from "node:os";
6+
import path from "node:path";
57
import {
68
app,
79
clipboard,
810
dialog,
911
Menu,
1012
type MenuItemConstructorOptions,
1113
} from "electron";
14+
import log from "electron-log/main";
1215
import { container } from "./di/container.js";
1316
import { MAIN_TOKENS } from "./di/tokens.js";
1417
import type { AgentService } from "./services/agent/service.js";
1518
import type { UIService } from "./services/ui/service.js";
1619
import type { UpdatesService } from "./services/updates/service.js";
1720

21+
function getSystemInfo(): string {
22+
const commit = __BUILD_COMMIT__ ?? "dev";
23+
const buildDate = __BUILD_DATE__ ?? "dev";
24+
return [
25+
`Version: ${app.getVersion()}`,
26+
`Commit: ${commit}`,
27+
`Date: ${buildDate}`,
28+
`Electron: ${process.versions.electron}`,
29+
`Chromium: ${process.versions.chrome}`,
30+
`Node.js: ${process.versions.node}`,
31+
`V8: ${process.versions.v8}`,
32+
`OS: ${process.platform} ${process.arch} ${os.release()}`,
33+
].join("\n");
34+
}
35+
1836
export function buildApplicationMenu(): void {
1937
const template: MenuItemConstructorOptions[] = [
2038
buildAppMenu(),
@@ -34,18 +52,7 @@ function buildAppMenu(): MenuItemConstructorOptions {
3452
{
3553
label: "About Twig",
3654
click: () => {
37-
const commit = __BUILD_COMMIT__ ?? "dev";
38-
const buildDate = __BUILD_DATE__ ?? "dev";
39-
const info = [
40-
`Version: ${app.getVersion()}`,
41-
`Commit: ${commit}`,
42-
`Date: ${buildDate}`,
43-
`Electron: ${process.versions.electron}`,
44-
`Chromium: ${process.versions.chrome}`,
45-
`Node.js: ${process.versions.node}`,
46-
`V8: ${process.versions.v8}`,
47-
`OS: ${process.platform} ${process.arch} ${os.release()}`,
48-
].join("\n");
55+
const info = getSystemInfo();
4956

5057
dialog
5158
.showMessageBox({
@@ -109,6 +116,52 @@ function buildFileMenu(): MenuItemConstructorOptions {
109116
{
110117
label: "Developer",
111118
submenu: [
119+
{
120+
label: "Export application logs",
121+
click: async () => {
122+
const logPath = log.transports.file.getFile().path;
123+
124+
try {
125+
await access(logPath);
126+
} catch {
127+
dialog.showMessageBox({
128+
type: "warning",
129+
title: "No Logs Found",
130+
message: "No log file exists yet.",
131+
detail: `Expected location: ${logPath}`,
132+
});
133+
return;
134+
}
135+
136+
const timestamp = new Date()
137+
.toISOString()
138+
.replace(/[:.]/g, "-")
139+
.slice(0, 19);
140+
const defaultName = `twig-logs-${timestamp}.log`;
141+
const { filePath, canceled } = await dialog.showSaveDialog({
142+
title: "Export Logs",
143+
defaultPath: path.join(app.getPath("desktop"), defaultName),
144+
filters: [{ name: "Log Files", extensions: ["log"] }],
145+
});
146+
if (canceled || !filePath) return;
147+
148+
const logContent = await readFile(logPath, "utf-8");
149+
const header = [
150+
"=".repeat(60),
151+
" Twig Log Export",
152+
"=".repeat(60),
153+
"",
154+
getSystemInfo(),
155+
"",
156+
`Exported: ${new Date().toISOString()}`,
157+
"",
158+
"=".repeat(60),
159+
"",
160+
].join("\n");
161+
162+
await writeFile(filePath, header + logContent, "utf-8");
163+
},
164+
},
112165
{
113166
label: "Clear application storage",
114167
click: () => {

0 commit comments

Comments
 (0)