-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Split GoogleUtilities from FirebaseCore #1370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This PR is not yet ready for detailed review. Current status is the six components in the Firebase Xcode project build and pass their unit tests with the new structure. For now, I've left the Utilities unit tests combined with Core. Next steps:
cc: @ryanwilson, @baolocdo, @tejasd |
Does this name (and grouping) at all align with Android? How does this relate to firebase_common over there? It's getting hard to discuss/reason about dependencies across the platforms. |
916d170
to
a5ccdea
Compare
Travis is green and the PR is ready for review. I'm planning to wait until after the 5.2.0 merge back to master before merging this one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we call it Utilities or something different from FirebaseUtilities? The point of having a separate module is that it can be depended on by Analytics without explicitly mentioning Firebase.
@baolocdo Do you have a suggestion for something more specific than What exactly is the reason for not mentioning Firebase? It seems that FirebaseUtilities is the most descriptive since the Firebase team owns the code and it the utilities are primarily used by Firebase. Analytics uses other utility pods already like GoogleToolboxForMac and nanopb. |
@salqadri Please help with the naming of the Utilities pod. |
b001565
to
bf3a795
Compare
Now ready for review:
Next step is integration with closed source dependencies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to stop reviewing. Github is going to break. I can already feel it slowing down while I'm typing.
This really should have been three PRs:
- Define GoogleUtilities, forking Core stuff but otherwise not changing it.
- Integrate GoogleUtilities into the various builds
- Migrate usage of Core APIs to GoogleUtilities as needed
If you have the stomach for it we should rebase squash this state and then split it up.
|
||
@property(nonatomic) id processInfoMock; | ||
|
||
@end | ||
|
||
@implementation FIRAppEnvironmentUtilTest | ||
@implementation GULAppEnvironmentUtilTest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this test move along with the sources?
This comment applies both here and to the other tests in Core in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. The tests will be factored out in a subsequent PR.
Example/Core/Tests/FIRLoggerTest.m
Outdated
@@ -18,26 +18,27 @@ | |||
#import "FIRTestCase.h" | |||
|
|||
#import <FirebaseCore/FIRLogger.h> | |||
#import <GoogleUtilities/GULLogger.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem like anything should import both FIRLogger and GULLogger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Adding a TODO comment to split FIRLoggerTest from GULLoggerTest.
Example/Podfile
Outdated
|
||
target 'Core_Example_iOS' do | ||
platform :ios, '8.0' | ||
|
||
# The next line is the forcing function for the Firebase pod. The Firebase | ||
# version's subspecs should depend on the component versions in their | ||
# corresponding podspec's. | ||
pod 'Firebase/Core', '5.3.0' | ||
pod 'Firebase/CoreOnly', '5.3.0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be "CoreCore" :-P.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:) This is the change that excludes FirebaseAnalytics and its no longer valid current dependencies from the unit tests.
Firebase/Core/FIRLogger.m
Outdated
#import "FIRLoggerLevel.h" | ||
#import "Private/FIRVersion.h" | ||
#import "third_party/FIRAppEnvironmentUtil.h" | ||
#import <GoogleUtilities/GULAppEnvironmentUtil.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: import order should be
- self header
- system headers
- other headers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually all deleted here and reordered in GULLogger.m
Firebase/Core/FIRLogger.m
Outdated
sMessageCodeRegex = | ||
[NSRegularExpression regularExpressionWithPattern:kMessageCodePattern options:0 error:NULL]; | ||
#endif | ||
GULLoggerInitializeASL([arguments containsObject:kFIRDisableDebugModeApplicationArgument], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there an API review for this?
If not:
- Let's drop "ASL", which is deprecated. We should eventually move to
os_log
. - Is there any way we can avoid passing three booleans to this? It's a terrible interface.
- Is there a way to translate debug modes into a maximum log level instead so that GULLogger doesn't even have to be aware of this wart?
In particular it seems like if argument processing is to be done here, then we should completely figure out if we want debug mode from the arguments locally. Passing two booleans that seem like logical inverses of each other seems wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to moving to os_log
but it's only available on iOS 10+, so we'll have to keep ASL
around until we drop support for iOS 8 and 9 (will be a while).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the UserDefaults stuff back to FIRLogger and reduced to two booleans. Overall, this really needs an overall rewrite with a breaking change.
#include <unistd.h> | ||
|
||
/// Arguments passed on launch. | ||
NSString *const kGULDisableDebugModeApplicationArgument = @"-GULDebugDisabled"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted
NSString *const kGULLoggerForceSDTERRApplicationArgument = @"-GULLoggerForceSTDERR"; | ||
|
||
/// Key for the debug mode bit in NSUserDefaults. | ||
NSString *const kGULPersistedDebugModeKey = @"/google/utilities/debug_mode"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation is now split-brained. Why are we handling command-line arguments for debug mode in FIRLogger, but NSUserDefaults here?
Either insulate GULLogger from knowing about this gunk, or just put it all in here. This combined approach is even harder to reason about than the old system.
const char *kGULLoggerASLClientFacilityName = "com.google.utilities.app.logger"; | ||
|
||
/// Keys for the number of errors and warnings logged. | ||
NSString *const kGULLoggerErrorCountKey = @"/google/utilities/count_of_errors_logged"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is declared and defined but appears otherwise unused. Can we just drop it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
NSString *const kGULPersistedDebugModeKey = @"/google/utilities/debug_mode"; | ||
|
||
/// ASL client facility name used by GULLogger. | ||
const char *kGULLoggerASLClientFacilityName = "com.google.utilities.app.logger"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This no longer really has anything to do with "app". "com.gogle.utilities.logger"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
|
||
void GULSetAnalyticsDebugMode(BOOL analyticsDebugMode) { | ||
GULLoggerInitializeASL(NO, NO, NO); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now functionally different than what came before.
Previously if your first call was FIRSetAnalyticsDebugMode we would initialize FIRLogger, including evaluating the command-line arguments. This now disregards the command-line arguments.
At a high level I think we should try really hard to avoid putting any kind of "debug mode" in GULLogger. As implemented it's broken. From my reading of the initialization code, debug mode has the effect of calling
But it also sets But GULLogBasic now has a "force" parameter and does not even concern itself with analytics debug mode. GULIsLoggableLevel allows you to query by whether or not it's an analytics component but GULLogBasic doesn't. How is this supposed to work in practice? I propose that analytics debug mode be pushed up into FIRLogger completely. I'd also propose that we try to eliminate logger debug mode. Why isn't this equivalent to GULSetLoggerLevel to the max? I also suggest moving the NSUserDefaults gunk up into FIRLogger as well. |
@@ -17,7 +17,7 @@ | |||
#import "ApplicationDelegate.h" | |||
|
|||
#import <FirebaseCore/FIRApp.h> | |||
#import <FirebaseCore/FIRLogger.h> | |||
#import <GoogleUtilities/FIRLogger.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this stay as FirebaseCore
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
@@ -15,17 +15,17 @@ | |||
#import <Foundation/Foundation.h> | |||
#import <XCTest/XCTest.h> | |||
|
|||
#import <FirebaseCore/FIRAppEnvironmentUtil.h> | |||
#import <GoogleUtilities/GULAppEnvironmentUtil.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this eventually just be moved to a GoogleUtilities test suite?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The tests will be factored out in a subsequent PR.
@@ -0,0 +1,273 @@ | |||
// Copyright 2017 Google |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize this was copied over, but does this count as new code and an updated copyright?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My interpretation was that since it was copied that it should keep the copyright.
@@ -137,7 +137,7 @@ + (BOOL)isProductionApp { | |||
|
|||
NSError *error = nil; | |||
|
|||
Class envClass = NSClassFromString(@"FIRAppEnvironmentUtil"); | |||
Class envClass = NSClassFromString(@"GULAppEnvironmentUtil"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since Auth relies on GoogleUtilities/GULAppEnvironmentUtil
already, can we remove the string based selectors here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes - done.
Firebase/Core/FIRLogger.m
Outdated
sMessageCodeRegex = | ||
[NSRegularExpression regularExpressionWithPattern:kMessageCodePattern options:0 error:NULL]; | ||
#endif | ||
GULLoggerInitializeASL([arguments containsObject:kFIRDisableDebugModeApplicationArgument], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to moving to os_log
but it's only available on iOS 10+, so we'll have to keep ASL
around until we drop support for iOS 8 and 9 (will be a while).
FirebaseCore.podspec
Outdated
@@ -25,13 +27,12 @@ Firebase Core includes FIRApp and FIROptions which provide central configuration | |||
s.prefix_header_file = false | |||
|
|||
s.source_files = 'Firebase/Core/**/*.[mh]' | |||
s.public_header_files = 'Firebase/Core/Public/*.h', 'Firebase/Core/Private/*.h' | |||
s.private_header_files = 'Firebase/Core/Private/*.h', 'Firebase/Core/third_party/*.h' | |||
s.public_header_files = 'Firebase/Core/Public/*.h' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the reason for having Private/
here as well again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To CocoaPods, "private" means publicly available but not included by default by importing the module - only by explicitly importing the header.
GoogleUtilities.podspec
Outdated
s.summary = 'Firebase Utilities for iOS (plus community support for macOS and tvOS)' | ||
|
||
s.description = <<-DESC | ||
Firebase Utilities including Network, Environment, Logger, and Swizzling. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to have a note here saying not for public use, or "Internal Google Utilities for iOS including Network, Environment, Logger, and Swizzling"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
GoogleUtilities.podspec
Outdated
Pod::Spec.new do |s| | ||
s.name = 'GoogleUtilities' | ||
s.version = '5.0.4' | ||
s.summary = 'Firebase Utilities for iOS (plus community support for macOS and tvOS)' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s/Firebase/Google
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with some small nits!
@@ -4887,6 +4887,10 @@ | |||
INFOPLIST_FILE = "$(SRCROOT)/Core/App/macOS/Core-Info.plist"; | |||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; | |||
MTL_ENABLE_DEBUG_INFO = YES; | |||
OTHER_LDFLAGS = ( | |||
"$(inherited)", | |||
"-ObjC", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this missed before, or why does it need to be added now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new pod structure exposed macOS test failures from categories not being linked in. There's no change to iOS since their tests are linked with -all_load.
Firebase/Core/FIRLogger.m
Outdated
#import "FIRLoggerLevel.h" | ||
#import <FirebaseCore/FIRLoggerLevel.h> | ||
#import <GoogleUtilities/GULAppEnvironmentUtil.h> | ||
#import <GoogleUtilities/GULLogger.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Should have vertical whitespace between the framework imports and file import.
Firebase/Core/FIRLogger.m
Outdated
aslOptions = 0; | ||
} | ||
#endif // TARGET_OS_SIMULATOR | ||
// Register Firebase Version with GULLogger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: punctuation.
kFIRNetworkLogLevelInfo = FIRLoggerLevelInfo, | ||
kFIRNetworkLogLevelDebug = FIRLoggerLevelDebug, | ||
#import <GoogleUtilities/GULLoggerLevel.h> | ||
#import "GULNetworkMessageCode.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Vertical whitespace between framework and file imports.
GoogleUtilities.podspec
Outdated
other Google CocoaPods. They're not intended for direct public usage. | ||
DESC | ||
|
||
s.homepage = 'https://firebase.google.com' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a more general homepage?
GoogleUtilities.podspec
Outdated
# :tag => 'Utilities-' + s.version.to_s | ||
:tag => 'pre-5.3-' + s.version.to_s | ||
} | ||
s.social_media_url = 'https://twitter.com/Firebase' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above - maybe this should be @googledevs
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! LGTM, please make sure @wilhuff is okay with this as well since he previously requested changes.
@ryanwilson Thanks for the review! I'm going to merge now to unblock other tasks. I believe I've addressed most, if not all, of @wilhuff's requests. If there are more, I'll address them in a follow-up PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still have plenty of reservations about this code.
I wish this had gone through API review because this is a new public API that isn't very good.
For example, it's still not clear to me why we need forceLog
. Why can't setting analytics debug mode in FIRLogger translate into a SetLoggerLevel down here?
I don't think this should have been submitted because now we have to release it (unless you revert it, which I suggest you do).
/** | ||
* Logs a message to the Xcode console and the device log. If running from AppStore, will | ||
* not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. | ||
* (required) log level (one of the GULLoggerLevel enum values). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the way to format documentation. It ends up looking like a mess of run-on text in the Xcode help.
See examples for how to do this correctly in http://google.github.io/styleguide/objcguide.html.
In particular, use @param variableName
to introduce each parameter and @return
to describe what's being returned.
* (required) overrideSTDERR Override the aslOptions to ASL_OPT_STDERR. | ||
* (required) forceDebugMode Force the asl level to ASL_LEVEL_DEBUG. | ||
*/ | ||
extern void GULLoggerInitializeASL(BOOL overrideSTDERR, BOOL forceDebugMode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should drop the "ASL" in this name and references to specific ASL options here.
NSString *message, | ||
// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable | ||
// See: http://stackoverflow.com/q/29095469 | ||
#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This #if
makes no sense. There's no useful way to write code that passes NULL
here since code we write must be testable on simulators (and 64-bit is our most common width).
In FIRLogger this was a pre-existing wart that we couldn't change, but we should get rid of this here before we publish it.
Additionally, this just passed directly to [NSString stringWithFormat:message arguments:args_ptr]
and that function has no similar decorations.
Meanwhile, if you're calling this function and don't want to pass any arguments you can instantiate a va_list
, not initialize it, and pass it here.
Finally note that message
is always a format string, even if you pass no arguments. For example, to get a literal %
in the output you still need to escape it (i.e. pass @"%%"
).
Also a va_list
is not necessarily a pointer, so we should call this "args" not "args_ptr".
* not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. | ||
* (required) log level (one of the GULLoggerLevel enum values). | ||
* (required) service name of type GULLoggerService. | ||
* (required) message code starting with "I-" which means iOS, followed by a capitalized |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing a description of forceLog
.
Thanks @wilhuff. I'll make another PR to address these in the next few days. Like FIRLogger, the only part of the GULLogger API that is technically public is GULLoggerLevel.h. See https://github.com/firebase/firebase-ios-sdk/blob/master/GoogleUtilities.podspec#L38. However, the GoogleUtilities pod documents itself as to not supporting non-Google usage. We can incrementally improve everything else without impacting the public API. I don't think we should revert since this PR is an incremental step forward. It unblocks other projects that need to use GoogleUtilities. It provides size improvements for many Firebase configurations. And is a step towards cleaning up FIRLogger. |
Ah, interesting! I saw these listed in the public headers and thought this was a public API. In that case please don't revert, but yes, let's address some of these rough edges as we get time. |
Create a new FirebaseUtilities pod consisting of Network, Environment, and Logger subspecs - extracted from FirebaseCore. A follow-on PR will add a Swizzler subspec.