Skip to content

Commit

Permalink
Add support for Logger categories
Browse files Browse the repository at this point in the history
  • Loading branch information
dianaafanador3 committed May 30, 2024
1 parent 21ac01d commit c6c23cd
Show file tree
Hide file tree
Showing 11 changed files with 607 additions and 113 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ x.y.z Release notes (yyyy-MM-dd)
=============================================================
### Enhancements
* None.
* Update release packaging for Xcode 15.4.
* Added support for filtering logs by category. Users wil have more fine grained control over
the log level for each category as well.
```swift
Logger.shared.setLogLevel(.info, category: Category.Storage.transactions)
```

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-swift/issues/????), since v?.?.?)
* None.

<!-- ### Breaking Changes - ONLY INCLUDE FOR NEW MAJOR version -->
### Deprecations
* `RLMLogger.level`/`Logger.level` has been deprecated in favor of using `RLMLogger.setLevel:category:`/`Logger.setLevel(:category:)` and `RLMLogger.getLevelForCategory:`/`Logger.getLevel(for:)`.

### Compatibility
* Realm Studio: 15.0.0 or later.
Expand Down
4 changes: 4 additions & 0 deletions Realm.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@
AC81360F287F21350029F15E /* AsymmetricObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC81360E287F21350029F15E /* AsymmetricObject.swift */; };
AC813612287F21700029F15E /* RLMAsymmetricObject.h in Headers */ = {isa = PBXBuildFile; fileRef = AC813610287F21700029F15E /* RLMAsymmetricObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
AC813613287F21700029F15E /* RLMAsymmetricObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC813611287F21700029F15E /* RLMAsymmetricObject.mm */; };
AC848BEC2BFFA4AF0026A2A6 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC848BEB2BFFA4AF0026A2A6 /* Logger.swift */; };
AC8846762686573B00DF4A65 /* SwiftUISyncTestHostApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC8846752686573B00DF4A65 /* SwiftUISyncTestHostApp.swift */; };
AC8846782686573B00DF4A65 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC8846772686573B00DF4A65 /* ContentView.swift */; };
AC8846B72687BC4100DF4A65 /* SwiftUIServerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC8846B62687BC4100DF4A65 /* SwiftUIServerTests.swift */; };
Expand Down Expand Up @@ -910,6 +911,7 @@
AC81360E287F21350029F15E /* AsymmetricObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsymmetricObject.swift; sourceTree = "<group>"; };
AC813610287F21700029F15E /* RLMAsymmetricObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RLMAsymmetricObject.h; sourceTree = "<group>"; };
AC813611287F21700029F15E /* RLMAsymmetricObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RLMAsymmetricObject.mm; sourceTree = "<group>"; };
AC848BEB2BFFA4AF0026A2A6 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
AC8846732686573B00DF4A65 /* SwiftUISyncTestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUISyncTestHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
AC8846752686573B00DF4A65 /* SwiftUISyncTestHostApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUISyncTestHostApp.swift; sourceTree = "<group>"; };
AC8846772686573B00DF4A65 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1360,6 +1362,7 @@
AC7825B82ACD90BE007ABA4B /* Geospatial.swift */,
5D1534B71CCFF545008976D7 /* LinkingObjects.swift */,
5D660FE41BE98D670021E04F /* List.swift */,
AC848BEB2BFFA4AF0026A2A6 /* Logger.swift */,
0C3BD4D225C1C5AB007CFDD3 /* Map.swift */,
5D660FE51BE98D670021E04F /* Migration.swift */,
CF76F80124816B3800890DD2 /* MongoClient.swift */,
Expand Down Expand Up @@ -2555,6 +2558,7 @@
3F857A482769291800F9B9B1 /* KeyPathStrings.swift in Sources */,
5D1534B81CCFF545008976D7 /* LinkingObjects.swift in Sources */,
5D660FF21BE98D670021E04F /* List.swift in Sources */,
AC848BEC2BFFA4AF0026A2A6 /* Logger.swift in Sources */,
0C3BD4D325C1C5AB007CFDD3 /* Map.swift in Sources */,
5D660FF31BE98D670021E04F /* Migration.swift in Sources */,
CF76F80224816B3800890DD2 /* MongoClient.swift in Sources */,
Expand Down
44 changes: 40 additions & 4 deletions Realm/RLMLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ typedef RLM_CLOSED_ENUM(NSUInteger, RLMLogLevel) {
RLM_SWIFT_SENDABLE // invoked on a background thread
typedef void (^RLMLogFunction)(RLMLogLevel level, NSString *message);

/// A log callback function which can be set on RLMLogger.
///
/// The log function may be called from multiple threads simultaneously, and is
/// responsible for performing its own synchronization if any is required.
RLM_SWIFT_SENDABLE // invoked on a background thread
typedef void (^RLMLogCategoryFunction)(RLMLogLevel level, NSString *category, NSString *message) NS_REFINED_FOR_SWIFT;
/**
`RLMLogger` is used for creating your own custom logging logic.
Expand All @@ -63,8 +69,9 @@ typedef void (^RLMLogFunction)(RLMLogLevel level, NSString *message);
Set this custom logger as you default logger using `setDefaultLogger`.
RLMLogger.defaultLogger = [[RLMLogger alloc] initWithLevel:RLMLogLevelDebug
logFunction:^(RLMLogLevel level, NSString * message) {
NSLog(@"Realm Log - %lu, %@", (unsigned long)level, message);
category:RLMLogCategoryRealm
logFunction:^(RLMLogLevel level, NSString *category, NSString *message) {
NSLog(@"Realm Log - %lu, %@, %@", (unsigned long)level, category, message);
}];
@note By default default log threshold level is `RLMLogLevelInfo`, and logging strings are output to Apple System Logger.
Expand All @@ -74,7 +81,8 @@ typedef void (^RLMLogFunction)(RLMLogLevel level, NSString *message);
/**
Gets the logging threshold level used by the logger.
*/
@property (nonatomic) RLMLogLevel level;
@property (nonatomic) RLMLogLevel level
__attribute__((deprecated("Use `setLevel(level:category)` or `setLevel:category` instead.")));

/// :nodoc:
- (instancetype)init NS_UNAVAILABLE;
Expand All @@ -85,7 +93,19 @@ typedef void (^RLMLogFunction)(RLMLogLevel level, NSString *message);
@param level The log level to be set for the logger.
@param logFunction The log function which will be invoked whenever there is a log message.
*/
- (instancetype)initWithLevel:(RLMLogLevel)level logFunction:(RLMLogFunction)logFunction;
- (instancetype)initWithLevel:(RLMLogLevel)level logFunction:(RLMLogFunction)logFunction
__attribute__((deprecated("Use `initWithLevel:logFunction:` instead.")));

/**
Creates a logger with the associated log level and the logic function to define your own logging logic.
@param level The log level to be set for the logger.
@param category The log category to be set for the logger.
@param logFunction The log function which will be invoked whenever there is a log message.
*/
- (instancetype)initWithLevel:(RLMLogLevel)level
category:(NSString *)category
logFunction:(RLMLogCategoryFunction)logFunction;

#pragma mark RLMLogger Default Logger API

Expand All @@ -94,6 +114,22 @@ typedef void (^RLMLogFunction)(RLMLogLevel level, NSString *message);
*/
@property (class) RLMLogger *defaultLogger NS_SWIFT_NAME(shared);

/**
Sets the logger's associated log and category.
@param level The log level to be set for the logger.
@param category The log function which will be invoked whenever there is a log message.
*/
- (void)setLevel:(RLMLogLevel)level category:(NSString *)category NS_REFINED_FOR_SWIFT;

/**
Gets the logger's associated level for the specified category.
@param category The log category which we need the level.
@returns The log level for the specified category
*/
- (RLMLogLevel)getLevelForCategory:(NSString *)category NS_REFINED_FOR_SWIFT;

@end

RLM_HEADER_AUDIT_END(nullability)
56 changes: 48 additions & 8 deletions Realm/RLMLogger.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@

#import <realm/util/logger.hpp>

typedef void (^RLMLoggerFunction)(RLMLogLevel level, NSString *message);
typedef void (^RLMLoggerFunction)(RLMLogLevel level, NSString *category, NSString *message);

using namespace realm;
using Logger = realm::util::Logger;
using Level = Logger::Level;
using LogCategory = realm::util::LogCategory;

namespace {
static Level levelForLogLevel(RLMLogLevel logLevel) {
Expand Down Expand Up @@ -61,7 +62,7 @@ static RLMLogLevel logLevelForLevel(Level logLevel) {

static NSString* levelPrefix(Level logLevel) {
switch (logLevel) {
case Level::off:
case Level::off: return @"";
case Level::all: return @"";
case Level::trace: return @"Trace";
case Level::debug: return @"Debug";
Expand All @@ -75,18 +76,18 @@ static RLMLogLevel logLevelForLevel(Level logLevel) {
}

struct CocoaLogger : public Logger {
void do_log(const realm::util::LogCategory&, Level level, const std::string& message) override {
NSLog(@"%@: %@", levelPrefix(level), RLMStringDataToNSString(message));
void do_log(const LogCategory& category, Level level, const std::string& message) override {
NSLog(@"%@:%@ %@", levelPrefix(level), RLMStringDataToNSString(category.get_name()), RLMStringDataToNSString(message));
}
};

class CustomLogger : public Logger {
public:
RLMLoggerFunction function;
void do_log(const realm::util::LogCategory&, Level level, const std::string& message) override {
void do_log(const LogCategory& category, Level level, const std::string& message) override {
@autoreleasepool {
if (function) {
function(logLevelForLevel(level), RLMStringDataToNSString(message));
function(logLevelForLevel(level), RLMStringDataToNSString(category.get_name()), RLMStringDataToNSString(message));
}
}
}
Expand Down Expand Up @@ -120,10 +121,26 @@ - (instancetype)initWithLogger:(std::shared_ptr<Logger>)logger {
return self;
}

- (instancetype)initWithLevel:(RLMLogLevel)level logFunction:(RLMLogFunction)logFunction {
- (instancetype)initWithLevel:(RLMLogLevel)level
logFunction:(RLMLogFunction)logFunction {
if (self = [super init]) {
auto logger = std::make_shared<CustomLogger>();
logger->set_level_threshold(levelForLogLevel(level));
auto block = [logFunction](RLMLogLevel level, NSString *, NSString *message) {
logFunction(level, message);
};
logger->function = block;
self->_logger = logger;
}
return self;
}

- (instancetype)initWithLevel:(RLMLogLevel)level
category:(NSString *)category
logFunction:(RLMLogCategoryFunction)logFunction {
if (self = [super init]) {
auto logger = std::make_shared<CustomLogger>();
logger->set_level_threshold(LogCategory::get_category(category.UTF8String), levelForLogLevel(level));
logger->function = logFunction;
self->_logger = logger;
}
Expand All @@ -140,11 +157,34 @@ - (void)logWithLevel:(RLMLogLevel)logLevel message:(NSString *)message, ... {
}
}

- (void)logLevel:(RLMLogLevel)logLevel message:(NSString *)message {
- (void)logWithLevel:(RLMLogLevel)logLevel category:(NSString *)category message:(NSString *)message {
auto level = levelForLogLevel(logLevel);
if (_logger->would_log(level)) {
_logger->log(level, "%1", message.UTF8String);
_logger->log(LogCategory::get_category(category.UTF8String), levelForLogLevel(logLevel), message.UTF8String);
}
}

- (void)setLevel:(RLMLogLevel)level category:(NSString *)category {
RLMLogger *defaultLogger = [RLMLogger defaultLogger];
defaultLogger->_logger->set_level_threshold(LogCategory::get_category(category.UTF8String), levelForLogLevel(level));
}

- (RLMLogLevel)getLevelForCategory:(NSString *)category {
RLMLogger *defaultLogger = [RLMLogger defaultLogger];
return logLevelForLevel(defaultLogger->_logger->get_level_threshold(LogCategory::get_category(category.UTF8String)));
}

#pragma mark Testing

+ (NSArray<NSString *> *)getAllCategories {
NSMutableArray<NSString *> *a = [NSMutableArray new];
auto categories = LogCategory::get_category_names();
for (const auto& category : categories) {
NSString *categoryName = RLMStringDataToNSString(category);
[a addObject:categoryName];
}
return a;
}

#pragma mark Global Logger Setter
Expand Down
15 changes: 14 additions & 1 deletion Realm/RLMLogger_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,20 @@ RLM_HEADER_AUDIT_BEGIN(nullability)
@param message The message to log.
*/
- (void)logWithLevel:(RLMLogLevel)logLevel message:(NSString *)message, ... NS_SWIFT_UNAVAILABLE("");
- (void)logLevel:(RLMLogLevel)logLevel message:(NSString *)message;

/**
Log a message to the supplied level.
@param logLevel The log level for the message.
@param category The log category for the message.
@param message The message to log.
*/
- (void)logWithLevel:(RLMLogLevel)logLevel category:(NSString *)category message:(NSString *)message;

/**
Gets all the categories from Core. This is to be used for testing purposes only.
*/
+ (NSArray<NSString *> *)getAllCategories;
@end

RLM_HEADER_AUDIT_END(nullability)
9 changes: 5 additions & 4 deletions Realm/RLMSyncManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

// NEXT-MAJOR: All the code associated to the logger from sync manager should be removed.
using Level = realm::util::Logger::Level;
using LogCategory = realm::util::LogCategory;

namespace {
Level levelForSyncLogLevel(RLMSyncLogLevel logLevel) {
Expand Down Expand Up @@ -73,14 +74,14 @@ RLMSyncLogLevel logLevelForLevel(Level logLevel) {
#pragma mark - Loggers

struct CocoaSyncLogger : public realm::util::Logger {
void do_log(const realm::util::LogCategory&, Level, const std::string& message) override {
NSLog(@"Sync: %@", RLMStringDataToNSString(message));
void do_log(const realm::util::LogCategory& category, Level, const std::string& message) override {
NSLog(@"%@: %@", RLMStringDataToNSString(category.get_name()), RLMStringDataToNSString(message));
}
};

static std::unique_ptr<realm::util::Logger> defaultSyncLogger(realm::util::Logger::Level level) {
auto logger = std::make_unique<CocoaSyncLogger>();
logger->set_level_threshold(level);
logger->set_level_threshold(LogCategory::sync, level);
return std::move(logger);
}

Expand Down Expand Up @@ -154,7 +155,7 @@ - (void)setLogger:(RLMSyncLogFunction)logFn {
_syncManager->set_logger_factory([logFn](realm::util::Logger::Level level) {
auto logger = std::make_unique<CallbackLogger>();
logger->logFn = logFn;
logger->set_level_threshold(level);
logger->set_level_threshold(LogCategory::sync, level);
return logger;
});
}
Expand Down
Loading

0 comments on commit c6c23cd

Please sign in to comment.