Subversion Repositories Mobile Apps.GyroMouse

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pmbaty 1
#import "DDDispatchQueueLogFormatter.h"
2
#import <libkern/OSAtomic.h>
3
 
4
/**
5
 * Welcome to Cocoa Lumberjack!
6
 *
7
 * The project page has a wealth of documentation if you have any questions.
8
 * https://github.com/CocoaLumberjack/CocoaLumberjack
9
 *
10
 * If you're new to the project you may wish to read the "Getting Started" wiki.
11
 * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted
12
**/
13
 
14
#if ! __has_feature(objc_arc)
15
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
16
#endif
17
 
18
 
19
@implementation DDDispatchQueueLogFormatter
20
{
21
    int32_t atomicLoggerCount;
22
    NSDateFormatter *threadUnsafeDateFormatter; // Use [self stringFromDate]
23
 
24
    OSSpinLock lock;
25
 
26
    NSUInteger _minQueueLength;           // _prefix == Only access via atomic property
27
    NSUInteger _maxQueueLength;           // _prefix == Only access via atomic property
28
    NSMutableDictionary *_replacements;   // _prefix == Only access from within spinlock
29
}
30
 
31
- (id)init
32
{
33
    if ((self = [super init]))
34
    {
35
        dateFormatString = @"yyyy-MM-dd HH:mm:ss:SSS";
36
 
37
        atomicLoggerCount = 0;
38
        threadUnsafeDateFormatter = nil;
39
 
40
        _minQueueLength = 0;
41
        _maxQueueLength = 0;
42
        _replacements = [[NSMutableDictionary alloc] init];
43
 
44
        // Set default replacements:
45
 
46
        _replacements[@"com.apple.main-thread"] = @"main";
47
    }
48
    return self;
49
}
50
 
51
 
52
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53
#pragma mark Configuration
54
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55
 
56
@synthesize minQueueLength = _minQueueLength;
57
@synthesize maxQueueLength = _maxQueueLength;
58
 
59
- (NSString *)replacementStringForQueueLabel:(NSString *)longLabel
60
{
61
    NSString *result = nil;
62
 
63
    OSSpinLockLock(&lock);
64
    {
65
        result = _replacements[longLabel];
66
    }
67
    OSSpinLockUnlock(&lock);
68
 
69
    return result;
70
}
71
 
72
- (void)setReplacementString:(NSString *)shortLabel forQueueLabel:(NSString *)longLabel
73
{
74
    OSSpinLockLock(&lock);
75
    {
76
        if (shortLabel)
77
            _replacements[longLabel] = shortLabel;
78
        else
79
            [_replacements removeObjectForKey:longLabel];
80
    }
81
    OSSpinLockUnlock(&lock);
82
}
83
 
84
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85
#pragma mark DDLogFormatter
86
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87
 
88
- (NSString *)stringFromDate:(NSDate *)date
89
{
90
    int32_t loggerCount = OSAtomicAdd32(0, &atomicLoggerCount);
91
 
92
    if (loggerCount <= 1)
93
    {
94
        // Single-threaded mode.
95
 
96
        if (threadUnsafeDateFormatter == nil)
97
        {
98
            threadUnsafeDateFormatter = [[NSDateFormatter alloc] init];
99
            [threadUnsafeDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
100
            [threadUnsafeDateFormatter setDateFormat:dateFormatString];
101
        }
102
 
103
        [threadUnsafeDateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]];
104
        return [threadUnsafeDateFormatter stringFromDate:date];
105
    }
106
    else
107
    {
108
        // Multi-threaded mode.
109
        // NSDateFormatter is NOT thread-safe.
110
 
111
        NSString *key = @"DispatchQueueLogFormatter_NSDateFormatter";
112
 
113
        NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary];
114
        NSDateFormatter *dateFormatter = threadDictionary[key];
115
 
116
        if (dateFormatter == nil)
117
        {
118
            dateFormatter = [[NSDateFormatter alloc] init];
119
            [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
120
            [dateFormatter setDateFormat:dateFormatString];
121
 
122
            threadDictionary[key] = dateFormatter;
123
        }
124
 
125
        [dateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]];
126
        return [dateFormatter stringFromDate:date];
127
    }
128
}
129
 
