// _____ _ // |_ _| |_ _ _ ___ ___ _ __ __ _ // | | | ' \| '_/ -_) -_) ' \/ _` |_ // |_| |_||_|_| \___\___|_|_|_\__,_(_) // // Threema iOS Client // Copyright (c) 2019-2020 Threema GmbH // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License, version 3, // as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #import "LogFormatterCustom.h" #import @implementation LogFormatterCustom { NSString *processName; NSString *processID; } static NSString *dateFormatString = @"yyyy-MM-dd HH:mm:ss.SSSZZZZZ"; - (instancetype)init { self = [super init]; if (self) { processName = [[NSProcessInfo processInfo] processName]; processID = [NSString stringWithFormat:@"%i", (int)getpid()]; } return self; } - (NSString *)stringFromDate:(NSDate *)date { atomic_fetch_add_explicit(&atomicLoggerCount, 0, memory_order_relaxed); if (atomicLoggerCount <= 1) { // Single-threaded mode. if (threadUnsafeDateFormatter == nil) { threadUnsafeDateFormatter = [[NSDateFormatter alloc] init]; [threadUnsafeDateFormatter setDateFormat:dateFormatString]; } return [threadUnsafeDateFormatter stringFromDate:date]; } else { // Multi-threaded mode. // NSDateFormatter is NOT thread-safe. NSString *key = @"MyCustomFormatter_NSDateFormatter"; NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary]; NSDateFormatter *dateFormatter = [threadDictionary objectForKey:key]; if (dateFormatter == nil) { dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:dateFormatString]; [threadDictionary setObject:dateFormatter forKey:key]; } return [dateFormatter stringFromDate:date]; } } - (NSString *)formatLogMessage:(DDLogMessage *)logMessage { NSString *logLevel; switch (logMessage->_flag) { case DDLogFlagError : logLevel = @"[Err]"; break; case DDLogFlagWarning : logLevel = @"[Warn]"; break; case DDLogFlagInfo : logLevel = @"[Info]"; break; case DDLogFlagDebug : logLevel = @"[Debug]"; break; case DDLogFlagNotice : logLevel = @"[Notice]"; break; default : logLevel = @"[Verbose]"; break; } NSString *dateAndTime = [self stringFromDate:logMessage.timestamp]; return [NSString stringWithFormat:@"%@ %@[%@:%@] %@:%lu %@ %@", dateAndTime, processName, processID, logMessage->_threadID, logMessage->_fileName, logMessage->_line, logLevel, logMessage->_message]; } - (void)didAddToLogger:(id )logger { atomic_fetch_add_explicit(&atomicLoggerCount, 1, memory_order_relaxed); } - (void)willRemoveFromLogger:(id )logger { atomic_fetch_sub_explicit(&atomicLoggerCount, 1, memory_order_relaxed); } @end