From 132d04348d3946c64429f0919423c2992167f22d Mon Sep 17 00:00:00 2001 From: Guogang Li Date: Wed, 28 May 2025 14:18:59 -0700 Subject: [PATCH] Convert iOS platform logging to ABSL logging PiperOrigin-RevId: 764413778 --- internal/platform/implementation/apple/BUILD | 16 ++ .../apple/nearby_logger_writer.h | 29 +++ .../apple/nearby_logger_writer.mm | 175 ++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 internal/platform/implementation/apple/nearby_logger_writer.h create mode 100644 internal/platform/implementation/apple/nearby_logger_writer.mm diff --git a/internal/platform/implementation/apple/BUILD b/internal/platform/implementation/apple/BUILD index 73fea964..3d5f96fd 100644 --- a/internal/platform/implementation/apple/BUILD +++ b/internal/platform/implementation/apple/BUILD @@ -164,6 +164,22 @@ objc_library( ], ) +objc_library( + name = "logger_writer", + srcs = [ + "nearby_logger_writer.mm", + ], + hdrs = [ + "nearby_logger_writer.h", + ], + # Prevent Objective-C++ headers from being pulled into swift. + aspect_hints = ["//tools/build_defs/swift:no_module"], + deps = [ + "//internal/platform:logging", + "//third_party/objective_c/google_toolbox_for_mac:GTM_Logger", + ], +) + cc_library( name = "Platform_cc", srcs = [ diff --git a/internal/platform/implementation/apple/nearby_logger_writer.h b/internal/platform/implementation/apple/nearby_logger_writer.h new file mode 100644 index 00000000..80ad9c40 --- /dev/null +++ b/internal/platform/implementation/apple/nearby_logger_writer.h @@ -0,0 +1,29 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PLATFORM_IMPL_APPLE_NEARBY_LOGGER_WRITER_H_ +#define PLATFORM_IMPL_APPLE_NEARBY_LOGGER_WRITER_H_ + +namespace nearby { +namespace apple { + +// NearbyLoggerWriter will handle GTM logs as ABSL logs. +// The SDK developer can setup ABSL log listener to receive all logs from Nearby +// connections. +void EnableNearbyLoggerWriter(); + +} // namespace apple +} // namespace nearby + +#endif // PLATFORM_IMPL_APPLE_NEARBY_LOGGER_WRITER_H_ diff --git a/internal/platform/implementation/apple/nearby_logger_writer.mm b/internal/platform/implementation/apple/nearby_logger_writer.mm new file mode 100644 index 00000000..26e3aaa1 --- /dev/null +++ b/internal/platform/implementation/apple/nearby_logger_writer.mm @@ -0,0 +1,175 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "internal/platform/implementation/apple/nearby_logger_writer.h" + +#include +#include + +#include "internal/platform/logging.h" + +#import "GoogleToolboxForMac/GTMLogger.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Log message with function name and message content. + * The log message will be used to pass data from NearbyLoggerFormatter to NearbyLoggerWriter. Due + * to the limitation of GTMLogger, we cannot get the file name and line number. + */ +@interface NearbyLogMessage : NSObject + +@property(nonatomic, readonly) uint32_t messageIndex; +@property(nonatomic, readonly) NSString *functionName; +@property(nonatomic, readonly) NSString *logMessage; + +/** + * Initializes the log message with message index, function name and message content. + * + * @param messageIndex The message index. + * @param functionName The function name. + * @param logMessage The log message. + * @return The initialized log message. + */ +- (instancetype)initWithMessageIndex:(uint32_t)messageIndex + functionName:(NSString *)functionName + logMessage:(NSString *)logMessage; +@end + +@implementation NearbyLogMessage +- (instancetype)initWithMessageIndex:(uint32_t)messageIndex + functionName:(NSString *)functionName + logMessage:(NSString *)logMessage { + if (self = [super init]) { + _messageIndex = messageIndex; + _functionName = [functionName copy]; + _logMessage = [logMessage copy]; + } + return self; +} +@end + +/** + * The customised log writer for `GTMLogWriter` is used to write the GTM log message as ABSL log + * message. + */ +@interface NearbyLoggerWriter : NSObject +@end + +#pragma mark - NearbyLoggerWriter + +@implementation NearbyLoggerWriter { + NSMutableArray *_messages; +} + +- (instancetype)initWithMessages:(NSMutableArray *)logMessages { + if ((self = [super init])) { + _messages = logMessages; + } + return self; +} + +- (void)logMessage:(NSString *)message level:(GTMLoggerLevel)level { + @synchronized(_messages) { + if (_messages.count == 0) { + return; + } + + uint32_t messageIndex = [message intValue]; + NearbyLogMessage *message = [_messages firstObject]; + [_messages removeObjectAtIndex:0]; + if (messageIndex > message.messageIndex) { + return; + } + + switch (level) { + case kGTMLoggerLevelDebug: + VLOG(1).AtLocation([message.functionName UTF8String], 0) + << std::string([message.logMessage UTF8String]); + break; + case kGTMLoggerLevelInfo: + LOG(INFO).AtLocation([message.functionName UTF8String], 0) + << std::string([message.logMessage UTF8String]); + break; + case kGTMLoggerLevelError: + LOG(ERROR).AtLocation([message.functionName UTF8String], 0) + << std::string([message.logMessage UTF8String]); + break; + case kGTMLoggerLevelAssert: + LOG(FATAL).AtLocation([message.functionName UTF8String], 0) + << std::string([message.logMessage UTF8String]); + break; + case kGTMLoggerLevelUnknown: + LOG(INFO).AtLocation([message.functionName UTF8String], 0) + << std::string([message.logMessage UTF8String]); + break; + } + } +} + +@end // NearbyLoggerWriter + +/** + * The customised log formatter for `GTMLogBasicFormatter`. It is used to get function name and + * message content. + */ +@interface NearbyLoggerFormatter : GTMLogBasicFormatter { + uint32_t _messageIndex; + NSMutableArray *_messages; +} +@end + +#pragma mark - NearbyLoggerFormatter +@implementation NearbyLoggerFormatter + +- (instancetype)initWithMessages:(NSMutableArray *)logMessages { + if (self = [super init]) { + _messageIndex = 0; + _messages = logMessages; + } + return self; +} + +- (NSString *)stringForFunc:(nullable NSString *)func + withFormat:(NSString *)format + valist:(va_list)args + level:(GTMLoggerLevel)level { + @synchronized(_messages) { + NSString *prettyNameForFunc = [self prettyNameForFunc:func]; + NSString *logMessage = [super stringForFunc:func withFormat:format valist:args level:level]; + NearbyLogMessage *message = [[NearbyLogMessage alloc] initWithMessageIndex:_messageIndex + functionName:prettyNameForFunc + logMessage:logMessage]; + [_messages addObject:message]; + return [NSString stringWithFormat:@"%d", (int)_messageIndex++]; + } +} + +@end // NearbyLoggerFormatter + +NS_ASSUME_NONNULL_END + +namespace nearby { +namespace apple { + +void EnableNearbyLoggerWriter() { + NSMutableArray *tupleArray = [[NSMutableArray alloc] init]; + GTMLogger.sharedLogger = + [GTMLogger loggerWithWriter:[[NearbyLoggerWriter alloc] initWithMessages:tupleArray] + formatter:[[NearbyLoggerFormatter alloc] initWithMessages:tupleArray] + filter:nil]; +} + +} // namespace apple +} // namespace nearby