-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogging.go
More file actions
149 lines (126 loc) · 3.59 KB
/
logging.go
File metadata and controls
149 lines (126 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// logging.go
//go:build windows
// +build windows
package main
import (
"fmt"
"time"
"github.com/gen2brain/beeep"
"github.com/getlantern/systray"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc/eventlog"
)
const (
adminRoleID = "S-1-5-32-544"
// Event log message IDs
infoEventID = 1
warningEventID = 2
errorEventID = 3
)
func isAdmin() bool {
token, err := windows.OpenCurrentProcessToken()
if err != nil {
return false
}
defer token.Close()
adminSid, err := windows.StringToSid(adminRoleID)
if err != nil {
return false
}
isMember, err := token.IsMember(adminSid)
return err == nil && isMember
}
func eventLogSourceExists() bool {
elog, err := eventlog.Open(appName)
if err != nil {
return false
}
defer elog.Close()
return true
}
func installEventLogSource() error {
if eventLogSourceExists() {
return nil
}
if !isAdmin() {
return fmt.Errorf("administrative privileges required for event log registration")
}
err := eventlog.InstallAsEventCreate(appName, eventlog.Error|eventlog.Warning|eventlog.Info)
if err != nil {
return fmt.Errorf("failed to install event log source: %v", err)
}
fmt.Println("Event log source installed successfully")
return nil
}
// logToConsole outputs a message to console with event type prefix
func logToConsole(eventType uint32, message string) {
fmt.Printf("[%s] %s\n", getEventTypeName(eventType), message)
}
// logEvent attempts to log to Windows Event Log, falls back to console on failure
func logEvent(eventType uint32, message string) error {
elog, err := eventlog.Open(appName)
if err != nil {
logToConsole(eventType, message)
return fmt.Errorf("failed to open event log: %v", err)
}
defer elog.Close()
switch eventType {
case eventlog.Info:
return elog.Info(infoEventID, message)
case eventlog.Warning:
return elog.Warning(warningEventID, message)
case eventlog.Error:
return elog.Error(errorEventID, message)
default:
return fmt.Errorf("unknown event type: %d", eventType)
}
}
// logEventSafe logs an event and ignores errors (for fire-and-forget logging)
func logEventSafe(eventType uint32, message string) {
if err := logEvent(eventType, message); err != nil {
logToConsole(eventType, message)
}
}
func getEventTypeName(eventType uint32) string {
switch eventType {
case eventlog.Info:
return "INFO"
case eventlog.Warning:
return "WARNING"
case eventlog.Error:
return "ERROR"
default:
return "UNKNOWN"
}
}
func showError(message string) {
logEventSafe(eventlog.Error, message)
showNotificationWithFallback(notificationTexts.Error, message, tooltips.Error+message)
}
// showNotificationWithFallback attempts desktop notification, falls back to tooltip
func showNotificationWithFallback(title, message, fallbackTooltip string) {
if err := beeep.Notify(title, message, ""); err != nil {
setTemporaryTooltip(fallbackTooltip, 3*time.Second)
}
}
// setTemporaryTooltip sets a temporary tooltip that reverts after duration
// Safely handles cases where systray is not available (e.g., in CI environments)
func setTemporaryTooltip(message string, duration time.Duration) {
defer func() {
if r := recover(); r != nil {
// Systray operations may fail in headless environments
logEventSafe(eventlog.Error, fmt.Sprintf("Tooltip operation failed (expected in CI): %v", r))
}
}()
systray.SetTooltip(message)
go func() {
defer func() {
if r := recover(); r != nil {
// Systray operations may fail in headless environments
logEventSafe(eventlog.Error, fmt.Sprintf("Tooltip reset failed (expected in CI): %v", r))
}
}()
time.Sleep(duration)
systray.SetTooltip(tooltips.Default)
}()
}