130
- (NSString *)queueThreadLabelForLogMessage:(DDLogMessage *)logMessage
131
{
132
    // As per the DDLogFormatter contract, this method is always invoked on the same thread/dispatch_queue
133
 
134
    NSUInteger minQueueLength = self.minQueueLength;
135
    NSUInteger maxQueueLength = self.maxQueueLength;
136
 
137
    // Get the name of the queue, thread, or machID (whichever we are to use).
138
 
139
    NSString *queueThreadLabel = nil;
140
 
141
    BOOL useQueueLabel = YES;
142
    BOOL useThreadName = NO;
143
 
144
    if (logMessage->queueLabel)
145
    {
146
        // If you manually create a thread, it's dispatch_queue will have one of the thread names below.
147
        // Since all such threads have the same name, we'd prefer to use the threadName or the machThreadID.
148
 
149
        char *names[] = { "com.apple.root.low-priority",
150
                          "com.apple.root.default-priority",
151
                          "com.apple.root.high-priority",
152
                          "com.apple.root.low-overcommit-priority",
153
                          "com.apple.root.default-overcommit-priority",
154
                          "com.apple.root.high-overcommit-priority"     };
155
 
156
        int length = sizeof(names) / sizeof(char *);
157
 
158
        int i;
159
        for (i = 0; i < length; i++)
160
        {
161
            if (strcmp(logMessage->queueLabel, names[i]) == 0)
162
            {
163
                useQueueLabel = NO;
164
                useThreadName = [logMessage->threadName length] > 0;
165
                break;
166
            }
167
        }
168
    }
169
    else
170
    {
171
        useQueueLabel = NO;
172
        useThreadName = [logMessage->threadName length] > 0;
173
    }
174
 
175
    if (useQueueLabel || useThreadName)
176
    {
177
        NSString *fullLabel;
178
        NSString *abrvLabel;
179
 
180
        if (useQueueLabel)
181
            fullLabel = @(logMessage->queueLabel);
182
        else
183
            fullLabel = logMessage->threadName;
184
 
185
        OSSpinLockLock(&lock);
186
        {
187
            abrvLabel = _replacements[fullLabel];
188
        }
189
        OSSpinLockUnlock(&lock);
190
 
191
        if (abrvLabel)
192
            queueThreadLabel = abrvLabel;
193
        else
194
            queueThreadLabel = fullLabel;
195
    }
196
    else
197
    {
198
        queueThreadLabel = [NSString stringWithFormat:@"%x", logMessage->machThreadID];
199
    }
200
 
201
    // Now use the thread label in the output
202
 
203
    NSUInteger labelLength = [queueThreadLabel length];
204
 
205
    // labelLength > maxQueueLength : truncate
206
    // labelLength < minQueueLength : padding
207
    //                              : exact
208
 
209
    if ((maxQueueLength > 0) && (labelLength > maxQueueLength))
210
    {
211
        // Truncate
212
 
213
        return [queueThreadLabel substringToIndex:maxQueueLength];
214
    }
215
    else if (labelLength < minQueueLength)
216
    {
217
        // Padding
218
 
219
        NSUInteger numSpaces = minQueueLength - labelLength;
220
 
221
        char spaces[numSpaces + 1];
222
        memset(spaces, ' ', numSpaces);
223
        spaces[numSpaces] = '\0';
224
 
225
        return [NSString stringWithFormat:@"%@%s", queueThreadLabel, spaces];
226
    }
227
    else
228
    {
229
        // Exact
230
 
231
        return queueThreadLabel;
232
    }
233
}
234
 
235
- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
236
{
237
    NSString *timestamp = [self stringFromDate:(logMessage->timestamp)];
238
    NSString *queueThreadLabel = [self queueThreadLabelForLogMessage:logMessage];
239
 
240
    return [NSString stringWithFormat:@"%@ [%@] %@", timestamp, queueThreadLabel, logMessage->logMsg];
241
}
242
 
243
- (void)didAddToLogger:(id <DDLogger>)logger
244
{
245
    OSAtomicIncrement32(&atomicLoggerCount);
246
}
247
 
248
- (void)willRemoveFromLogger:(id <DDLogger>)logger
249
{
250
    OSAtomicDecrement32(&atomicLoggerCount);
251
}
252
 
253
@end