forked from gnachman/iTerm2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDebugLogging.m
More file actions
144 lines (133 loc) · 4.76 KB
/
DebugLogging.m
File metadata and controls
144 lines (133 loc) · 4.76 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
//
// DebugLogging.m
// iTerm
//
// Created by George Nachman on 10/13/13.
//
//
#import "DebugLogging.h"
#import "NSView+RecursiveDescription.h"
#import <Cocoa/Cocoa.h>
#include <sys/time.h>
static NSMutableString* gDebugLogStr = nil;
static NSMutableString* gDebugLogStr2 = nil;
static NSRecursiveLock *gDebugLogLock = nil;
BOOL gDebugLogging = NO;
int gDebugLogFile = -1;
static void WriteDebugLogHeader() {
NSMutableString *windows = [NSMutableString string];
for (NSWindow *window in [[NSApplication sharedApplication] windows]) {
[windows appendFormat:@"\nWindow %@, frame=%@. isMain=%d isKey=%d\n%@\n",
window,
[NSValue valueWithRect:window.frame],
(int)[window isMainWindow],
(int)[window isKeyWindow],
[window.contentView iterm_recursiveDescription]];
}
NSString *header = [NSString stringWithFormat:
@"iTerm2 version: %@\n"
@"Date: %@ (%lld)\n"
@"Key window: %@\n"
@"Windows: %@\n"
@"------ END HEADER ------\n\n",
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"],
[NSDate date],
(long long)[[NSDate date] timeIntervalSince1970],
[[NSApplication sharedApplication] keyWindow],
windows];
NSData* data = [header dataUsingEncoding:NSUTF8StringEncoding];
int written = write(gDebugLogFile, [data bytes], [data length]);
assert(written == [data length]);
}
static void WriteDebugLogFooter() {
NSMutableString *windows = [NSMutableString string];
for (NSWindow *window in [[NSApplication sharedApplication] windows]) {
[windows appendFormat:@"\nWindow %@, frame=%@. isMain=%d isKey=%d\n%@\n",
window,
[NSValue valueWithRect:window.frame],
(int)[window isMainWindow],
(int)[window isKeyWindow],
[window.contentView iterm_recursiveDescription]];
}
NSString *header = [NSString stringWithFormat:
@"------ BEGIN FOOTER -----\n"
@"Windows: %@\n",
windows];
NSData* data = [header dataUsingEncoding:NSUTF8StringEncoding];
int written = write(gDebugLogFile, [data bytes], [data length]);
assert(written == [data length]);
}
static void SwapDebugLog() {
[gDebugLogLock lock];
NSMutableString* temp;
temp = gDebugLogStr;
gDebugLogStr = gDebugLogStr2;
gDebugLogStr2 = temp;
[gDebugLogLock unlock];
}
static void FlushDebugLog() {
[gDebugLogLock lock];
NSData* data = [gDebugLogStr dataUsingEncoding:NSUTF8StringEncoding];
size_t written = write(gDebugLogFile, [data bytes], [data length]);
assert(written == [data length]);
[gDebugLogStr setString:@""];
[gDebugLogLock unlock];
}
int DebugLogImpl(const char *file, int line, const char *function, NSString* value)
{
if (gDebugLogging) {
struct timeval tv;
gettimeofday(&tv, NULL);
[gDebugLogLock lock];
const char *lastSlash = strrchr(file, '/');
if (!lastSlash) {
lastSlash = file;
} else {
lastSlash++;
}
[gDebugLogStr appendFormat:@"%lld.%08lld %s:%d (%s): ",
(long long)tv.tv_sec, (long long)tv.tv_usec, lastSlash, line, function];
[gDebugLogStr appendString:value];
[gDebugLogStr appendString:@"\n"];
if ([gDebugLogStr length] > 100000000) {
SwapDebugLog();
[gDebugLogStr2 setString:@""];
}
[gDebugLogLock unlock];
}
return 1;
}
void ToggleDebugLogging(void) {
if (!gDebugLogging) {
NSRunAlertPanel(@"Debug Logging Enabled",
@"Writing to /tmp/debuglog.txt",
@"OK", nil, nil);
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
gDebugLogLock = [[NSRecursiveLock alloc] init];
});
[gDebugLogLock lock];
gDebugLogFile = open("/tmp/debuglog.txt", O_TRUNC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
WriteDebugLogHeader();
gDebugLogStr = [[NSMutableString alloc] init];
gDebugLogStr2 = [[NSMutableString alloc] init];
gDebugLogging = !gDebugLogging;
[gDebugLogLock unlock];
} else {
[gDebugLogLock lock];
gDebugLogging = !gDebugLogging;
SwapDebugLog();
FlushDebugLog();
SwapDebugLog();
FlushDebugLog();
WriteDebugLogFooter();
close(gDebugLogFile);
gDebugLogFile=-1;
NSRunAlertPanel(@"Debug Logging Stopped",
@"Please compress and send /tmp/debuglog.txt to the developers.",
@"OK", nil, nil);
[gDebugLogStr release];
[gDebugLogStr2 release];
[gDebugLogLock unlock];
}
}