Skip to content

Commit ad81ad9

Browse files
committed
Add diagnostics to log upload and update types
1 parent cbb74d0 commit ad81ad9

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

apps/desktop/src-tauri/src/logging.rs

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::{ArcLock, web_api::ManagerExt};
1+
use crate::{ArcLock, feeds::microphone::MicrophoneFeed, permissions, web_api::ManagerExt};
2+
use serde::Serialize;
23
use std::{fs, path::PathBuf};
34
use tauri::{AppHandle, Manager};
45

@@ -29,6 +30,60 @@ async fn get_latest_log_file(app: &AppHandle) -> Option<PathBuf> {
2930
log_files.first().map(|(path, _)| path.clone())
3031
}
3132

33+
#[derive(Serialize)]
34+
#[serde(rename_all = "camelCase")]
35+
struct LogUploadDiagnostics {
36+
system: cap_recording::diagnostics::SystemDiagnostics,
37+
cameras: Vec<String>,
38+
microphones: Vec<String>,
39+
permissions: PermissionsInfo,
40+
}
41+
42+
#[derive(Serialize)]
43+
#[serde(rename_all = "camelCase")]
44+
struct PermissionsInfo {
45+
screen_recording: String,
46+
camera: String,
47+
microphone: String,
48+
}
49+
50+
fn collect_diagnostics_for_upload() -> LogUploadDiagnostics {
51+
let system = cap_recording::diagnostics::collect_diagnostics();
52+
let permissions = permissions::do_permissions_check(false);
53+
54+
let cameras: Vec<String> = if permissions.camera.permitted() {
55+
cap_camera::list_cameras()
56+
.map(|c| c.display_name().to_string())
57+
.collect()
58+
} else {
59+
vec![]
60+
};
61+
62+
let microphones: Vec<String> = if permissions.microphone.permitted() {
63+
MicrophoneFeed::list().keys().cloned().collect()
64+
} else {
65+
vec![]
66+
};
67+
68+
let perm_status = |p: &permissions::OSPermissionStatus| match p {
69+
permissions::OSPermissionStatus::NotNeeded => "not_needed",
70+
permissions::OSPermissionStatus::Empty => "not_requested",
71+
permissions::OSPermissionStatus::Granted => "granted",
72+
permissions::OSPermissionStatus::Denied => "denied",
73+
};
74+
75+
LogUploadDiagnostics {
76+
system,
77+
cameras,
78+
microphones,
79+
permissions: PermissionsInfo {
80+
screen_recording: perm_status(&permissions.screen_recording).to_string(),
81+
camera: perm_status(&permissions.camera).to_string(),
82+
microphone: perm_status(&permissions.microphone).to_string(),
83+
},
84+
}
85+
}
86+
3287
pub async fn upload_log_file(app: &AppHandle) -> Result<(), String> {
3388
let log_file = get_latest_log_file(app).await.ok_or("No log file found")?;
3489

@@ -62,10 +117,14 @@ pub async fn upload_log_file(app: &AppHandle) -> Result<(), String> {
62117
fs::read_to_string(&log_file).map_err(|e| format!("Failed to read log file: {e}"))?
63118
};
64119

120+
let diagnostics = collect_diagnostics_for_upload();
121+
let diagnostics_json = serde_json::to_string(&diagnostics).unwrap_or_else(|_| "{}".to_string());
122+
65123
let form = reqwest::multipart::Form::new()
66124
.text("log", log_content)
67125
.text("os", std::env::consts::OS)
68-
.text("version", env!("CARGO_PKG_VERSION"));
126+
.text("version", env!("CARGO_PKG_VERSION"))
127+
.text("diagnostics", diagnostics_json);
69128

70129
let response = app
71130
.api_request("/api/desktop/logs", |client, url| {

apps/desktop/src/utils/tauri.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ uploadProgressEvent: "upload-progress-event"
375375

376376
/** user-defined types **/
377377

378-
export type AllGpusInfo = { gpus: GpuInfoDiag[]; primaryGpuIndex: number | null; isMultiGpuSystem: boolean; hasDiscreteGpu: boolean }
379378
export type Annotation = { id: string; type: AnnotationType; x: number; y: number; width: number; height: number; strokeColor: string; strokeWidth: number; fillColor: string; opacity: number; rotation: number; text: string | null; maskType?: MaskType | null; maskLevel?: number | null }
380379
export type AnnotationType = "arrow" | "circle" | "rectangle" | "text" | "mask"
381380
export type AppTheme = "system" | "light" | "dark"
@@ -445,7 +444,6 @@ quality: number | null;
445444
* Whether to prioritize speed over quality (default: false)
446445
*/
447446
fast: boolean | null }
448-
export type GpuInfoDiag = { vendor: string; description: string; dedicatedVideoMemoryMb: number; adapterIndex: number; isSoftwareAdapter: boolean; isBasicRenderDriver: boolean; supportsHardwareEncoding: boolean }
449447
export type HapticPattern = "alignment" | "levelChange" | "generic"
450448
export type HapticPerformanceTime = "default" | "now" | "drawCompleted"
451449
export type Hotkey = { code: string; meta: boolean; ctrl: boolean; alt: boolean; shift: boolean }
@@ -458,6 +456,7 @@ export type JsonValue<T> = [T]
458456
export type LogicalBounds = { position: LogicalPosition; size: LogicalSize }
459457
export type LogicalPosition = { x: number; y: number }
460458
export type LogicalSize = { width: number; height: number }
459+
export type MacOSVersionInfo = { displayName: string }
461460
export type MainWindowRecordingStartBehaviour = "close" | "minimise"
462461
export type MaskKeyframes = { position?: MaskVectorKeyframe[]; size?: MaskVectorKeyframe[]; intensity?: MaskScalarKeyframe[] }
463462
export type MaskKind = "sensitive" | "highlight"
@@ -500,7 +499,6 @@ export type RecordingStatus = "pending" | "recording"
500499
export type RecordingStopped = null
501500
export type RecordingTargetMode = "display" | "window" | "area"
502501
export type RenderFrameEvent = { frame_number: number; fps: number; resolution_base: XY<number> }
503-
export type RenderingStatus = { isUsingSoftwareRendering: boolean; isUsingBasicRenderDriver: boolean; hardwareEncodingAvailable: boolean; warningMessage: string | null }
504502
export type RequestOpenRecordingPicker = { target_mode: RecordingTargetMode | null }
505503
export type RequestOpenSettings = { page: string }
506504
export type RequestScreenCapturePrewarm = { force?: boolean }
@@ -521,7 +519,7 @@ export type StartRecordingInputs = { capture_target: ScreenCaptureTarget; captur
521519
export type StereoMode = "stereo" | "monoL" | "monoR"
522520
export type StudioRecordingMeta = { segment: SingleSegment } | { inner: MultipleSegments }
523521
export type StudioRecordingStatus = { status: "InProgress" } | { status: "NeedsRemux" } | { status: "Failed"; error: string } | { status: "Complete" }
524-
export type SystemDiagnostics = { windowsVersion: WindowsVersionInfo | null; gpuInfo: GpuInfoDiag | null; allGpus: AllGpusInfo | null; renderingStatus: RenderingStatus; availableEncoders: string[]; graphicsCaptureSupported: boolean; d3D11VideoProcessorAvailable: boolean }
522+
export type SystemDiagnostics = { macosVersion: MacOSVersionInfo | null; availableEncoders: string[]; screenCaptureSupported: boolean }
525523
export type TargetUnderCursor = { display_id: DisplayId | null; window: WindowUnderCursor | null }
526524
export type TextSegment = { start: number; end: number; enabled?: boolean; content?: string; center?: XY<number>; size?: XY<number>; fontFamily?: string; fontSize?: number; fontWeight?: number; italic?: boolean; color?: string; fadeDuration?: number }
527525
export type TimelineConfiguration = { segments: TimelineSegment[]; zoomSegments: ZoomSegment[]; sceneSegments?: SceneSegment[]; maskSegments?: MaskSegment[]; textSegments?: TextSegment[] }
@@ -538,7 +536,6 @@ export type VideoUploadInfo = { id: string; link: string; config: S3UploadMeta }
538536
export type WindowExclusion = { bundleIdentifier?: string | null; ownerName?: string | null; windowTitle?: string | null }
539537
export type WindowId = string
540538
export type WindowUnderCursor = { id: WindowId; app_name: string; bounds: LogicalBounds }
541-
export type WindowsVersionInfo = { major: number; minor: number; build: number; displayName: string; meetsRequirements: boolean; isWindows11: boolean }
542539
export type XY<T> = { x: T; y: T }
543540
export type ZoomMode = "auto" | { manual: { x: number; y: number } }
544541
export type ZoomSegment = { start: number; end: number; amount: number; mode: ZoomMode }

0 commit comments

Comments
 (0)