firebase log level
This commit is contained in:
156
Pods/FirebasePerformance/FirebaseCore/Extension/FIRAppInternal.h
generated
Normal file
156
Pods/FirebasePerformance/FirebaseCore/Extension/FIRAppInternal.h
generated
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2017 Google
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 <FirebaseCore/FIRApp.h>
|
||||
|
||||
@class FIRComponentContainer;
|
||||
@class FIRHeartbeatLogger;
|
||||
@protocol FIRLibrary;
|
||||
|
||||
/**
|
||||
* The internal interface to `FirebaseApp`. This is meant for first-party integrators, who need to
|
||||
* receive `FirebaseApp` notifications, log info about the success or failure of their
|
||||
* configuration, and access other internal functionality of `FirebaseApp`.
|
||||
*/
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSInteger, FIRConfigType) {
|
||||
FIRConfigTypeCore = 1,
|
||||
FIRConfigTypeSDK = 2,
|
||||
};
|
||||
|
||||
extern NSString *const kFIRDefaultAppName;
|
||||
extern NSString *const kFIRAppReadyToConfigureSDKNotification;
|
||||
extern NSString *const kFIRAppDeleteNotification;
|
||||
extern NSString *const kFIRAppIsDefaultAppKey;
|
||||
extern NSString *const kFIRAppNameKey;
|
||||
extern NSString *const kFIRGoogleAppIDKey;
|
||||
extern NSString *const kFirebaseCoreErrorDomain;
|
||||
|
||||
/**
|
||||
* The format string for the `UserDefaults` key used for storing the data collection enabled flag.
|
||||
* This includes formatting to append the `FirebaseApp`'s name.
|
||||
*/
|
||||
extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat;
|
||||
|
||||
/**
|
||||
* The plist key used for storing the data collection enabled flag.
|
||||
*/
|
||||
extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey;
|
||||
|
||||
/** @var FirebaseAuthStateDidChangeInternalNotification
|
||||
@brief The name of the @c NotificationCenter notification which is posted when the auth state
|
||||
changes (e.g. a new token has been produced, a user logs in or out). The object parameter of
|
||||
the notification is a dictionary possibly containing the key:
|
||||
@c FirebaseAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not
|
||||
contain this key it indicates a sign-out event took place.
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotification;
|
||||
|
||||
/** @var FirebaseAuthStateDidChangeInternalNotificationTokenKey
|
||||
@brief A key present in the dictionary object parameter of the
|
||||
@c FirebaseAuthStateDidChangeInternalNotification notification. The value associated with this
|
||||
key will contain the new access token.
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey;
|
||||
|
||||
/** @var FirebaseAuthStateDidChangeInternalNotificationAppKey
|
||||
@brief A key present in the dictionary object parameter of the
|
||||
@c FirebaseAuthStateDidChangeInternalNotification notification. The value associated with this
|
||||
key will contain the FirebaseApp associated with the auth instance.
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey;
|
||||
|
||||
/** @var FirebaseAuthStateDidChangeInternalNotificationUIDKey
|
||||
@brief A key present in the dictionary object parameter of the
|
||||
@c FirebaseAuthStateDidChangeInternalNotification notification. The value associated with this
|
||||
key will contain the new user's UID (or nil if there is no longer a user signed in).
|
||||
*/
|
||||
extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey;
|
||||
|
||||
@interface FIRApp ()
|
||||
|
||||
/**
|
||||
* A flag indicating if this is the default app (has the default app name).
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isDefaultApp;
|
||||
|
||||
/**
|
||||
* The container of interop SDKs for this app.
|
||||
*/
|
||||
@property(nonatomic) FIRComponentContainer *container;
|
||||
|
||||
/**
|
||||
* The heartbeat logger associated with this app.
|
||||
*
|
||||
* Firebase apps have a 1:1 relationship with heartbeat loggers.
|
||||
*/
|
||||
@property(readonly) FIRHeartbeatLogger *heartbeatLogger;
|
||||
|
||||
/**
|
||||
* Checks if the default app is configured without trying to configure it.
|
||||
*/
|
||||
+ (BOOL)isDefaultAppConfigured;
|
||||
|
||||
/**
|
||||
* Registers a given third-party library with the given version number to be reported for
|
||||
* analytics.
|
||||
*
|
||||
* @param name Name of the library.
|
||||
* @param version Version of the library.
|
||||
*/
|
||||
+ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version;
|
||||
|
||||
/**
|
||||
* Registers a given internal library to be reported for analytics.
|
||||
*
|
||||
* @param library Optional parameter for component registration.
|
||||
* @param name Name of the library.
|
||||
*/
|
||||
+ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
|
||||
withName:(nonnull NSString *)name;
|
||||
|
||||
/**
|
||||
* Registers a given internal library with the given version number to be reported for
|
||||
* analytics. This should only be used for non-Firebase libraries that have their own versioning
|
||||
* scheme.
|
||||
*
|
||||
* @param library Optional parameter for component registration.
|
||||
* @param name Name of the library.
|
||||
* @param version Version of the library.
|
||||
*/
|
||||
+ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library
|
||||
withName:(nonnull NSString *)name
|
||||
withVersion:(nonnull NSString *)version;
|
||||
|
||||
/**
|
||||
* A concatenated string representing all the third-party libraries and version numbers.
|
||||
*/
|
||||
+ (NSString *)firebaseUserAgent;
|
||||
|
||||
/**
|
||||
* Can be used by the unit tests in each SDK to reset `FirebaseApp`. This method is thread unsafe.
|
||||
*/
|
||||
+ (void)resetApps;
|
||||
|
||||
/**
|
||||
* Can be used by the unit tests in each SDK to set customized options.
|
||||
*/
|
||||
- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
84
Pods/FirebasePerformance/FirebaseCore/Extension/FIRComponent.h
generated
Normal file
84
Pods/FirebasePerformance/FirebaseCore/Extension/FIRComponent.h
generated
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRApp;
|
||||
@class FIRComponentContainer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Provides a system to clean up cached instances returned from the component system.
|
||||
NS_SWIFT_NAME(ComponentLifecycleMaintainer)
|
||||
@protocol FIRComponentLifecycleMaintainer
|
||||
/// The associated app will be deleted, clean up any resources as they are about to be deallocated.
|
||||
- (void)appWillBeDeleted:(FIRApp *)app;
|
||||
@end
|
||||
|
||||
typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container,
|
||||
BOOL *isCacheable)
|
||||
NS_SWIFT_NAME(ComponentCreationBlock);
|
||||
|
||||
/// Describes the timing of instantiation. Note: new components should default to lazy unless there
|
||||
/// is a strong reason to be eager.
|
||||
typedef NS_ENUM(NSInteger, FIRInstantiationTiming) {
|
||||
FIRInstantiationTimingLazy,
|
||||
FIRInstantiationTimingAlwaysEager,
|
||||
FIRInstantiationTimingEagerInDefaultApp
|
||||
} NS_SWIFT_NAME(InstantiationTiming);
|
||||
|
||||
/// A component that can be used from other Firebase SDKs.
|
||||
NS_SWIFT_NAME(Component)
|
||||
@interface FIRComponent : NSObject
|
||||
|
||||
/// The protocol describing functionality provided from the `Component`.
|
||||
@property(nonatomic, strong, readonly) Protocol *protocol;
|
||||
|
||||
/// The timing of instantiation.
|
||||
@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming;
|
||||
|
||||
/// A block to instantiate an instance of the component with the appropriate dependencies.
|
||||
@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock;
|
||||
|
||||
// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format
|
||||
// for the next two methods.
|
||||
// clang-format off
|
||||
|
||||
/// Creates a component with no dependencies that will be lazily initialized.
|
||||
+ (instancetype)componentWithProtocol:(Protocol *)protocol
|
||||
creationBlock:(FIRComponentCreationBlock)creationBlock
|
||||
NS_SWIFT_NAME(init(_:creationBlock:));
|
||||
|
||||
/// Creates a component to be registered with the component container.
|
||||
///
|
||||
/// @param protocol - The protocol describing functionality provided by the component.
|
||||
/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's
|
||||
/// a good reason to be instantiated earlier.
|
||||
/// @param creationBlock - A block to instantiate the component with a container, and if
|
||||
/// @return A component that can be registered with the component container.
|
||||
+ (instancetype)componentWithProtocol:(Protocol *)protocol
|
||||
instantiationTiming:(FIRInstantiationTiming)instantiationTiming
|
||||
creationBlock:(FIRComponentCreationBlock)creationBlock
|
||||
NS_SWIFT_NAME(init(_:instantiationTiming:creationBlock:));
|
||||
|
||||
// clang-format on
|
||||
|
||||
/// Unavailable.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
45
Pods/FirebasePerformance/FirebaseCore/Extension/FIRComponentContainer.h
generated
Normal file
45
Pods/FirebasePerformance/FirebaseCore/Extension/FIRComponentContainer.h
generated
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A type-safe macro to retrieve a component from a container. This should be used to retrieve
|
||||
/// components instead of using the container directly.
|
||||
#define FIR_COMPONENT(type, container) \
|
||||
[FIRComponentType<id<type>> instanceForProtocol:@protocol(type) inContainer:container]
|
||||
|
||||
@class FIRApp;
|
||||
|
||||
/// A container that holds different components that are registered via the
|
||||
/// `registerAsComponentRegistrant` call. These classes should conform to `ComponentRegistrant`
|
||||
/// in order to properly register components for Core.
|
||||
NS_SWIFT_NAME(FirebaseComponentContainer)
|
||||
@interface FIRComponentContainer : NSObject
|
||||
|
||||
/// A weak reference to the app that an instance of the container belongs to.
|
||||
@property(nonatomic, weak, readonly) FIRApp *app;
|
||||
|
||||
// TODO: See if we can get improved type safety here.
|
||||
/// A Swift only API for fetching an instance since the top macro isn't available.
|
||||
- (nullable id)__instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:));
|
||||
|
||||
/// Unavailable. Use the `container` property on `FirebaseApp`.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
35
Pods/FirebasePerformance/FirebaseCore/Extension/FIRComponentType.h
generated
Normal file
35
Pods/FirebasePerformance/FirebaseCore/Extension/FIRComponentType.h
generated
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRComponentContainer;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Do not use directly. A placeholder type in order to provide a macro that will warn users of
|
||||
/// mis-matched protocols.
|
||||
NS_SWIFT_NAME(ComponentType)
|
||||
@interface FIRComponentType<__covariant T> : NSObject
|
||||
|
||||
/// Do not use directly. A factory method to retrieve an instance that provides a specific
|
||||
/// functionality.
|
||||
+ (nullable T)instanceForProtocol:(Protocol *)protocol
|
||||
inContainer:(FIRComponentContainer *)container;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
90
Pods/FirebasePerformance/FirebaseCore/Extension/FIRHeartbeatLogger.h
generated
Normal file
90
Pods/FirebasePerformance/FirebaseCore/Extension/FIRHeartbeatLogger.h
generated
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2021 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
@class FIRHeartbeatsPayload;
|
||||
#endif // FIREBASE_BUILD_CMAKE
|
||||
|
||||
/// Enum representing different daily heartbeat codes.
|
||||
/// This enum is only used by clients using platform logging V1. This is because
|
||||
/// the V1 payload only supports a single daily heartbeat.
|
||||
typedef NS_ENUM(NSInteger, FIRDailyHeartbeatCode) {
|
||||
/// Represents the absence of a daily heartbeat.
|
||||
FIRDailyHeartbeatCodeNone = 0,
|
||||
/// Represents the presence of a daily heartbeat.
|
||||
FIRDailyHeartbeatCodeSome = 2,
|
||||
};
|
||||
|
||||
@protocol FIRHeartbeatLoggerProtocol <NSObject>
|
||||
|
||||
/// Asynchronously logs a heartbeat.
|
||||
- (void)log;
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
/// Return the headerValue for the HeartbeatLogger.
|
||||
- (NSString *_Nullable)headerValue;
|
||||
#endif // FIREBASE_BUILD_CMAKE
|
||||
|
||||
/// Gets the heartbeat code for today.
|
||||
- (FIRDailyHeartbeatCode)heartbeatCodeForToday;
|
||||
|
||||
@end
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
/// Returns a nullable string header value from a given heartbeats payload.
|
||||
///
|
||||
/// This API returns `nil` when the given heartbeats payload is considered empty.
|
||||
///
|
||||
/// @param heartbeatsPayload The heartbeats payload.
|
||||
NSString *_Nullable FIRHeaderValueFromHeartbeatsPayload(FIRHeartbeatsPayload *heartbeatsPayload);
|
||||
#endif // FIREBASE_BUILD_CMAKE
|
||||
|
||||
/// A thread safe, synchronized object that logs and flushes platform logging info.
|
||||
@interface FIRHeartbeatLogger : NSObject <FIRHeartbeatLoggerProtocol>
|
||||
|
||||
/// Designated initializer.
|
||||
///
|
||||
/// @param appID The app ID that this heartbeat logger corresponds to.
|
||||
- (instancetype)initWithAppID:(NSString *)appID;
|
||||
|
||||
/// Asynchronously logs a new heartbeat corresponding to the Firebase User Agent, if needed.
|
||||
///
|
||||
/// @note This API is thread-safe.
|
||||
- (void)log;
|
||||
|
||||
#ifndef FIREBASE_BUILD_CMAKE
|
||||
/// Flushes heartbeats from storage into a structured payload of heartbeats.
|
||||
///
|
||||
/// This API is for clients using platform logging V2.
|
||||
///
|
||||
/// @note This API is thread-safe.
|
||||
/// @return A payload of heartbeats.
|
||||
- (FIRHeartbeatsPayload *)flushHeartbeatsIntoPayload;
|
||||
#endif // FIREBASE_BUILD_CMAKE
|
||||
|
||||
/// Gets today's corresponding heartbeat code.
|
||||
///
|
||||
/// This API is for clients using platform logging V1.
|
||||
///
|
||||
/// @note This API is thread-safe.
|
||||
/// @return Heartbeat code indicating whether or not there is an unsent global heartbeat.
|
||||
- (FIRDailyHeartbeatCode)heartbeatCodeForToday;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
39
Pods/FirebasePerformance/FirebaseCore/Extension/FIRLibrary.h
generated
Normal file
39
Pods/FirebasePerformance/FirebaseCore/Extension/FIRLibrary.h
generated
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018 Google
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 FIRLibrary_h
|
||||
#define FIRLibrary_h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FIRApp;
|
||||
@class FIRComponent;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Provide an interface to register a library for userAgent logging and availability to others.
|
||||
NS_SWIFT_NAME(Library)
|
||||
@protocol FIRLibrary
|
||||
|
||||
/// Returns one or more Components that will be registered in
|
||||
/// FirebaseApp and participate in dependency resolution and injection.
|
||||
+ (NSArray<FIRComponent *> *)componentsToRegister;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif /* FIRLibrary_h */
|
||||
148
Pods/FirebasePerformance/FirebaseCore/Extension/FIRLogger.h
generated
Normal file
148
Pods/FirebasePerformance/FirebaseCore/Extension/FIRLogger.h
generated
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2017 Google
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import <FirebaseCore/FIRLoggerLevel.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* The Firebase services used in Firebase logger.
|
||||
*/
|
||||
typedef NSString *const FIRLoggerService;
|
||||
|
||||
extern NSString *const kFIRLoggerAnalytics;
|
||||
extern NSString *const kFIRLoggerCrash;
|
||||
extern NSString *const kFIRLoggerCore;
|
||||
extern NSString *const kFIRLoggerRemoteConfig;
|
||||
|
||||
/**
|
||||
* The key used to store the logger's error count.
|
||||
*/
|
||||
extern NSString *const kFIRLoggerErrorCountKey;
|
||||
|
||||
/**
|
||||
* The key used to store the logger's warning count.
|
||||
*/
|
||||
extern NSString *const kFIRLoggerWarningCountKey;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
/**
|
||||
* Enables or disables Analytics debug mode.
|
||||
* If set to true, the logging level for Analytics will be set to FirebaseLoggerLevelDebug.
|
||||
* Enabling the debug mode has no effect if the app is running from App Store.
|
||||
* (required) analytics debug mode flag.
|
||||
*/
|
||||
void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode);
|
||||
|
||||
/**
|
||||
* Gets the current FIRLoggerLevel.
|
||||
*/
|
||||
FIRLoggerLevel FIRGetLoggerLevel(void);
|
||||
|
||||
/**
|
||||
* Changes the default logging level of FirebaseLoggerLevelNotice to a user-specified level.
|
||||
* The default level cannot be set above FirebaseLoggerLevelNotice if the app is running from App
|
||||
* Store. (required) log level (one of the FirebaseLoggerLevel enum values).
|
||||
*/
|
||||
void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
|
||||
|
||||
/**
|
||||
* Checks if the specified logger level is loggable given the current settings.
|
||||
* (required) log level (one of the FirebaseLoggerLevel enum values).
|
||||
* (required) whether or not this function is called from the Analytics component.
|
||||
*/
|
||||
BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent);
|
||||
|
||||
/**
|
||||
* 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 FirebaseLoggerLevelNotice to avoid log spamming.
|
||||
* (required) log level (one of the FirebaseLoggerLevel enum values).
|
||||
* (required) service name of type FirebaseLoggerService.
|
||||
* (required) message code starting with "I-" which means iOS, followed by a capitalized
|
||||
* three-character service identifier and a six digit integer message ID that is unique
|
||||
* within the service.
|
||||
* An example of the message code is @"I-COR000001".
|
||||
* (required) message string which can be a format string.
|
||||
* (optional) variable arguments list obtained from calling va_start, used when message is a format
|
||||
* string.
|
||||
*/
|
||||
extern void FIRLogBasic(FIRLoggerLevel level,
|
||||
NSString *category,
|
||||
NSString *messageCode,
|
||||
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
|
||||
va_list args_ptr
|
||||
#else
|
||||
va_list _Nullable args_ptr
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
* The following functions accept the following parameters in order:
|
||||
* (required) service name of type FirebaseLoggerService.
|
||||
* (required) message code starting from "I-" which means iOS, followed by a capitalized
|
||||
* three-character service identifier and a six digit integer message ID that is unique
|
||||
* within the service.
|
||||
* An example of the message code is @"I-COR000001".
|
||||
* See go/firebase-log-proposal for details.
|
||||
* (required) message string which can be a format string.
|
||||
* (optional) the list of arguments to substitute into the format string.
|
||||
* Example usage:
|
||||
* FirebaseLogError(kFirebaseLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name);
|
||||
*/
|
||||
extern void FIRLogError(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogWarning(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogNotice(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogInfo(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
extern void FIRLogDebug(NSString *category, NSString *messageCode, NSString *message, ...)
|
||||
NS_FORMAT_FUNCTION(3, 4);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
NS_SWIFT_NAME(FirebaseLogger)
|
||||
@interface FIRLoggerWrapper : NSObject
|
||||
|
||||
/// Logs a given message at a given log level.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - level: The log level to use (defined by `FirebaseLoggerLevel` enum values).
|
||||
/// - service: The service name of type `FirebaseLoggerService`.
|
||||
/// - code: The message code. Starting with "I-" which means iOS, followed by a capitalized
|
||||
/// three-character service identifier and a six digit integer message ID that is unique within
|
||||
/// the service. An example of the message code is @"I-COR000001".
|
||||
/// - message: Formatted string to be used as the log's message.
|
||||
+ (void)logWithLevel:(FIRLoggerLevel)level
|
||||
service:(NSString *)category
|
||||
code:(NSString *)code
|
||||
message:(NSString *)message
|
||||
__attribute__((__swift_name__("log(level:service:code:message:)")));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
106
Pods/FirebasePerformance/FirebaseCore/Extension/FIROptionsInternal.h
generated
Normal file
106
Pods/FirebasePerformance/FirebaseCore/Extension/FIROptionsInternal.h
generated
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2017 Google
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 <FirebaseCore/FIROptions.h>
|
||||
|
||||
/**
|
||||
* Keys for the strings in the plist file.
|
||||
*/
|
||||
extern NSString *const kFIRAPIKey;
|
||||
extern NSString *const kFIRTrackingID;
|
||||
extern NSString *const kFIRGoogleAppID;
|
||||
extern NSString *const kFIRClientID;
|
||||
extern NSString *const kFIRGCMSenderID;
|
||||
extern NSString *const kFIRAndroidClientID;
|
||||
extern NSString *const kFIRDatabaseURL;
|
||||
extern NSString *const kFIRStorageBucket;
|
||||
extern NSString *const kFIRBundleID;
|
||||
extern NSString *const kFIRProjectID;
|
||||
|
||||
/**
|
||||
* Keys for the plist file name
|
||||
*/
|
||||
extern NSString *const kServiceInfoFileName;
|
||||
|
||||
extern NSString *const kServiceInfoFileType;
|
||||
|
||||
/**
|
||||
* This header file exposes the initialization of FirebaseOptions to internal use.
|
||||
*/
|
||||
@interface FIROptions ()
|
||||
|
||||
/**
|
||||
* `resetDefaultOptions` and `initInternalWithOptionsDictionary` are exposed only for unit tests.
|
||||
*/
|
||||
+ (void)resetDefaultOptions;
|
||||
|
||||
/**
|
||||
* Initializes the options with dictionary. The above strings are the keys of the dictionary.
|
||||
* This is the designated initializer.
|
||||
*/
|
||||
- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* `defaultOptions` and `defaultOptionsDictionary` are exposed in order to be used in FirebaseApp
|
||||
* and other first party services.
|
||||
*/
|
||||
+ (FIROptions *)defaultOptions;
|
||||
|
||||
+ (NSDictionary *)defaultOptionsDictionary;
|
||||
|
||||
/**
|
||||
* Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at
|
||||
* runtime.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet;
|
||||
|
||||
/**
|
||||
* Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless
|
||||
* explicitly disabled in GoogleService-Info.plist.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled;
|
||||
|
||||
/**
|
||||
* Whether or not Analytics Collection was completely disabled. If true, then
|
||||
* isAnalyticsCollectionEnabled will be false.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated;
|
||||
|
||||
/**
|
||||
* The version ID of the client library, e.g. @"1100000".
|
||||
*/
|
||||
@property(nonatomic, readonly, copy) NSString *libraryVersionID;
|
||||
|
||||
/**
|
||||
* The flag indicating whether this object was constructed with the values in the default plist
|
||||
* file.
|
||||
*/
|
||||
@property(nonatomic) BOOL usingOptionsFromDefaultPlist;
|
||||
|
||||
/**
|
||||
* Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in
|
||||
* GoogleService-Info.plist.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isMeasurementEnabled;
|
||||
|
||||
/**
|
||||
* Whether or not editing is locked. This should occur after `FirebaseOptions` has been set on a
|
||||
* `FirebaseApp`.
|
||||
*/
|
||||
@property(nonatomic, getter=isEditingLocked) BOOL editingLocked;
|
||||
|
||||
@end
|
||||
24
Pods/FirebasePerformance/FirebaseCore/Extension/FirebaseCoreInternal.h
generated
Normal file
24
Pods/FirebasePerformance/FirebaseCore/Extension/FirebaseCoreInternal.h
generated
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 FirebaseCore;
|
||||
|
||||
#import "FIRAppInternal.h"
|
||||
#import "FIRComponent.h"
|
||||
#import "FIRComponentContainer.h"
|
||||
#import "FIRComponentType.h"
|
||||
#import "FIRHeartbeatLogger.h"
|
||||
#import "FIRLibrary.h"
|
||||
#import "FIRLogger.h"
|
||||
#import "FIROptionsInternal.h"
|
||||
@ -0,0 +1,19 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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.
|
||||
|
||||
// An umbrella header, for any other libraries in this repo to access Firebase
|
||||
// Installations Public headers. Any package manager complexity should be
|
||||
// handled here.
|
||||
|
||||
#import <FirebaseInstallations/FirebaseInstallations.h>
|
||||
64
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h
generated
Normal file
64
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h
generated
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.h"
|
||||
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRTrace.h"
|
||||
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppStartTraceName;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppStartStageNameTimeToUI;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppStartStageNameTimeToFirstDraw;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppStartStageNameTimeToUserInteraction;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppTraceNameForegroundSession;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppTraceNameBackgroundSession;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppCounterNameTraceEventsRateLimited;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppCounterNameNetworkTraceEventsRateLimited;
|
||||
FOUNDATION_EXTERN NSString *__nonnull const kFPRAppCounterNameTraceNotStopped;
|
||||
|
||||
/** Different states of the current application. */
|
||||
typedef NS_ENUM(NSInteger, FPRApplicationState) {
|
||||
FPRApplicationStateUnknown,
|
||||
|
||||
/** Application in foreground. */
|
||||
FPRApplicationStateForeground,
|
||||
|
||||
/** Application in background. */
|
||||
FPRApplicationStateBackground,
|
||||
};
|
||||
|
||||
/** This class is used to track the app activity and create internal traces to capture the
|
||||
* performance metrics.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRAppActivityTracker : NSObject
|
||||
|
||||
/** The trace that tracks the currently active session of the app. *Do not stop this trace*. This is
|
||||
* an active trace that needs to be running. Stopping this trace might impact the overall
|
||||
* performance metrics captured for the active session. All other operations can be performed.
|
||||
*/
|
||||
@property(nonatomic, nullable, readonly) FIRTrace *activeTrace;
|
||||
|
||||
/** Current running state of the application. */
|
||||
@property(nonatomic, readonly) FPRApplicationState applicationState;
|
||||
|
||||
/** Current network connection type of the application. */
|
||||
@property(nonatomic, readonly) firebase_perf_v1_NetworkConnectionInfo_NetworkType networkType;
|
||||
|
||||
/** Accesses the singleton instance.
|
||||
* @return Reference to the shared object if successful; <code>nil</code> if not.
|
||||
*/
|
||||
+ (nullable instancetype)sharedInstance;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
334
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.m
generated
Normal file
334
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.m
generated
Normal file
@ -0,0 +1,334 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Network/Network.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector+Private.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/FPRGaugeManager.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector+Private.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
|
||||
|
||||
static NSDate *appStartTime = nil;
|
||||
static NSDate *doubleDispatchTime = nil;
|
||||
static NSDate *applicationDidFinishLaunchTime = nil;
|
||||
static NSTimeInterval gAppStartMaxValidDuration = 60 * 60; // 60 minutes.
|
||||
static FPRCPUGaugeData *gAppStartCPUGaugeData = nil;
|
||||
static FPRMemoryGaugeData *gAppStartMemoryGaugeData = nil;
|
||||
static BOOL isActivePrewarm = NO;
|
||||
|
||||
NSString *const kFPRAppStartTraceName = @"_as";
|
||||
NSString *const kFPRAppStartStageNameTimeToUI = @"_astui";
|
||||
NSString *const kFPRAppStartStageNameTimeToFirstDraw = @"_astfd";
|
||||
NSString *const kFPRAppStartStageNameTimeToUserInteraction = @"_asti";
|
||||
NSString *const kFPRAppTraceNameForegroundSession = @"_fs";
|
||||
NSString *const kFPRAppTraceNameBackgroundSession = @"_bs";
|
||||
NSString *const kFPRAppCounterNameTraceEventsRateLimited = @"_fstec";
|
||||
NSString *const kFPRAppCounterNameNetworkTraceEventsRateLimited = @"_fsntc";
|
||||
NSString *const kFPRAppCounterNameTraceNotStopped = @"_tsns";
|
||||
NSString *const kFPRAppCounterNameActivePrewarm = @"_fsapc";
|
||||
|
||||
@interface FPRAppActivityTracker ()
|
||||
|
||||
/** The foreground session trace. Will be set only when the app is in the foreground. */
|
||||
@property(nonatomic, readwrite) FIRTrace *foregroundSessionTrace;
|
||||
|
||||
/** The background session trace. Will be set only when the app is in the background. */
|
||||
@property(nonatomic, readwrite) FIRTrace *backgroundSessionTrace;
|
||||
|
||||
/** Current running state of the application. */
|
||||
@property(nonatomic, readwrite) FPRApplicationState applicationState;
|
||||
|
||||
/** Current network connection type of the application. */
|
||||
@property(nonatomic, readwrite) firebase_perf_v1_NetworkConnectionInfo_NetworkType networkType;
|
||||
|
||||
/** Network monitor object to track network movements. */
|
||||
@property(nonatomic, readwrite) nw_path_monitor_t monitor;
|
||||
|
||||
/** Queue used to track the network monitoring changes. */
|
||||
@property(nonatomic, readwrite) dispatch_queue_t monitorQueue;
|
||||
|
||||
/** Trace to measure the app start performance. */
|
||||
@property(nonatomic) FIRTrace *appStartTrace;
|
||||
|
||||
/** Tracks if the gauge metrics are dispatched. */
|
||||
@property(nonatomic) BOOL appStartGaugeMetricDispatched;
|
||||
|
||||
/** Firebase Performance Configuration object */
|
||||
@property(nonatomic) FPRConfigurations *configurations;
|
||||
|
||||
/** Starts tracking app active sessions. */
|
||||
- (void)startAppActivityTracking;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRAppActivityTracker
|
||||
|
||||
+ (void)load {
|
||||
// This is an approximation of the app start time.
|
||||
appStartTime = [NSDate date];
|
||||
|
||||
// When an app is prewarmed, Apple sets env variable ActivePrewarm to 1, then the env variable is
|
||||
// deleted after didFinishLaunching
|
||||
isActivePrewarm = [NSProcessInfo.processInfo.environment[@"ActivePrewarm"] isEqualToString:@"1"];
|
||||
|
||||
gAppStartCPUGaugeData = fprCollectCPUMetric();
|
||||
gAppStartMemoryGaugeData = fprCollectMemoryMetric();
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(windowDidBecomeVisible:)
|
||||
name:UIWindowDidBecomeVisibleNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationDidFinishLaunching:)
|
||||
name:UIApplicationDidFinishLaunchingNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
+ (void)windowDidBecomeVisible:(NSNotification *)notification {
|
||||
FPRAppActivityTracker *activityTracker = [self sharedInstance];
|
||||
[activityTracker startAppActivityTracking];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIWindowDidBecomeVisibleNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
+ (void)applicationDidFinishLaunching:(NSNotification *)notification {
|
||||
applicationDidFinishLaunchTime = [NSDate date];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationDidFinishLaunchingNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static FPRAppActivityTracker *instance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[self alloc] initAppActivityTracker];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom initializer to create an app activity tracker.
|
||||
*/
|
||||
- (instancetype)initAppActivityTracker {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_applicationState = FPRApplicationStateUnknown;
|
||||
_appStartGaugeMetricDispatched = NO;
|
||||
_configurations = [FPRConfigurations sharedInstance];
|
||||
[self startTrackingNetwork];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)startAppActivityTracking {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appDidBecomeActiveNotification:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appWillResignActiveNotification:)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
}
|
||||
|
||||
- (FIRTrace *)activeTrace {
|
||||
if (self.foregroundSessionTrace) {
|
||||
return self.foregroundSessionTrace;
|
||||
}
|
||||
return self.backgroundSessionTrace;
|
||||
}
|
||||
|
||||
- (void)startTrackingNetwork {
|
||||
self.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_NONE;
|
||||
|
||||
dispatch_queue_attr_t attrs = dispatch_queue_attr_make_with_qos_class(
|
||||
DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, DISPATCH_QUEUE_PRIORITY_DEFAULT);
|
||||
self.monitorQueue = dispatch_queue_create("com.google.firebase.perf.network.monitor", attrs);
|
||||
|
||||
self.monitor = nw_path_monitor_create();
|
||||
nw_path_monitor_set_queue(self.monitor, self.monitorQueue);
|
||||
__weak FPRAppActivityTracker *weakSelf = self;
|
||||
nw_path_monitor_set_update_handler(self.monitor, ^(nw_path_t _Nonnull path) {
|
||||
BOOL isWiFi = nw_path_uses_interface_type(path, nw_interface_type_wifi);
|
||||
BOOL isCellular = nw_path_uses_interface_type(path, nw_interface_type_cellular);
|
||||
BOOL isEthernet = nw_path_uses_interface_type(path, nw_interface_type_wired);
|
||||
|
||||
if (isWiFi) {
|
||||
weakSelf.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_WIFI;
|
||||
} else if (isCellular) {
|
||||
weakSelf.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_MOBILE;
|
||||
} else if (isEthernet) {
|
||||
weakSelf.networkType = firebase_perf_v1_NetworkConnectionInfo_NetworkType_ETHERNET;
|
||||
}
|
||||
});
|
||||
|
||||
nw_path_monitor_start(self.monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the prewarming feature is available on the current device.
|
||||
*
|
||||
* @return true if the OS could prewarm apps on the current device
|
||||
*/
|
||||
- (BOOL)isPrewarmAvailable {
|
||||
return YES;
|
||||
}
|
||||
|
||||
/**
|
||||
RC flag for dropping all app start events
|
||||
*/
|
||||
- (BOOL)isAppStartEnabled {
|
||||
return [self.configurations prewarmDetectionMode] != PrewarmDetectionModeKeepNone;
|
||||
}
|
||||
|
||||
/**
|
||||
RC flag for enabling prewarm-detection using ActivePrewarm environment variable
|
||||
*/
|
||||
- (BOOL)isActivePrewarmEnabled {
|
||||
PrewarmDetectionMode mode = [self.configurations prewarmDetectionMode];
|
||||
return (mode == PrewarmDetectionModeActivePrewarm);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the current app start is a prewarmed app start
|
||||
*/
|
||||
- (BOOL)isApplicationPreWarmed {
|
||||
if (![self isPrewarmAvailable]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL isPrewarmed = NO;
|
||||
|
||||
if (isActivePrewarm == YES) {
|
||||
isPrewarmed = isPrewarmed || [self isActivePrewarmEnabled];
|
||||
[self.activeTrace incrementMetric:kFPRAppCounterNameActivePrewarm byInt:1];
|
||||
} else {
|
||||
[self.activeTrace incrementMetric:kFPRAppCounterNameActivePrewarm byInt:0];
|
||||
}
|
||||
|
||||
return isPrewarmed;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets called whenever the app becomes active. A new trace will be created to track the active
|
||||
* foreground session. Any background session trace that was running in the past will be stopped.
|
||||
*
|
||||
* @param notification Notification received during app launch.
|
||||
*/
|
||||
- (void)appDidBecomeActiveNotification:(NSNotification *)notification {
|
||||
self.applicationState = FPRApplicationStateForeground;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
self.appStartTrace = [[FIRTrace alloc] initInternalTraceWithName:kFPRAppStartTraceName];
|
||||
[self.appStartTrace startWithStartTime:appStartTime];
|
||||
[self.appStartTrace startStageNamed:kFPRAppStartStageNameTimeToUI startTime:appStartTime];
|
||||
|
||||
// Start measuring time to first draw on the App start trace.
|
||||
[self.appStartTrace startStageNamed:kFPRAppStartStageNameTimeToFirstDraw];
|
||||
});
|
||||
|
||||
// If ever the app start trace had it life in background stage, do not send the trace.
|
||||
if (self.appStartTrace.backgroundTraceState != FPRTraceStateForegroundOnly) {
|
||||
self.appStartTrace = nil;
|
||||
}
|
||||
|
||||
// Stop the active background session trace.
|
||||
[self.backgroundSessionTrace stop];
|
||||
self.backgroundSessionTrace = nil;
|
||||
|
||||
// Start foreground session trace.
|
||||
FIRTrace *appTrace =
|
||||
[[FIRTrace alloc] initInternalTraceWithName:kFPRAppTraceNameForegroundSession];
|
||||
[appTrace start];
|
||||
self.foregroundSessionTrace = appTrace;
|
||||
|
||||
// Start measuring time to make the app interactive on the App start trace.
|
||||
static BOOL TTIStageStarted = NO;
|
||||
if (!TTIStageStarted) {
|
||||
[self.appStartTrace startStageNamed:kFPRAppStartStageNameTimeToUserInteraction];
|
||||
TTIStageStarted = YES;
|
||||
|
||||
// Assumption here is that - the app becomes interactive in the next runloop cycle.
|
||||
// It is possible that the app does more things later, but for now we are not measuring that.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSTimeInterval startTimeSinceEpoch = [self.appStartTrace startTimeSinceEpoch];
|
||||
NSTimeInterval currentTimeSinceEpoch = [[NSDate date] timeIntervalSince1970];
|
||||
|
||||
// The below check is to account for 2 scenarios.
|
||||
// 1. The app gets started in the background and might come to foreground a lot later.
|
||||
// 2. The app is launched, but immediately backgrounded for some reason and the actual launch
|
||||
// happens a lot later.
|
||||
// Dropping the app start trace in such situations where the launch time is taking more than
|
||||
// 60 minutes. This is an approximation, but a more agreeable timelimit for app start.
|
||||
if ((currentTimeSinceEpoch - startTimeSinceEpoch < gAppStartMaxValidDuration) &&
|
||||
[self isAppStartEnabled] && ![self isApplicationPreWarmed]) {
|
||||
[self.appStartTrace stop];
|
||||
} else {
|
||||
[self.appStartTrace cancel];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets called whenever the app resigns its active status. The currently active foreground
|
||||
* session trace will be stopped and a background session trace will be started.
|
||||
*
|
||||
* @param notification Notification received during app resigning active status.
|
||||
*/
|
||||
- (void)appWillResignActiveNotification:(NSNotification *)notification {
|
||||
// Dispatch the collected gauge metrics.
|
||||
if (!self.appStartGaugeMetricDispatched) {
|
||||
[[FPRGaugeManager sharedInstance] dispatchMetric:gAppStartCPUGaugeData];
|
||||
[[FPRGaugeManager sharedInstance] dispatchMetric:gAppStartMemoryGaugeData];
|
||||
self.appStartGaugeMetricDispatched = YES;
|
||||
}
|
||||
|
||||
self.applicationState = FPRApplicationStateBackground;
|
||||
|
||||
// Stop foreground session trace.
|
||||
[self.foregroundSessionTrace stop];
|
||||
self.foregroundSessionTrace = nil;
|
||||
|
||||
// Start background session trace.
|
||||
self.backgroundSessionTrace =
|
||||
[[FIRTrace alloc] initInternalTraceWithName:kFPRAppTraceNameBackgroundSession];
|
||||
[self.backgroundSessionTrace start];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
nw_path_monitor_cancel(self.monitor);
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
}
|
||||
|
||||
@end
|
||||
117
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker+Private.h
generated
Normal file
117
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker+Private.h
generated
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <stdatomic.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
|
||||
|
||||
@class UIViewController;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Prefix string for screen traces. */
|
||||
FOUNDATION_EXTERN NSString *const kFPRPrefixForScreenTraceName;
|
||||
|
||||
/** Counter name for frozen frames. */
|
||||
FOUNDATION_EXTERN NSString *const kFPRFrozenFrameCounterName;
|
||||
|
||||
/** Counter name for slow frames. */
|
||||
FOUNDATION_EXTERN NSString *const kFPRSlowFrameCounterName;
|
||||
|
||||
/** Counter name for total frames. */
|
||||
FOUNDATION_EXTERN NSString *const kFPRTotalFramesCounterName;
|
||||
|
||||
/** Slow frame threshold (for time difference between current and previous frame render time)
|
||||
* in sec.
|
||||
*/
|
||||
FOUNDATION_EXTERN CFTimeInterval const kFPRSlowFrameThreshold;
|
||||
|
||||
/** Frozen frame threshold (for time difference between current and previous frame render time)
|
||||
* in sec.
|
||||
*/
|
||||
FOUNDATION_EXTERN CFTimeInterval const kFPRFrozenFrameThreshold;
|
||||
|
||||
@interface FPRScreenTraceTracker ()
|
||||
|
||||
/** A map table of that has the viewControllers as the keys and their associated trace as the value.
|
||||
* The key is weakly retained and the value is strongly retained.
|
||||
*/
|
||||
@property(nonatomic) NSMapTable<UIViewController *, FIRTrace *> *activeScreenTraces;
|
||||
|
||||
/** A list of all UIViewController instances that were visible before app was backgrounded. The
|
||||
* viewControllers are reatined weakly.
|
||||
*/
|
||||
@property(nonatomic, nullable) NSPointerArray *previouslyVisibleViewControllers;
|
||||
|
||||
/** Serial queue on which all operations that need to be thread safe in this class take place. */
|
||||
@property(nonatomic) dispatch_queue_t screenTraceTrackerSerialQueue;
|
||||
|
||||
/** The display link that provides us with the frame rate data. */
|
||||
@property(nonatomic) CADisplayLink *displayLink;
|
||||
|
||||
/** Dispatch group which allows us to make this class testable. Instead of waiting an arbitrary
|
||||
* amount of time for an asynchronous task to finish before asserting its behavior, we can wait
|
||||
* on this dispatch group to finish executing before testing the behavior of any asynchronous
|
||||
* task. Consequently, all asynchronous tasks in this class should use this dispatch group.
|
||||
*/
|
||||
@property(nonatomic) dispatch_group_t screenTraceTrackerDispatchGroup;
|
||||
|
||||
/** The frozen frames counter. */
|
||||
@property(atomic) int_fast64_t frozenFramesCount;
|
||||
|
||||
/** The total frames counter. */
|
||||
@property(atomic) int_fast64_t totalFramesCount;
|
||||
|
||||
/** The slow frames counter. */
|
||||
@property(atomic) int_fast64_t slowFramesCount;
|
||||
|
||||
/** Handles the appDidBecomeActive notification. Restores the screen traces that were active before
|
||||
* the app was backgrounded.
|
||||
*
|
||||
* @param notification The NSNotification object.
|
||||
*/
|
||||
- (void)appDidBecomeActiveNotification:(NSNotification *)notification;
|
||||
|
||||
/** Handles the appWillResignActive notification. Saves the names of the screen traces that are
|
||||
* currently active and stops all of them.
|
||||
*
|
||||
* @param notification The NSNotification object.
|
||||
*/
|
||||
- (void)appWillResignActiveNotification:(NSNotification *)notification;
|
||||
|
||||
/** The method that is invoked by the CADisplayLink when a new frame is rendered. */
|
||||
- (void)displayLinkStep;
|
||||
|
||||
/** Tells the screen trace tracker that the given viewController appeared. This should be called
|
||||
* from the main thread.
|
||||
*
|
||||
* @param viewController The UIViewController instance that appeared.
|
||||
*/
|
||||
- (void)viewControllerDidAppear:(UIViewController *)viewController;
|
||||
|
||||
/** Tells the screen trace tracker that the given viewController disappeared. This should be called
|
||||
* from the main thread.
|
||||
*
|
||||
* @param viewController The UIViewController instance that disappeared.
|
||||
*/
|
||||
- (void)viewControllerDidDisappear:(id)viewController;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
34
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.h
generated
Normal file
34
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.h
generated
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class manages all the screen traces. If initialized, it records the total frames, frozen
|
||||
* frames and slow frames, and if it has been registered as a delegate of FIRAScreenViewReporter,
|
||||
* it also automatically creates screen traces for each UIViewController.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRScreenTraceTracker : NSObject
|
||||
|
||||
/** Singleton instance of FPRScreenTraceTracker.
|
||||
*
|
||||
* @return The shared instance of FPRScreenTraceTracker.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
403
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.m
generated
Normal file
403
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.m
generated
Normal file
@ -0,0 +1,403 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.h"
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker+Private.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
|
||||
NSString *const kFPRPrefixForScreenTraceName = @"_st_";
|
||||
NSString *const kFPRFrozenFrameCounterName = @"_fr_fzn";
|
||||
NSString *const kFPRSlowFrameCounterName = @"_fr_slo";
|
||||
NSString *const kFPRTotalFramesCounterName = @"_fr_tot";
|
||||
|
||||
// Note: This was previously 60 FPS, but that resulted in 90% + of all frames collected to be
|
||||
// flagged as slow frames, and so the threshold for iOS is being changed to 59 FPS.
|
||||
// TODO(b/73498642): Make these configurable.
|
||||
CFTimeInterval const kFPRSlowFrameThreshold = 1.0 / 59.0; // Anything less than 59 FPS is slow.
|
||||
CFTimeInterval const kFPRFrozenFrameThreshold = 700.0 / 1000.0;
|
||||
|
||||
/** Constant that indicates an invalid time. */
|
||||
CFAbsoluteTime const kFPRInvalidTime = -1.0;
|
||||
|
||||
/** Returns the class name without the prefixed module name present in Swift classes
|
||||
* (e.g. MyModule.MyViewController -> MyViewController).
|
||||
*/
|
||||
static NSString *FPRUnprefixedClassName(Class theClass) {
|
||||
NSString *className = NSStringFromClass(theClass);
|
||||
NSRange periodRange = [className rangeOfString:@"." options:NSBackwardsSearch];
|
||||
if (periodRange.location == NSNotFound) {
|
||||
return className;
|
||||
}
|
||||
return periodRange.location < className.length - 1
|
||||
? [className substringFromIndex:periodRange.location + 1]
|
||||
: className;
|
||||
}
|
||||
|
||||
/** Returns the name for the screen trace for a given UIViewController. It does the following:
|
||||
* - Removes module name from swift classes - (e.g. MyModule.MyViewController -> MyViewController)
|
||||
* - Prepends "_st_" to the class name
|
||||
* - Truncates the length if it exceeds the maximum trace length.
|
||||
*
|
||||
* @param viewController The view controller whose screen trace name we want. Cannot be nil.
|
||||
* @return An NSString containing the trace name, or a string containing an error if the
|
||||
* class was nil.
|
||||
*/
|
||||
static NSString *FPRScreenTraceNameForViewController(UIViewController *viewController) {
|
||||
NSString *unprefixedClassName = FPRUnprefixedClassName([viewController class]);
|
||||
if (unprefixedClassName.length != 0) {
|
||||
NSString *traceName =
|
||||
[NSString stringWithFormat:@"%@%@", kFPRPrefixForScreenTraceName, unprefixedClassName];
|
||||
return traceName.length > kFPRMaxNameLength ? [traceName substringToIndex:kFPRMaxNameLength]
|
||||
: traceName;
|
||||
} else {
|
||||
// This is unlikely, but might happen if there's a regression on iOS where the class name
|
||||
// returned for a non-nil class is nil or empty.
|
||||
return @"_st_ERROR_NIL_CLASS_NAME";
|
||||
}
|
||||
}
|
||||
|
||||
@implementation FPRScreenTraceTracker {
|
||||
/** Instance variable storing the total frames observed so far. */
|
||||
atomic_int_fast64_t _totalFramesCount;
|
||||
|
||||
/** Instance variable storing the slow frames observed so far. */
|
||||
atomic_int_fast64_t _slowFramesCount;
|
||||
|
||||
/** Instance variable storing the frozen frames observed so far. */
|
||||
atomic_int_fast64_t _frozenFramesCount;
|
||||
}
|
||||
|
||||
@dynamic totalFramesCount;
|
||||
@dynamic frozenFramesCount;
|
||||
@dynamic slowFramesCount;
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static FPRScreenTraceTracker *instance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[self alloc] init];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// Weakly retain viewController, use pointer hashing.
|
||||
NSMapTableOptions keyOptions = NSMapTableWeakMemory | NSMapTableObjectPointerPersonality;
|
||||
// Strongly retain the FIRTrace.
|
||||
NSMapTableOptions valueOptions = NSMapTableStrongMemory;
|
||||
_activeScreenTraces = [NSMapTable mapTableWithKeyOptions:keyOptions valueOptions:valueOptions];
|
||||
|
||||
_previouslyVisibleViewControllers = nil; // Will be set when there is data.
|
||||
_screenTraceTrackerSerialQueue =
|
||||
dispatch_queue_create("com.google.FPRScreenTraceTracker", DISPATCH_QUEUE_SERIAL);
|
||||
_screenTraceTrackerDispatchGroup = dispatch_group_create();
|
||||
|
||||
atomic_store_explicit(&_totalFramesCount, 0, memory_order_relaxed);
|
||||
atomic_store_explicit(&_frozenFramesCount, 0, memory_order_relaxed);
|
||||
atomic_store_explicit(&_slowFramesCount, 0, memory_order_relaxed);
|
||||
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkStep)];
|
||||
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
||||
|
||||
// We don't receive background and foreground events from analytics and so we have to listen to
|
||||
// them ourselves.
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appDidBecomeActiveNotification:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appWillResignActiveNotification:)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_displayLink invalidate];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
}
|
||||
|
||||
- (void)appDidBecomeActiveNotification:(NSNotification *)notification {
|
||||
// To get the most accurate numbers of total, frozen and slow frames, we need to capture them as
|
||||
// soon as we're notified of an event.
|
||||
int64_t currentTotalFrames = atomic_load_explicit(&_totalFramesCount, memory_order_relaxed);
|
||||
int64_t currentFrozenFrames = atomic_load_explicit(&_frozenFramesCount, memory_order_relaxed);
|
||||
int64_t currentSlowFrames = atomic_load_explicit(&_slowFramesCount, memory_order_relaxed);
|
||||
|
||||
dispatch_group_async(self.screenTraceTrackerDispatchGroup, self.screenTraceTrackerSerialQueue, ^{
|
||||
for (id viewController in self.previouslyVisibleViewControllers) {
|
||||
[self startScreenTraceForViewController:viewController
|
||||
currentTotalFrames:currentTotalFrames
|
||||
currentFrozenFrames:currentFrozenFrames
|
||||
currentSlowFrames:currentSlowFrames];
|
||||
}
|
||||
self.previouslyVisibleViewControllers = nil;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appWillResignActiveNotification:(NSNotification *)notification {
|
||||
// To get the most accurate numbers of total, frozen and slow frames, we need to capture them as
|
||||
// soon as we're notified of an event.
|
||||
int64_t currentTotalFrames = atomic_load_explicit(&_totalFramesCount, memory_order_relaxed);
|
||||
int64_t currentFrozenFrames = atomic_load_explicit(&_frozenFramesCount, memory_order_relaxed);
|
||||
int64_t currentSlowFrames = atomic_load_explicit(&_slowFramesCount, memory_order_relaxed);
|
||||
|
||||
dispatch_group_async(self.screenTraceTrackerDispatchGroup, self.screenTraceTrackerSerialQueue, ^{
|
||||
self.previouslyVisibleViewControllers = [NSPointerArray weakObjectsPointerArray];
|
||||
id visibleViewControllersEnumerator = [self.activeScreenTraces keyEnumerator];
|
||||
id visibleViewController = nil;
|
||||
while (visibleViewController = [visibleViewControllersEnumerator nextObject]) {
|
||||
[self.previouslyVisibleViewControllers addPointer:(__bridge void *)(visibleViewController)];
|
||||
}
|
||||
|
||||
for (id visibleViewController in self.previouslyVisibleViewControllers) {
|
||||
[self stopScreenTraceForViewController:visibleViewController
|
||||
currentTotalFrames:currentTotalFrames
|
||||
currentFrozenFrames:currentFrozenFrames
|
||||
currentSlowFrames:currentSlowFrames];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Frozen, slow and good frames
|
||||
|
||||
- (void)displayLinkStep {
|
||||
static CFAbsoluteTime previousTimestamp = kFPRInvalidTime;
|
||||
CFAbsoluteTime currentTimestamp = self.displayLink.timestamp;
|
||||
RecordFrameType(currentTimestamp, previousTimestamp, &_slowFramesCount, &_frozenFramesCount,
|
||||
&_totalFramesCount);
|
||||
previousTimestamp = currentTimestamp;
|
||||
}
|
||||
|
||||
/** This function increments the relevant frame counters based on the current and previous
|
||||
* timestamp provided by the displayLink.
|
||||
*
|
||||
* @param currentTimestamp The current timestamp of the displayLink.
|
||||
* @param previousTimestamp The previous timestamp of the displayLink.
|
||||
* @param slowFramesCounter The value of the slowFramesCount before this function was called.
|
||||
* @param frozenFramesCounter The value of the frozenFramesCount before this function was called.
|
||||
* @param totalFramesCounter The value of the totalFramesCount before this function was called.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
void RecordFrameType(CFAbsoluteTime currentTimestamp,
|
||||
CFAbsoluteTime previousTimestamp,
|
||||
atomic_int_fast64_t *slowFramesCounter,
|
||||
atomic_int_fast64_t *frozenFramesCounter,
|
||||
atomic_int_fast64_t *totalFramesCounter) {
|
||||
CFTimeInterval frameDuration = currentTimestamp - previousTimestamp;
|
||||
if (previousTimestamp == kFPRInvalidTime) {
|
||||
return;
|
||||
}
|
||||
if (frameDuration > kFPRSlowFrameThreshold) {
|
||||
atomic_fetch_add_explicit(slowFramesCounter, 1, memory_order_relaxed);
|
||||
}
|
||||
if (frameDuration > kFPRFrozenFrameThreshold) {
|
||||
atomic_fetch_add_explicit(frozenFramesCounter, 1, memory_order_relaxed);
|
||||
}
|
||||
atomic_fetch_add_explicit(totalFramesCounter, 1, memory_order_relaxed);
|
||||
}
|
||||
|
||||
#pragma mark - Helper methods
|
||||
|
||||
/** Starts a screen trace for the given UIViewController instance if it doesn't exist. This method
|
||||
* does NOT ensure thread safety - the caller is responsible for making sure that this is invoked
|
||||
* in a thread safe manner.
|
||||
*
|
||||
* @param viewController The UIViewController instance for which the trace is to be started.
|
||||
* @param currentTotalFrames The value of the totalFramesCount before this method was called.
|
||||
* @param currentFrozenFrames The value of the frozenFramesCount before this method was called.
|
||||
* @param currentSlowFrames The value of the slowFramesCount before this method was called.
|
||||
*/
|
||||
- (void)startScreenTraceForViewController:(UIViewController *)viewController
|
||||
currentTotalFrames:(int64_t)currentTotalFrames
|
||||
currentFrozenFrames:(int64_t)currentFrozenFrames
|
||||
currentSlowFrames:(int64_t)currentSlowFrames {
|
||||
if (![self shouldCreateScreenTraceForViewController:viewController]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's a trace for this viewController, don't do anything.
|
||||
if (![self.activeScreenTraces objectForKey:viewController]) {
|
||||
NSString *traceName = FPRScreenTraceNameForViewController(viewController);
|
||||
FIRTrace *newTrace = [[FIRTrace alloc] initInternalTraceWithName:traceName];
|
||||
[newTrace start];
|
||||
[newTrace setIntValue:currentTotalFrames forMetric:kFPRTotalFramesCounterName];
|
||||
[newTrace setIntValue:currentFrozenFrames forMetric:kFPRFrozenFrameCounterName];
|
||||
[newTrace setIntValue:currentSlowFrames forMetric:kFPRSlowFrameCounterName];
|
||||
[self.activeScreenTraces setObject:newTrace forKey:viewController];
|
||||
}
|
||||
}
|
||||
|
||||
/** Stops a screen trace for the given UIViewController instance if it exist. This method does NOT
|
||||
* ensure thread safety - the caller is responsible for making sure that this is invoked in a
|
||||
* thread safe manner.
|
||||
*
|
||||
* @param viewController The UIViewController instance for which the trace is to be stopped.
|
||||
* @param currentTotalFrames The value of the totalFramesCount before this method was called.
|
||||
* @param currentFrozenFrames The value of the frozenFramesCount before this method was called.
|
||||
* @param currentSlowFrames The value of the slowFramesCount before this method was called.
|
||||
*/
|
||||
- (void)stopScreenTraceForViewController:(UIViewController *)viewController
|
||||
currentTotalFrames:(int64_t)currentTotalFrames
|
||||
currentFrozenFrames:(int64_t)currentFrozenFrames
|
||||
currentSlowFrames:(int64_t)currentSlowFrames {
|
||||
FIRTrace *previousScreenTrace = [self.activeScreenTraces objectForKey:viewController];
|
||||
|
||||
// Get a diff between the counters now and what they were at trace start.
|
||||
int64_t actualTotalFrames =
|
||||
currentTotalFrames - [previousScreenTrace valueForIntMetric:kFPRTotalFramesCounterName];
|
||||
int64_t actualFrozenFrames =
|
||||
currentFrozenFrames - [previousScreenTrace valueForIntMetric:kFPRFrozenFrameCounterName];
|
||||
int64_t actualSlowFrames =
|
||||
currentSlowFrames - [previousScreenTrace valueForIntMetric:kFPRSlowFrameCounterName];
|
||||
|
||||
// Update the values in the trace.
|
||||
if (actualTotalFrames != 0) {
|
||||
[previousScreenTrace setIntValue:actualTotalFrames forMetric:kFPRTotalFramesCounterName];
|
||||
} else {
|
||||
[previousScreenTrace deleteMetric:kFPRTotalFramesCounterName];
|
||||
}
|
||||
|
||||
if (actualFrozenFrames != 0) {
|
||||
[previousScreenTrace setIntValue:actualFrozenFrames forMetric:kFPRFrozenFrameCounterName];
|
||||
} else {
|
||||
[previousScreenTrace deleteMetric:kFPRFrozenFrameCounterName];
|
||||
}
|
||||
|
||||
if (actualSlowFrames != 0) {
|
||||
[previousScreenTrace setIntValue:actualSlowFrames forMetric:kFPRSlowFrameCounterName];
|
||||
} else {
|
||||
[previousScreenTrace deleteMetric:kFPRSlowFrameCounterName];
|
||||
}
|
||||
|
||||
if (previousScreenTrace.numberOfCounters > 0) {
|
||||
[previousScreenTrace stop];
|
||||
} else {
|
||||
// The trace did not collect any data. Don't log it.
|
||||
[previousScreenTrace cancel];
|
||||
}
|
||||
[self.activeScreenTraces removeObjectForKey:viewController];
|
||||
}
|
||||
|
||||
#pragma mark - Filtering for screen traces
|
||||
|
||||
/** Determines whether to create a screen trace for the given UIViewController instance.
|
||||
*
|
||||
* @param viewController The UIViewController instance.
|
||||
* @return YES if a screen trace should be created for the given UIViewController instance,
|
||||
NO otherwise.
|
||||
*/
|
||||
- (BOOL)shouldCreateScreenTraceForViewController:(UIViewController *)viewController {
|
||||
if (viewController == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Ignore non-main bundle view controllers whose class or superclass is an internal iOS view
|
||||
// controller. This is borrowed from the logic for tracking screens in Firebase Analytics.
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[viewController class]];
|
||||
if (bundle != [NSBundle mainBundle]) {
|
||||
NSString *className = FPRUnprefixedClassName([viewController class]);
|
||||
if ([className hasPrefix:@"_"]) {
|
||||
return NO;
|
||||
}
|
||||
NSString *superClassName = FPRUnprefixedClassName([viewController superclass]);
|
||||
if ([superClassName hasPrefix:@"_"]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
// We are not creating screen traces for these view controllers because they're container view
|
||||
// controllers. They always have a child view controller which will provide better context for a
|
||||
// screen trace. We are however capturing traces if a developer subclasses these as there may be
|
||||
// some context. Special case: We are not capturing screen traces for any input view
|
||||
// controllers.
|
||||
return !([viewController isMemberOfClass:[UINavigationController class]] ||
|
||||
[viewController isMemberOfClass:[UITabBarController class]] ||
|
||||
[viewController isMemberOfClass:[UISplitViewController class]] ||
|
||||
[viewController isMemberOfClass:[UIPageViewController class]] ||
|
||||
[viewController isKindOfClass:[UIInputViewController class]]);
|
||||
}
|
||||
|
||||
#pragma mark - Screen Traces swizzling hooks
|
||||
|
||||
- (void)viewControllerDidAppear:(UIViewController *)viewController {
|
||||
// To get the most accurate numbers of total, frozen and slow frames, we need to capture them as
|
||||
// soon as we're notified of an event.
|
||||
int64_t currentTotalFrames = atomic_load_explicit(&_totalFramesCount, memory_order_relaxed);
|
||||
int64_t currentFrozenFrames = atomic_load_explicit(&_frozenFramesCount, memory_order_relaxed);
|
||||
int64_t currentSlowFrames = atomic_load_explicit(&_slowFramesCount, memory_order_relaxed);
|
||||
|
||||
dispatch_sync(self.screenTraceTrackerSerialQueue, ^{
|
||||
[self startScreenTraceForViewController:viewController
|
||||
currentTotalFrames:currentTotalFrames
|
||||
currentFrozenFrames:currentFrozenFrames
|
||||
currentSlowFrames:currentSlowFrames];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)viewControllerDidDisappear:(id)viewController {
|
||||
// To get the most accurate numbers of total, frozen and slow frames, we need to capture them as
|
||||
// soon as we're notified of an event.
|
||||
int64_t currentTotalFrames = atomic_load_explicit(&_totalFramesCount, memory_order_relaxed);
|
||||
int64_t currentFrozenFrames = atomic_load_explicit(&_frozenFramesCount, memory_order_relaxed);
|
||||
int64_t currentSlowFrames = atomic_load_explicit(&_slowFramesCount, memory_order_relaxed);
|
||||
|
||||
dispatch_sync(self.screenTraceTrackerSerialQueue, ^{
|
||||
[self stopScreenTraceForViewController:viewController
|
||||
currentTotalFrames:currentTotalFrames
|
||||
currentFrozenFrames:currentFrozenFrames
|
||||
currentSlowFrames:currentSlowFrames];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Test Helper Methods
|
||||
|
||||
- (int_fast64_t)totalFramesCount {
|
||||
return atomic_load_explicit(&_totalFramesCount, memory_order_relaxed);
|
||||
}
|
||||
|
||||
- (void)setTotalFramesCount:(int_fast64_t)count {
|
||||
atomic_store_explicit(&_totalFramesCount, count, memory_order_relaxed);
|
||||
}
|
||||
|
||||
- (int_fast64_t)slowFramesCount {
|
||||
return atomic_load_explicit(&_slowFramesCount, memory_order_relaxed);
|
||||
}
|
||||
|
||||
- (void)setSlowFramesCount:(int_fast64_t)count {
|
||||
atomic_store_explicit(&_slowFramesCount, count, memory_order_relaxed);
|
||||
}
|
||||
|
||||
- (int_fast64_t)frozenFramesCount {
|
||||
return atomic_load_explicit(&_frozenFramesCount, memory_order_relaxed);
|
||||
}
|
||||
|
||||
- (void)setFrozenFramesCount:(int_fast64_t)count {
|
||||
atomic_store_explicit(&_frozenFramesCount, count, memory_order_relaxed);
|
||||
}
|
||||
|
||||
@end
|
||||
56
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionDetails.h
generated
Normal file
56
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionDetails.h
generated
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/* List of options the session cares about. */
|
||||
typedef NS_OPTIONS(NSUInteger, FPRSessionOptions) {
|
||||
FPRSessionOptionsNone = 0,
|
||||
FPRSessionOptionsGauges = (1 << 0),
|
||||
FPRSessionOptionsEvents = (1 << 1),
|
||||
};
|
||||
|
||||
/* Class that contains the details of a session including the sessionId and session options. */
|
||||
@interface FPRSessionDetails : NSObject
|
||||
|
||||
/* The sessionId with which the session details is initialized with. */
|
||||
@property(nonatomic, nonnull, readonly) NSString *sessionId;
|
||||
|
||||
/* List of options enabled for the session. */
|
||||
@property(nonatomic, readonly) FPRSessionOptions options;
|
||||
|
||||
/* Length of the session in minutes. */
|
||||
- (NSUInteger)sessionLengthInMinutesFromDate:(nonnull NSDate *)now;
|
||||
|
||||
/**
|
||||
* Creates an instance of FPRSessionDetails with the provided sessionId and the list of available
|
||||
* options.
|
||||
*
|
||||
* @param sessionId Session Id for which the object is created.
|
||||
* @param options Options enabled for the session.
|
||||
* @return Instance of the object FPRSessionDetails.
|
||||
*/
|
||||
- (nonnull instancetype)initWithSessionId:(nonnull NSString *)sessionId
|
||||
options:(FPRSessionOptions)options NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Checks and returns if the session is verbose.
|
||||
*
|
||||
* @return Return YES if verbose, NO otherwise.
|
||||
*/
|
||||
- (BOOL)isVerbose;
|
||||
|
||||
@end
|
||||
59
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionDetails.m
generated
Normal file
59
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionDetails.m
generated
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/AppActivity/FPRSessionDetails.h"
|
||||
|
||||
@interface FPRSessionDetails ()
|
||||
|
||||
/** @brief Time at which the session was created. */
|
||||
@property(nonatomic) NSDate *sessionCreationTime;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRSessionDetails
|
||||
|
||||
- (instancetype)initWithSessionId:(NSString *)sessionId options:(FPRSessionOptions)options {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_sessionId = sessionId;
|
||||
_options = options;
|
||||
_sessionCreationTime = [NSDate date];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (FPRSessionDetails *)copyWithZone:(NSZone *)zone {
|
||||
FPRSessionDetails *detailsCopy = [[[self class] allocWithZone:zone] initWithSessionId:_sessionId
|
||||
options:_options];
|
||||
detailsCopy.sessionCreationTime = _sessionCreationTime;
|
||||
return detailsCopy;
|
||||
}
|
||||
|
||||
- (NSUInteger)sessionLengthInMinutesFromDate:(NSDate *)now {
|
||||
NSTimeInterval sessionLengthInSeconds = ABS([now timeIntervalSinceDate:self.sessionCreationTime]);
|
||||
return (NSUInteger)(sessionLengthInSeconds / 60);
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(FPRSessionDetails *)detailsObject {
|
||||
if (self.sessionId == detailsObject.sessionId) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isVerbose {
|
||||
return (self.options > FPRSessionOptionsNone);
|
||||
}
|
||||
|
||||
@end
|
||||
49
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionManager+Private.h
generated
Normal file
49
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionManager+Private.h
generated
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/FPRGaugeManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This extension should only be used for testing. */
|
||||
@interface FPRSessionManager ()
|
||||
|
||||
@property(nonatomic) FPRGaugeManager *gaugeManager;
|
||||
|
||||
/** The current active session managed by the session manager. Modifiable for unit tests */
|
||||
@property(atomic, nullable, readwrite) FPRSessionDetails *sessionDetails;
|
||||
|
||||
/**
|
||||
* Creates an instance of FPRSesssionManager with the notification center provided. All the
|
||||
* notifications from the session manager will sent using this notification center.
|
||||
*
|
||||
* @param gaugeManager Gauge manager used by the session manager to work with gauges.
|
||||
* @param notificationCenter Notification center with which the session manager with be initialized.
|
||||
* @return Returns an instance of the session manager.
|
||||
*/
|
||||
- (FPRSessionManager *)initWithGaugeManager:(FPRGaugeManager *)gaugeManager
|
||||
notificationCenter:(NSNotificationCenter *)notificationCenter;
|
||||
|
||||
/**
|
||||
* Checks if the currently active session is beyond maximum allowed time for gauge-collection. If so
|
||||
* stop gauges, else no-op.
|
||||
*/
|
||||
- (void)stopGaugesIfRunningTooLong;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
54
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionManager.h
generated
Normal file
54
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionManager.h
generated
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionDetails.h"
|
||||
|
||||
/* Notification name when the session Id gets updated. */
|
||||
FOUNDATION_EXTERN NSString *_Nonnull const kFPRSessionIdUpdatedNotification;
|
||||
|
||||
/* Notification name when the session Id gets updated. */
|
||||
FOUNDATION_EXTERN NSString *_Nonnull const kFPRSessionIdNotificationKey;
|
||||
|
||||
/** This class manages the current active sessionId of the application and provides mechanism for
|
||||
* propagating the session Id.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRSessionManager : NSObject
|
||||
|
||||
/** The current active session managed by the session manager. */
|
||||
@property(atomic, readonly, nonnull) FPRSessionDetails *sessionDetails;
|
||||
|
||||
/**
|
||||
* The notification center managed by the session manager. All the notifications by the session
|
||||
* manager will get broadcasted on this notification center.
|
||||
*/
|
||||
@property(nonatomic, readonly, nonnull) NSNotificationCenter *sessionNotificationCenter;
|
||||
|
||||
/**
|
||||
* The shared instance of Session Manager.
|
||||
*
|
||||
* @return The singleton instance.
|
||||
*/
|
||||
+ (nonnull FPRSessionManager *)sharedInstance;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (void)updateSessionId:(nonnull NSString *)sessionIdString;
|
||||
|
||||
// Collects all the enabled gauge metrics once.
|
||||
- (void)collectAllGaugesOnce;
|
||||
|
||||
@end
|
||||
113
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionManager.m
generated
Normal file
113
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRSessionManager.m
generated
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NSString *const kFPRSessionIdUpdatedNotification = @"kFPRSessionIdUpdatedNotification";
|
||||
NSString *const kFPRSessionIdNotificationKey = @"kFPRSessionIdNotificationKey";
|
||||
|
||||
@interface FPRSessionManager ()
|
||||
|
||||
@property(nonatomic, readwrite) NSNotificationCenter *sessionNotificationCenter;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRSessionManager
|
||||
|
||||
+ (FPRSessionManager *)sharedInstance {
|
||||
static FPRSessionManager *instance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSNotificationCenter *notificationCenter = [[NSNotificationCenter alloc] init];
|
||||
FPRGaugeManager *gaugeManager = [FPRGaugeManager sharedInstance];
|
||||
instance = [[FPRSessionManager alloc] initWithGaugeManager:gaugeManager
|
||||
notificationCenter:notificationCenter];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (FPRSessionManager *)initWithGaugeManager:(FPRGaugeManager *)gaugeManager
|
||||
notificationCenter:(NSNotificationCenter *)notificationCenter {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_gaugeManager = gaugeManager;
|
||||
_sessionNotificationCenter = notificationCenter;
|
||||
// Empty string is immediately replaced when FirebaseCore runs Fireperf's
|
||||
// FIRComponentCreationBlock, because in the creation block we register Fireperf with Sessions,
|
||||
// and the registration function immediately propagates real sessionId. This is at an early time
|
||||
// in initialization that any trace is yet to be created.
|
||||
_sessionDetails = [[FPRSessionDetails alloc] initWithSessionId:@""
|
||||
options:FPRSessionOptionsNone];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)stopGaugesIfRunningTooLong {
|
||||
NSUInteger maxSessionLength = [[FPRConfigurations sharedInstance] maxSessionLengthInMinutes];
|
||||
if ([self.sessionDetails sessionLengthInMinutesFromDate:[NSDate date]] >= maxSessionLength) {
|
||||
[self.gaugeManager stopCollectingGauges:FPRGaugeCPU | FPRGaugeMemory];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops current session, and create a new session with new session id.
|
||||
*
|
||||
* @param sessionIdString New session id.
|
||||
*/
|
||||
- (void)updateSessionId:(NSString *)sessionIdString {
|
||||
FPRSessionOptions sessionOptions = FPRSessionOptionsNone;
|
||||
if ([self isGaugeCollectionEnabledForSessionId:sessionIdString]) {
|
||||
[self.gaugeManager startCollectingGauges:FPRGaugeCPU | FPRGaugeMemory
|
||||
forSessionId:sessionIdString];
|
||||
sessionOptions = FPRSessionOptionsGauges;
|
||||
} else {
|
||||
[self.gaugeManager stopCollectingGauges:FPRGaugeCPU | FPRGaugeMemory];
|
||||
}
|
||||
|
||||
FPRLogDebug(kFPRSessionId, @"Session Id changed - %@", sessionIdString);
|
||||
FPRSessionDetails *sessionInfo = [[FPRSessionDetails alloc] initWithSessionId:sessionIdString
|
||||
options:sessionOptions];
|
||||
self.sessionDetails = sessionInfo;
|
||||
NSMutableDictionary<NSString *, FPRSessionDetails *> *userInfo =
|
||||
[[NSMutableDictionary alloc] init];
|
||||
[userInfo setObject:sessionInfo forKey:kFPRSessionIdNotificationKey];
|
||||
[self.sessionNotificationCenter postNotificationName:kFPRSessionIdUpdatedNotification
|
||||
object:self
|
||||
userInfo:[userInfo copy]];
|
||||
}
|
||||
|
||||
- (void)collectAllGaugesOnce {
|
||||
[self.gaugeManager collectAllGauges];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided sessionId can have gauge data collection enabled.
|
||||
*
|
||||
* @param sessionId Session Id for which the check is done.
|
||||
* @return YES if gauge collection is enabled, NO otherwise.
|
||||
*/
|
||||
- (BOOL)isGaugeCollectionEnabledForSessionId:(NSString *)sessionId {
|
||||
float_t sessionSamplePercentage = [[FPRConfigurations sharedInstance] sessionsSamplingPercentage];
|
||||
double randomNumberBetween0And1 = ((double)arc4random() / UINT_MAX);
|
||||
BOOL sessionsEnabled = randomNumberBetween0And1 * 100 < sessionSamplePercentage;
|
||||
return sessionsEnabled;
|
||||
}
|
||||
|
||||
@end
|
||||
42
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.h
generated
Normal file
42
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.h
generated
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/** Different background states of a trace. */
|
||||
typedef NS_ENUM(NSInteger, FPRTraceState) {
|
||||
FPRTraceStateUnknown,
|
||||
|
||||
/** Background only trace. */
|
||||
FPRTraceStateBackgroundOnly,
|
||||
|
||||
/** Foreground only trace. */
|
||||
FPRTraceStateForegroundOnly,
|
||||
|
||||
/** Background and foreground trace. */
|
||||
FPRTraceStateBackgroundAndForeground,
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is used to track the app activity and track the background and foreground state of the
|
||||
* object. This object will be used by a trace to determine its application state if the lifecycle
|
||||
* of the trace is backgrounded, foregrounded or both.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRTraceBackgroundActivityTracker : NSObject
|
||||
|
||||
/** Background state of the tracker. */
|
||||
@property(nonatomic, readonly) FPRTraceState traceBackgroundState;
|
||||
|
||||
@end
|
||||
81
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.m
generated
Normal file
81
Pods/FirebasePerformance/FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.m
generated
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"
|
||||
|
||||
@interface FPRTraceBackgroundActivityTracker ()
|
||||
|
||||
@property(nonatomic, readwrite) FPRTraceState traceBackgroundState;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRTraceBackgroundActivityTracker
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if ([FPRAppActivityTracker sharedInstance].applicationState == FPRApplicationStateBackground) {
|
||||
_traceBackgroundState = FPRTraceStateBackgroundOnly;
|
||||
} else {
|
||||
_traceBackgroundState = FPRTraceStateForegroundOnly;
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationDidBecomeActive:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationDidEnterBackground:)
|
||||
name:UIApplicationDidEnterBackgroundNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// Remove all the notification observers registered.
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
#pragma mark - UIApplicationDelegate events
|
||||
|
||||
/**
|
||||
* This gets called whenever the app becomes active.
|
||||
*
|
||||
* @param notification Notification received during app launch.
|
||||
*/
|
||||
- (void)applicationDidBecomeActive:(NSNotification *)notification {
|
||||
if (_traceBackgroundState == FPRTraceStateBackgroundOnly) {
|
||||
_traceBackgroundState = FPRTraceStateBackgroundAndForeground;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets called whenever the app enters background.
|
||||
*
|
||||
* @param notification Notification received when the app enters background.
|
||||
*/
|
||||
- (void)applicationDidEnterBackground:(NSNotification *)notification {
|
||||
if (_traceBackgroundState == FPRTraceStateForegroundOnly) {
|
||||
_traceBackgroundState = FPRTraceStateBackgroundAndForeground;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
51
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConsoleURLGenerator.h
generated
Normal file
51
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConsoleURLGenerator.h
generated
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2021 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/** This class generated the console URLs for a project or a metric.*/
|
||||
@interface FPRConsoleURLGenerator : NSObject
|
||||
|
||||
/**
|
||||
* Generates the console URL for the dashboard page of the project.
|
||||
*
|
||||
* @param projectID The Firebase project ID.
|
||||
* @param bundleID The bundle ID of this project.
|
||||
* @return The console URL for the dashboard page.
|
||||
*/
|
||||
+ (NSString *)generateDashboardURLWithProjectID:(NSString *)projectID bundleID:(NSString *)bundleID;
|
||||
|
||||
/**
|
||||
* Generates the console URL for the custom trace page.
|
||||
*
|
||||
* @param projectID The Firebase project ID.
|
||||
* @param bundleID The bundle ID of this project.
|
||||
* @return The console URL for the custom trace page.
|
||||
*/
|
||||
+ (NSString *)generateCustomTraceURLWithProjectID:(NSString *)projectID
|
||||
bundleID:(NSString *)bundleID
|
||||
traceName:(NSString *)traceName;
|
||||
|
||||
/**
|
||||
* Generates the console URL for the screen trace page.
|
||||
*
|
||||
* @param projectID The Firebase project ID.
|
||||
* @param bundleID The bundle ID of this project.
|
||||
* @return The console URL for the custom trace page.
|
||||
*/
|
||||
+ (NSString *)generateScreenTraceURLWithProjectID:(NSString *)projectID
|
||||
bundleID:(NSString *)bundleID
|
||||
traceName:(NSString *)traceName;
|
||||
|
||||
@end
|
||||
56
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConsoleURLGenerator.m
generated
Normal file
56
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConsoleURLGenerator.m
generated
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2021 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Common/FPRConsoleURLGenerator.h"
|
||||
|
||||
NSString *const URL_BASE_PATH = @"https://console.firebase.google.com";
|
||||
NSString *const UTM_MEDIUM = @"ios-ide";
|
||||
NSString *const UTM_SOURCE = @"perf-ios-sdk";
|
||||
|
||||
@implementation FPRConsoleURLGenerator
|
||||
|
||||
/** This is a class method to generate the console URL for the project's dashboard page.*/
|
||||
+ (NSString *)generateDashboardURLWithProjectID:(NSString *)projectID
|
||||
bundleID:(NSString *)bundleID {
|
||||
NSString *rootUrl = [FPRConsoleURLGenerator getRootURLWithProjectID:projectID bundleID:bundleID];
|
||||
return [NSString
|
||||
stringWithFormat:@"%@/trends?utm_source=%@&utm_medium=%@", rootUrl, UTM_SOURCE, UTM_MEDIUM];
|
||||
}
|
||||
|
||||
/** This is a class method to generate the console URL for the custom trace.*/
|
||||
+ (NSString *)generateCustomTraceURLWithProjectID:(NSString *)projectID
|
||||
bundleID:(NSString *)bundleID
|
||||
traceName:(NSString *)traceName {
|
||||
NSString *rootUrl = [FPRConsoleURLGenerator getRootURLWithProjectID:projectID bundleID:bundleID];
|
||||
return [NSString stringWithFormat:@"%@/troubleshooting/trace/"
|
||||
@"DURATION_TRACE/%@?utm_source=%@&utm_medium=%@",
|
||||
rootUrl, traceName, UTM_SOURCE, UTM_MEDIUM];
|
||||
}
|
||||
|
||||
/** This is a class method to generate the console URL for the screen trace.*/
|
||||
+ (NSString *)generateScreenTraceURLWithProjectID:(NSString *)projectID
|
||||
bundleID:(NSString *)bundleID
|
||||
traceName:(NSString *)traceName {
|
||||
NSString *rootUrl = [FPRConsoleURLGenerator getRootURLWithProjectID:projectID bundleID:bundleID];
|
||||
return [NSString stringWithFormat:@"%@/troubleshooting/trace/"
|
||||
@"SCREEN_TRACE/%@?utm_source=%@&utm_medium=%@",
|
||||
rootUrl, traceName, UTM_SOURCE, UTM_MEDIUM];
|
||||
}
|
||||
|
||||
/** This is a class method to get the root URL for the console .*/
|
||||
+ (NSString *)getRootURLWithProjectID:(NSString *)projectID bundleID:(NSString *)bundleID {
|
||||
return [NSString
|
||||
stringWithFormat:@"%@/project/%@/performance/app/ios:%@", URL_BASE_PATH, projectID, bundleID];
|
||||
}
|
||||
@end
|
||||
39
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConstants.h
generated
Normal file
39
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConstants.h
generated
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
// SDK Version number.
|
||||
FOUNDATION_EXTERN const char* const kFPRSDKVersion;
|
||||
|
||||
// Prefix for internal naming of objects
|
||||
FOUNDATION_EXTERN NSString* const kFPRInternalNamePrefix;
|
||||
|
||||
// Max length for object names
|
||||
FOUNDATION_EXTERN int const kFPRMaxNameLength;
|
||||
|
||||
// Max URL length
|
||||
FOUNDATION_EXTERN int const kFPRMaxURLLength;
|
||||
|
||||
// Max length for attribute name.
|
||||
FOUNDATION_EXTERN int const kFPRMaxAttributeNameLength;
|
||||
|
||||
// Max length for attribute value.
|
||||
FOUNDATION_EXTERN int const kFPRMaxAttributeValueLength;
|
||||
|
||||
// Maximum number of global custom attributes.
|
||||
FOUNDATION_EXTERN int const kFPRMaxGlobalCustomAttributesCount;
|
||||
|
||||
// Maximum number of trace custom attributes.
|
||||
FOUNDATION_EXTERN int const kFPRMaxTraceCustomAttributesCount;
|
||||
43
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConstants.m
generated
Normal file
43
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRConstants.m
generated
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
|
||||
// extract macro value into a C string
|
||||
#define STR_FROM_MACRO(x) #x
|
||||
#define STR(x) STR_FROM_MACRO(x)
|
||||
|
||||
// SDK Version number.
|
||||
const char *const kFPRSDKVersion = (const char *const)STR(FIRPerformance_LIB_VERSION);
|
||||
|
||||
// Characters used prefix for internal naming of objects.
|
||||
NSString *const kFPRInternalNamePrefix = @"_";
|
||||
|
||||
// Max length for object names
|
||||
int const kFPRMaxNameLength = 100;
|
||||
|
||||
// Max URL length.
|
||||
int const kFPRMaxURLLength = 2000;
|
||||
|
||||
// Max length for attribute name.
|
||||
int const kFPRMaxAttributeNameLength = 40;
|
||||
|
||||
// Max length for attribute value.
|
||||
int const kFPRMaxAttributeValueLength = 100;
|
||||
|
||||
// Maximum number of global custom attributes.
|
||||
int const kFPRMaxGlobalCustomAttributesCount = 5;
|
||||
|
||||
// Maximum number of trace custom attributes.
|
||||
int const kFPRMaxTraceCustomAttributesCount = 5;
|
||||
35
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDate.h
generated
Normal file
35
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDate.h
generated
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* Definition of a date that is used internally.
|
||||
*/
|
||||
@protocol FPRDate <NSObject>
|
||||
|
||||
/** Returns the current time. */
|
||||
- (NSDate *)now;
|
||||
|
||||
/**
|
||||
* Calculates the time difference between the provided date and returns the difference in seconds.
|
||||
*
|
||||
* @param date A date object used for reference.
|
||||
* @return Difference in time between the current date and the provided date in seconds. If the
|
||||
* current date is older than the provided date, the difference is returned in positive, else
|
||||
* negative.
|
||||
*/
|
||||
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)date;
|
||||
|
||||
@end
|
||||
60
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDiagnostics.h
generated
Normal file
60
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDiagnostics.h
generated
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
/** Logs assert information. This shouldn't be called by anything except FPRAssert.
|
||||
*
|
||||
* @param object The object (or class) that is asserting.
|
||||
* @param condition The condition that is being asserted to be true.
|
||||
* @param func The value of the __func__ variable.
|
||||
*/
|
||||
FOUNDATION_EXTERN void __FPRAssert(id object, BOOL condition, const char *func);
|
||||
|
||||
/** This protocol defines the selectors that are invoked when a diagnostics event occurs. */
|
||||
@protocol FPRDiagnosticsProtocol
|
||||
|
||||
@optional
|
||||
|
||||
/** Emits class-level diagnostic information. */
|
||||
+ (void)emitDiagnostics;
|
||||
|
||||
/** Emits object-level diagnostic information. */
|
||||
- (void)emitDiagnostics;
|
||||
|
||||
@end
|
||||
|
||||
// Use this define in implementations of +/-emitDiagnostics.
|
||||
#define EMIT_DIAGNOSTIC(...) FPRLogNotice(kFPRDiagnosticLog, __VA_ARGS__)
|
||||
|
||||
// This assert adds additional functionality to the normal NSAssert, including printing out
|
||||
// information when NSAsserts are stripped. A __builtin_expect is utilized to keep running speed
|
||||
// as fast as possible.
|
||||
#define FPRAssert(condition, ...) \
|
||||
{ \
|
||||
do { \
|
||||
__FPRAssert(self, !!(condition), __func__); \
|
||||
NSAssert(condition, __VA_ARGS__); \
|
||||
} while (0); \
|
||||
}
|
||||
|
||||
/** This class handles the control of diagnostics in the SDK. */
|
||||
@interface FPRDiagnostics : NSObject
|
||||
|
||||
/** YES if diagnostics are enabled, NO otherwise. */
|
||||
@property(class, nonatomic, readonly, getter=isEnabled) BOOL enabled;
|
||||
|
||||
@end
|
||||
83
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDiagnostics.m
generated
Normal file
83
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDiagnostics.m
generated
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics_Private.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
|
||||
void __FPRAssert(id object, BOOL condition, const char *func) {
|
||||
static BOOL diagnosticsEnabled = NO;
|
||||
static dispatch_once_t onceToken;
|
||||
NSDictionary<NSString *, NSString *> *environment = [NSProcessInfo processInfo].environment;
|
||||
// Enable diagnostics when in test environment
|
||||
if (environment[@"XCTestConfigurationFilePath"] != nil) {
|
||||
diagnosticsEnabled = [FPRDiagnostics isEnabled];
|
||||
} else {
|
||||
dispatch_once(&onceToken, ^{
|
||||
diagnosticsEnabled = [FPRDiagnostics isEnabled];
|
||||
});
|
||||
}
|
||||
|
||||
if (__builtin_expect(!condition && diagnosticsEnabled, NO)) {
|
||||
FPRLogError(kFPRDiagnosticFailure, @"Failure in %s, information follows:", func);
|
||||
FPRLogNotice(kFPRDiagnosticLog, @"Stack for failure in %s:\n%@", func,
|
||||
[NSThread callStackSymbols]);
|
||||
if ([[object class] respondsToSelector:@selector(emitDiagnostics)]) {
|
||||
[[object class] performSelector:@selector(emitDiagnostics) withObject:nil];
|
||||
}
|
||||
if ([object respondsToSelector:@selector(emitDiagnostics)]) {
|
||||
[object performSelector:@selector(emitDiagnostics) withObject:nil];
|
||||
}
|
||||
FPRLogNotice(kFPRDiagnosticLog, @"End of diagnostics for %s failure.", func);
|
||||
}
|
||||
}
|
||||
|
||||
@implementation FPRDiagnostics
|
||||
|
||||
static FPRConfigurations *_configuration;
|
||||
|
||||
+ (void)initialize {
|
||||
_configuration = [FPRConfigurations sharedInstance];
|
||||
}
|
||||
|
||||
+ (FPRConfigurations *)configuration {
|
||||
return _configuration;
|
||||
}
|
||||
|
||||
+ (void)setConfiguration:(FPRConfigurations *)config {
|
||||
_configuration = config;
|
||||
}
|
||||
|
||||
+ (BOOL)isEnabled {
|
||||
// Check a soft-linked FIRCore class to see if this is running in the app store.
|
||||
Class FIRAppEnvironmentUtil = NSClassFromString(@"FIRAppEnvironmentUtil");
|
||||
SEL isFromAppStore = NSSelectorFromString(@"isFromAppStore");
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
if (FIRAppEnvironmentUtil && [FIRAppEnvironmentUtil respondsToSelector:isFromAppStore] &&
|
||||
[FIRAppEnvironmentUtil performSelector:isFromAppStore]) {
|
||||
return NO;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
BOOL enabled = [FPRDiagnostics.configuration diagnosticsEnabled];
|
||||
if (enabled) {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
FPRLogNotice(kFPRDiagnosticInfo, @"Firebase Performance Diagnostics have been enabled!");
|
||||
});
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@end
|
||||
27
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDiagnostics_Private.h
generated
Normal file
27
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRDiagnostics_Private.h
generated
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
|
||||
/**
|
||||
* Extension that is added on top of the class FPRDiagnostics to make the private properties
|
||||
* visible between the implementation file and the unit tests.
|
||||
*/
|
||||
@interface FPRDiagnostics ()
|
||||
|
||||
/** FPRCongiguration to check if diagnostic is enabled. */
|
||||
@property(class, nonatomic, readwrite) FPRConfigurations *configuration;
|
||||
|
||||
@end
|
||||
22
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRPerfDate.h
generated
Normal file
22
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRPerfDate.h
generated
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Common/FPRDate.h"
|
||||
|
||||
/**
|
||||
* FPRPerfDate creates a date object that does time calculations.
|
||||
*/
|
||||
@interface FPRPerfDate : NSObject <FPRDate>
|
||||
|
||||
@end
|
||||
27
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRPerfDate.m
generated
Normal file
27
Pods/FirebasePerformance/FirebasePerformance/Sources/Common/FPRPerfDate.m
generated
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Common/FPRPerfDate.h"
|
||||
|
||||
@implementation FPRPerfDate
|
||||
|
||||
- (NSDate *)now {
|
||||
return [NSDate date];
|
||||
}
|
||||
|
||||
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)date {
|
||||
return [self.now timeIntervalSinceDate:date];
|
||||
}
|
||||
|
||||
@end
|
||||
76
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h
generated
Normal file
76
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h
generated
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class GULUserDefaults;
|
||||
|
||||
/** List of gauges the gauge manager controls. */
|
||||
typedef NS_OPTIONS(NSUInteger, FPRConfigurationSource) {
|
||||
FPRConfigurationSourceNone = 0,
|
||||
FPRConfigurationSourceRemoteConfig = (1 << 1),
|
||||
};
|
||||
|
||||
/** This extension should only be used for testing. */
|
||||
@interface FPRConfigurations ()
|
||||
|
||||
/** @brief Different configuration sources managed by the object. */
|
||||
@property(nonatomic) FPRConfigurationSource sources;
|
||||
|
||||
/** @brief Instance of remote config flags. */
|
||||
@property(nonatomic) FPRRemoteConfigFlags *remoteConfigFlags;
|
||||
|
||||
/** @brief The class to use when FIRApp is referenced. */
|
||||
@property(nonatomic) Class FIRAppClass;
|
||||
|
||||
/** @brief User defaults used for user preference config fetches . */
|
||||
@property(nonatomic) GULUserDefaults *userDefaults;
|
||||
|
||||
/** @brief The main bundle identifier used by config system. */
|
||||
@property(nonatomic) NSString *mainBundleIdentifier;
|
||||
|
||||
/** @brief The infoDictionary provided by the main bundle. */
|
||||
@property(nonatomic) NSDictionary<NSString *, id> *infoDictionary;
|
||||
|
||||
/** @brief Configurations update queue. */
|
||||
@property(nonatomic) dispatch_queue_t updateQueue;
|
||||
|
||||
/**
|
||||
* Creates an instance of the FPRConfigurations class with the specified sources.
|
||||
*
|
||||
* @param source Source that needs to be enabled for fetching configurations.
|
||||
* @return Instance of FPRConfiguration.
|
||||
*/
|
||||
- (instancetype)initWithSources:(FPRConfigurationSource)source NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Returns the list of SDK versions that are disabled. SDK Versions are ';' separated. If no
|
||||
* versions are disabled, an empty set is returned.
|
||||
*
|
||||
* @return The set of disabled SDK versions.
|
||||
*/
|
||||
- (nonnull NSSet<NSString *> *)sdkDisabledVersions;
|
||||
|
||||
/**
|
||||
* Resets this class by changing the onceToken back to 0, allowing a new singleton to be created,
|
||||
* while the old one is dealloc'd. This should only be used for testing.
|
||||
*/
|
||||
+ (void)reset;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
212
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRConfigurations.h
generated
Normal file
212
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRConfigurations.h
generated
Normal file
@ -0,0 +1,212 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Different modes of prewarm-detection
|
||||
* KeepNone = No app start events are allowed
|
||||
* ActivePrewarm = Only detect prewarming using ActivePrewarm environment
|
||||
* KeepAll = All app start events are allowed
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, PrewarmDetectionMode) {
|
||||
PrewarmDetectionModeKeepNone = 0,
|
||||
PrewarmDetectionModeActivePrewarm = 1,
|
||||
PrewarmDetectionModeKeepAll = 2
|
||||
};
|
||||
|
||||
/** A typedef for ensuring that config names are one of the below specified strings. */
|
||||
typedef NSString* const FPRConfigName;
|
||||
|
||||
/**
|
||||
* Class that manages the configurations used by firebase performance SDK. This class abstracts the
|
||||
* configuration flags from different configuration sources.
|
||||
*/
|
||||
@interface FPRConfigurations : NSObject
|
||||
|
||||
/** Enables or disables performance data collection in the SDK. If the value is set to 'NO' none of
|
||||
* the performance data will be sent to the server. Default is YES. */
|
||||
@property(nonatomic, getter=isDataCollectionEnabled) BOOL dataCollectionEnabled;
|
||||
|
||||
/** The config KVC name string for the dataCollectionEnabled property. */
|
||||
FOUNDATION_EXTERN FPRConfigName kFPRConfigDataCollectionEnabled;
|
||||
|
||||
/** Enables or disables instrumenting the app to collect performance data (like app start time,
|
||||
* networking). Default is YES. */
|
||||
@property(nonatomic, getter=isInstrumentationEnabled) BOOL instrumentationEnabled;
|
||||
|
||||
/** The config KVC name string for the instrumentationEnabled property. */
|
||||
FOUNDATION_EXTERN FPRConfigName kFPRConfigInstrumentationEnabled;
|
||||
|
||||
/** Log source against which the Fireperf events are recorded. */
|
||||
@property(nonatomic, readonly) int logSource;
|
||||
|
||||
/** Specifies if the SDK is enabled. */
|
||||
@property(nonatomic, readonly) BOOL sdkEnabled;
|
||||
|
||||
/** Specifies if the diagnostic log messages should be enabled. */
|
||||
@property(nonatomic, readonly) BOOL diagnosticsEnabled;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Singleton instance of FPRConfigurations. */
|
||||
+ (nullable instancetype)sharedInstance;
|
||||
|
||||
/**
|
||||
* Updates all the configurations flags relevant to Firebase Performance.
|
||||
*
|
||||
* This call blocks until the update is done.
|
||||
*/
|
||||
- (void)update;
|
||||
|
||||
#pragma mark - Configuration fetcher methods.
|
||||
|
||||
/**
|
||||
* Returns the mode that prewarm-detection should drop events in.
|
||||
*
|
||||
* @see PrewarmDetectionMode
|
||||
* @return filter mode of app start traces prewarm-detection
|
||||
*/
|
||||
- (PrewarmDetectionMode)prewarmDetectionMode;
|
||||
|
||||
/**
|
||||
* Returns the percentage of instances that would send trace events. Range [0-1].
|
||||
*
|
||||
* @return The percentage of instances that would send trace events.
|
||||
*/
|
||||
- (float)logTraceSamplingRate;
|
||||
|
||||
/**
|
||||
* Returns the percentage of instances that would send network request events. Range [0-1].
|
||||
*
|
||||
* @return The percentage of instances that would send network request events.
|
||||
*/
|
||||
- (float)logNetworkSamplingRate;
|
||||
|
||||
/**
|
||||
* Returns the foreground event count/burst size. This is the number of events that are allowed to
|
||||
* flow in burst when the app is in foreground.
|
||||
*
|
||||
* @return The foreground event count as determined from configs.
|
||||
*/
|
||||
- (uint32_t)foregroundEventCount;
|
||||
|
||||
/**
|
||||
* Returns the foreground time limit to allow the foreground event count. This is specified in
|
||||
* number of minutes.
|
||||
*
|
||||
* @return The foreground event time limit as determined from configs.
|
||||
*/
|
||||
- (uint32_t)foregroundEventTimeLimit;
|
||||
|
||||
/**
|
||||
* Returns the background event count/burst size. This is the number of events that are allowed to
|
||||
* flow in burst when the app is in background.
|
||||
*
|
||||
* @return The background event count as determined from configs.
|
||||
*/
|
||||
- (uint32_t)backgroundEventCount;
|
||||
|
||||
/**
|
||||
* Returns the background time limit to allow the background event count. This is specified in
|
||||
* number of minutes.
|
||||
*
|
||||
* @return The background event time limit as determined from configs.
|
||||
*/
|
||||
- (uint32_t)backgroundEventTimeLimit;
|
||||
|
||||
/**
|
||||
* Returns the foreground network event count/burst size. This is the number of network events that
|
||||
* are allowed to flow in burst when the app is in foreground.
|
||||
*
|
||||
* @return The foreground network event count as determined from configs.
|
||||
*/
|
||||
- (uint32_t)foregroundNetworkEventCount;
|
||||
|
||||
/**
|
||||
* Returns the foreground time limit to allow the foreground network event count. This is specified
|
||||
* in number of minutes.
|
||||
*
|
||||
* @return The foreground network event time limit as determined from configs.
|
||||
*/
|
||||
- (uint32_t)foregroundNetworkEventTimeLimit;
|
||||
|
||||
/**
|
||||
* Returns the background network event count/burst size. This is the number of network events that
|
||||
* are allowed to flow in burst when the app is in background.
|
||||
*
|
||||
* @return The background network event count as determined from configs.
|
||||
*/
|
||||
- (uint32_t)backgroundNetworkEventCount;
|
||||
|
||||
/**
|
||||
* Returns the background time limit to allow the background network event count. This is specified
|
||||
* in number of minutes.
|
||||
*
|
||||
* @return The background network event time limit as determined from configs.
|
||||
*/
|
||||
- (uint32_t)backgroundNetworkEventTimeLimit;
|
||||
|
||||
/**
|
||||
* Returns a float specifying the percentage of device instances on which session feature is
|
||||
* enabled. Range [0-100].
|
||||
*
|
||||
* @return The percentage of devices on which session feature should be enabled.
|
||||
*/
|
||||
- (float_t)sessionsSamplingPercentage;
|
||||
|
||||
/**
|
||||
* Returns the maximum length of a session in minutes. Default is 240 minutes.
|
||||
*
|
||||
* @return Maximum allowed length of the session in minutes.
|
||||
*/
|
||||
- (uint32_t)maxSessionLengthInMinutes;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which the CPU usage metrics are to be collected when the app is in the
|
||||
* foreground. Frequency is specified in milliseconds. A value of '0' means do not capture.
|
||||
*
|
||||
* @return An integer value specifying the frequency of capture in milliseconds.
|
||||
*/
|
||||
- (uint32_t)cpuSamplingFrequencyInForegroundInMS;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which the CPU usage metrics are to be collected when the app is in the
|
||||
* background. Frequency is specified in milliseconds. A value of '0' means do not capture.
|
||||
*
|
||||
* @return An integer value specifying the frequency of capture in milliseconds.
|
||||
*/
|
||||
- (uint32_t)cpuSamplingFrequencyInBackgroundInMS;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which the memory usage metrics are to be collected when the app is in
|
||||
* the foreground. Frequency is specified in milliseconds. A value of '0' means do not capture.
|
||||
*
|
||||
* @return An integer value specifying the frequency of capture in milliseconds.
|
||||
*/
|
||||
- (uint32_t)memorySamplingFrequencyInForegroundInMS;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which the memory usage metrics are to be collected when the app is in
|
||||
* the background. Frequency is specified in milliseconds. A value of '0' means do not capture.
|
||||
*
|
||||
* @return An integer value specifying the frequency of capture in milliseconds.
|
||||
*/
|
||||
- (uint32_t)memorySamplingFrequencyInBackgroundInMS;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
488
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRConfigurations.m
generated
Normal file
488
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRConfigurations.m
generated
Normal file
@ -0,0 +1,488 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <UIKit/UIKit.h>
|
||||
|
||||
#import <GoogleUtilities/GULUserDefaults.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags+Private.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h"
|
||||
|
||||
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
|
||||
|
||||
FPRConfigName kFPRConfigDataCollectionEnabled = @"dataCollectionEnabled";
|
||||
|
||||
FPRConfigName kFPRConfigInstrumentationEnabled = @"instrumentationEnabled";
|
||||
|
||||
NSString *const kFPRConfigInstrumentationUserPreference =
|
||||
@"com.firebase.performanceInsrumentationEnabled";
|
||||
NSString *const kFPRConfigInstrumentationPlistKey = @"firebase_performance_instrumentation_enabled";
|
||||
|
||||
NSString *const kFPRConfigCollectionUserPreference = @"com.firebase.performanceCollectionEnabled";
|
||||
NSString *const kFPRConfigCollectionPlistKey = @"firebase_performance_collection_enabled";
|
||||
|
||||
NSString *const kFPRDiagnosticsUserPreference = @"FPRDiagnosticsLocal";
|
||||
NSString *const kFPRDiagnosticsEnabledPlistKey = @"FPRDiagnosticsLocal";
|
||||
|
||||
NSString *const kFPRConfigCollectionDeactivationPlistKey =
|
||||
@"firebase_performance_collection_deactivated";
|
||||
|
||||
NSString *const kFPRConfigLogSource = @"com.firebase.performanceLogSource";
|
||||
|
||||
@implementation FPRConfigurations
|
||||
|
||||
static dispatch_once_t gSharedInstanceToken;
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static FPRConfigurations *instance = nil;
|
||||
dispatch_once(&gSharedInstanceToken, ^{
|
||||
FPRConfigurationSource sources = FPRConfigurationSourceRemoteConfig;
|
||||
instance = [[FPRConfigurations alloc] initWithSources:sources];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ (void)reset {
|
||||
// TODO(b/120032990): Reset the singletons that this singleton uses.
|
||||
gSharedInstanceToken = 0;
|
||||
[[GULUserDefaults standardUserDefaults]
|
||||
removeObjectForKey:kFPRConfigInstrumentationUserPreference];
|
||||
[[GULUserDefaults standardUserDefaults] removeObjectForKey:kFPRConfigCollectionUserPreference];
|
||||
}
|
||||
|
||||
- (instancetype)initWithSources:(FPRConfigurationSource)source {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_sources = source;
|
||||
[self setupRemoteConfigFlags];
|
||||
|
||||
// Register for notifications to update configs.
|
||||
[self registerForNotifications];
|
||||
|
||||
self.FIRAppClass = [FIRApp class];
|
||||
self.userDefaults = [GULUserDefaults standardUserDefaults];
|
||||
self.infoDictionary = [NSBundle mainBundle].infoDictionary;
|
||||
self.mainBundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
|
||||
self.updateQueue = dispatch_queue_create("com.google.perf.configUpdate", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)registerForNotifications {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(update)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
/** Searches the main bundle and the bundle from bundleForClass: info dictionaries for the key and
|
||||
* returns the first result.
|
||||
*
|
||||
* @param key The key to search the info dictionaries for.
|
||||
* @return The first object found in the info dictionary of the main bundle and bundleForClass:.
|
||||
*/
|
||||
- (nullable id)objectForInfoDictionaryKey:(NSString *)key {
|
||||
// If the config infoDictionary has been set to a new dictionary, only use the original dictionary
|
||||
// instead of the new dictionary.
|
||||
if (self.infoDictionary != [NSBundle mainBundle].infoDictionary) {
|
||||
return self.infoDictionary[key]; // nullable.
|
||||
}
|
||||
NSArray<NSBundle *> *bundles = @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ];
|
||||
for (NSBundle *bundle in bundles) {
|
||||
id object = [bundle objectForInfoDictionaryKey:key];
|
||||
if (object) {
|
||||
return object; // nonnull.
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
dispatch_async(self.updateQueue, ^{
|
||||
if (!self.remoteConfigFlags) {
|
||||
[self setupRemoteConfigFlags];
|
||||
}
|
||||
[self.remoteConfigFlags update];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the remote config flags instance based on 3 different factors:
|
||||
* 1. Is the firebase app configured?
|
||||
* 2. Is the remote config source enabled?
|
||||
* 3. If the Remote Config flags instance exists already?
|
||||
*/
|
||||
- (void)setupRemoteConfigFlags {
|
||||
if (!self.remoteConfigFlags && [self.FIRAppClass isDefaultAppConfigured] &&
|
||||
(self.sources & FPRConfigurationSourceRemoteConfig) == FPRConfigurationSourceRemoteConfig) {
|
||||
self.remoteConfigFlags = [FPRRemoteConfigFlags sharedInstance];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Overridden Properties
|
||||
|
||||
- (void)setDataCollectionEnabled:(BOOL)dataCollectionEnabled {
|
||||
[self.userDefaults setBool:dataCollectionEnabled forKey:kFPRConfigCollectionUserPreference];
|
||||
}
|
||||
|
||||
// The data collection flag is determined by this order:
|
||||
// 1. A plist flag for permanently disabling data collection
|
||||
// 2. The runtime flag (GULUserDefaults)
|
||||
// 3. A plist flag for enabling/disabling (overridable)
|
||||
// 4. The global data collection switch from Core.
|
||||
- (BOOL)isDataCollectionEnabled {
|
||||
/**
|
||||
* Perf only works with the default app, so validate it exists then use the value from the global
|
||||
* data collection from the default app as the base value if no other values are set.
|
||||
*/
|
||||
if (![self.FIRAppClass isDefaultAppConfigured]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL dataCollectionPreference = [self.FIRAppClass defaultApp].isDataCollectionDefaultEnabled;
|
||||
|
||||
// Check if data collection is permanently disabled by plist. If so, disable data collection.
|
||||
id dataCollectionDeactivationObject =
|
||||
[self objectForInfoDictionaryKey:kFPRConfigCollectionDeactivationPlistKey];
|
||||
if (dataCollectionDeactivationObject) {
|
||||
BOOL dataCollectionDeactivated = [dataCollectionDeactivationObject boolValue];
|
||||
if (dataCollectionDeactivated) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if the performance collection preference key is available in GULUserDefaults.
|
||||
* If it exists - Just honor that and return that value.
|
||||
* If it does not exist - Check if firebase_performance_collection_enabled exists in Info.plist.
|
||||
* If it exists - honor that and return that value.
|
||||
* If not - return YES stating performance collection is enabled.
|
||||
*/
|
||||
id dataCollectionPreferenceObject =
|
||||
[self.userDefaults objectForKey:kFPRConfigCollectionUserPreference];
|
||||
if (dataCollectionPreferenceObject) {
|
||||
dataCollectionPreference = [dataCollectionPreferenceObject boolValue];
|
||||
} else {
|
||||
dataCollectionPreferenceObject = [self objectForInfoDictionaryKey:kFPRConfigCollectionPlistKey];
|
||||
if (dataCollectionPreferenceObject) {
|
||||
dataCollectionPreference = [dataCollectionPreferenceObject boolValue];
|
||||
}
|
||||
}
|
||||
|
||||
return dataCollectionPreference;
|
||||
}
|
||||
|
||||
- (void)setInstrumentationEnabled:(BOOL)instrumentationEnabled {
|
||||
[self.userDefaults setBool:instrumentationEnabled forKey:kFPRConfigInstrumentationUserPreference];
|
||||
}
|
||||
|
||||
- (BOOL)isInstrumentationEnabled {
|
||||
BOOL instrumentationPreference = YES;
|
||||
|
||||
id instrumentationPreferenceObject =
|
||||
[self.userDefaults objectForKey:kFPRConfigInstrumentationUserPreference];
|
||||
|
||||
/**
|
||||
* Check if the performance instrumentation preference key is available in GULUserDefaults.
|
||||
* If it exists - Just honor that and return that value.
|
||||
* If not - Check if firebase_performance_instrumentation_enabled exists in Info.plist.
|
||||
* If it exists - honor that and return that value.
|
||||
* If not - return YES stating performance instrumentation is enabled.
|
||||
*/
|
||||
if (instrumentationPreferenceObject) {
|
||||
instrumentationPreference = [instrumentationPreferenceObject boolValue];
|
||||
} else {
|
||||
instrumentationPreferenceObject =
|
||||
[self objectForInfoDictionaryKey:kFPRConfigInstrumentationPlistKey];
|
||||
if (instrumentationPreferenceObject) {
|
||||
instrumentationPreference = [instrumentationPreferenceObject boolValue];
|
||||
}
|
||||
}
|
||||
|
||||
return instrumentationPreference;
|
||||
}
|
||||
|
||||
#pragma mark - Fireperf SDK configurations.
|
||||
|
||||
- (BOOL)sdkEnabled {
|
||||
BOOL enabled = YES;
|
||||
if (self.remoteConfigFlags) {
|
||||
enabled = [self.remoteConfigFlags performanceSDKEnabledWithDefaultValue:enabled];
|
||||
}
|
||||
|
||||
// Check if the current version is one of the disabled versions.
|
||||
if ([[self sdkDisabledVersions] containsObject:[NSString stringWithUTF8String:kFPRSDKVersion]]) {
|
||||
enabled = NO;
|
||||
}
|
||||
|
||||
// If there is a plist override, honor that value.
|
||||
// NOTE: PList override should ideally be used only for tests and not for production.
|
||||
id plistObject = [self objectForInfoDictionaryKey:@"firebase_performance_sdk_enabled"];
|
||||
if (plistObject) {
|
||||
enabled = [plistObject boolValue];
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
- (BOOL)diagnosticsEnabled {
|
||||
BOOL enabled = NO;
|
||||
|
||||
/**
|
||||
* Check if the diagnostics preference key is available in GULUserDefaults.
|
||||
* If it exists - Just honor that and return that value.
|
||||
* If not - Check if firebase_performance_instrumentation_enabled exists in Info.plist.
|
||||
* If it exists - honor that and return that value.
|
||||
* If not - return NO stating diagnostics is disabled.
|
||||
*/
|
||||
id diagnosticsEnabledPreferenceObject =
|
||||
[self.userDefaults objectForKey:kFPRDiagnosticsUserPreference];
|
||||
|
||||
if (diagnosticsEnabledPreferenceObject) {
|
||||
enabled = [diagnosticsEnabledPreferenceObject boolValue];
|
||||
} else {
|
||||
id diagnosticsEnabledObject = [self objectForInfoDictionaryKey:kFPRDiagnosticsEnabledPlistKey];
|
||||
if (diagnosticsEnabledObject) {
|
||||
enabled = [diagnosticsEnabledObject boolValue];
|
||||
}
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
- (NSSet<NSString *> *)sdkDisabledVersions {
|
||||
NSMutableSet<NSString *> *disabledVersions = [[NSMutableSet<NSString *> alloc] init];
|
||||
|
||||
if (self.remoteConfigFlags) {
|
||||
NSSet<NSString *> *sdkDisabledVersions =
|
||||
[self.remoteConfigFlags sdkDisabledVersionsWithDefaultValue:[disabledVersions copy]];
|
||||
if (sdkDisabledVersions.count > 0) {
|
||||
[disabledVersions addObjectsFromArray:[sdkDisabledVersions allObjects]];
|
||||
}
|
||||
}
|
||||
|
||||
return [disabledVersions copy];
|
||||
}
|
||||
|
||||
- (int)logSource {
|
||||
/**
|
||||
* Order of preference of returning the log source.
|
||||
* If it is an autopush build (based on environment variable), always return
|
||||
* LogRequest_LogSource_FireperfAutopush (461). If there is a recent value of remote config fetch,
|
||||
* honor that value. If logSource cached value (GULUserDefaults value) exists, honor that.
|
||||
* Fallback to the default value LogRequest_LogSource_Fireperf (462).
|
||||
*/
|
||||
int logSource = 462;
|
||||
|
||||
NSDictionary<NSString *, NSString *> *environment = [NSProcessInfo processInfo].environment;
|
||||
if (environment[@"FPR_AUTOPUSH_ENV"] != nil &&
|
||||
[environment[@"FPR_AUTOPUSH_ENV"] isEqualToString:@"1"]) {
|
||||
logSource = 461;
|
||||
} else {
|
||||
if (self.remoteConfigFlags) {
|
||||
logSource = [self.remoteConfigFlags logSourceWithDefaultValue:462];
|
||||
}
|
||||
}
|
||||
|
||||
return logSource;
|
||||
}
|
||||
|
||||
- (PrewarmDetectionMode)prewarmDetectionMode {
|
||||
PrewarmDetectionMode mode = PrewarmDetectionModeActivePrewarm;
|
||||
if (self.remoteConfigFlags) {
|
||||
mode = [self.remoteConfigFlags getIntValueForFlag:@"fpr_prewarm_detection"
|
||||
defaultValue:(int)mode];
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
#pragma mark - Log sampling configurations.
|
||||
|
||||
- (float)logTraceSamplingRate {
|
||||
float samplingRate = 1.0f;
|
||||
if (self.remoteConfigFlags) {
|
||||
float rcSamplingRate = [self.remoteConfigFlags traceSamplingRateWithDefaultValue:samplingRate];
|
||||
if (rcSamplingRate >= 0) {
|
||||
samplingRate = rcSamplingRate;
|
||||
}
|
||||
}
|
||||
return samplingRate;
|
||||
}
|
||||
|
||||
- (float)logNetworkSamplingRate {
|
||||
float samplingRate = 1.0f;
|
||||
if (self.remoteConfigFlags) {
|
||||
float rcSamplingRate =
|
||||
[self.remoteConfigFlags networkRequestSamplingRateWithDefaultValue:samplingRate];
|
||||
if (rcSamplingRate >= 0) {
|
||||
samplingRate = rcSamplingRate;
|
||||
}
|
||||
}
|
||||
return samplingRate;
|
||||
}
|
||||
|
||||
#pragma mark - Traces rate limiting configurations.
|
||||
|
||||
- (uint32_t)foregroundEventCount {
|
||||
uint32_t eventCount = 300;
|
||||
if (self.remoteConfigFlags) {
|
||||
eventCount =
|
||||
[self.remoteConfigFlags rateLimitTraceCountInForegroundWithDefaultValue:eventCount];
|
||||
}
|
||||
return eventCount;
|
||||
}
|
||||
|
||||
- (uint32_t)foregroundEventTimeLimit {
|
||||
uint32_t timeLimit = 600;
|
||||
if (self.remoteConfigFlags) {
|
||||
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
||||
}
|
||||
|
||||
uint32_t timeLimitInMinutes = timeLimit / 60;
|
||||
return timeLimitInMinutes;
|
||||
}
|
||||
|
||||
- (uint32_t)backgroundEventCount {
|
||||
uint32_t eventCount = 30;
|
||||
if (self.remoteConfigFlags) {
|
||||
eventCount =
|
||||
[self.remoteConfigFlags rateLimitTraceCountInBackgroundWithDefaultValue:eventCount];
|
||||
}
|
||||
return eventCount;
|
||||
}
|
||||
|
||||
- (uint32_t)backgroundEventTimeLimit {
|
||||
uint32_t timeLimit = 600;
|
||||
if (self.remoteConfigFlags) {
|
||||
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
||||
}
|
||||
|
||||
uint32_t timeLimitInMinutes = timeLimit / 60;
|
||||
return timeLimitInMinutes;
|
||||
}
|
||||
|
||||
#pragma mark - Network requests rate limiting configurations.
|
||||
|
||||
- (uint32_t)foregroundNetworkEventCount {
|
||||
uint32_t eventCount = 700;
|
||||
if (self.remoteConfigFlags) {
|
||||
eventCount = [self.remoteConfigFlags
|
||||
rateLimitNetworkRequestCountInForegroundWithDefaultValue:eventCount];
|
||||
}
|
||||
return eventCount;
|
||||
}
|
||||
|
||||
- (uint32_t)foregroundNetworkEventTimeLimit {
|
||||
uint32_t timeLimit = 600;
|
||||
if (self.remoteConfigFlags) {
|
||||
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
||||
}
|
||||
|
||||
uint32_t timeLimitInMinutes = timeLimit / 60;
|
||||
return timeLimitInMinutes;
|
||||
}
|
||||
|
||||
- (uint32_t)backgroundNetworkEventCount {
|
||||
uint32_t eventCount = 70;
|
||||
if (self.remoteConfigFlags) {
|
||||
eventCount = [self.remoteConfigFlags
|
||||
rateLimitNetworkRequestCountInBackgroundWithDefaultValue:eventCount];
|
||||
}
|
||||
return eventCount;
|
||||
}
|
||||
|
||||
- (uint32_t)backgroundNetworkEventTimeLimit {
|
||||
uint32_t timeLimit = 600;
|
||||
if (self.remoteConfigFlags) {
|
||||
timeLimit = [self.remoteConfigFlags rateLimitTimeDurationWithDefaultValue:timeLimit];
|
||||
}
|
||||
|
||||
uint32_t timeLimitInMinutes = timeLimit / 60;
|
||||
return timeLimitInMinutes;
|
||||
}
|
||||
|
||||
#pragma mark - Sessions feature related configurations.
|
||||
|
||||
- (float_t)sessionsSamplingPercentage {
|
||||
float samplingPercentage = 1.0f; // One Percent.
|
||||
if (self.remoteConfigFlags) {
|
||||
float rcSamplingRate =
|
||||
[self.remoteConfigFlags sessionSamplingRateWithDefaultValue:(samplingPercentage / 100)];
|
||||
if (rcSamplingRate >= 0) {
|
||||
samplingPercentage = rcSamplingRate * 100;
|
||||
}
|
||||
}
|
||||
|
||||
id plistObject = [self objectForInfoDictionaryKey:@"sessionsSamplingPercentage"];
|
||||
if (plistObject) {
|
||||
samplingPercentage = [plistObject floatValue];
|
||||
}
|
||||
return samplingPercentage;
|
||||
}
|
||||
|
||||
- (uint32_t)maxSessionLengthInMinutes {
|
||||
uint32_t sessionLengthInMinutes = 240;
|
||||
if (self.remoteConfigFlags) {
|
||||
sessionLengthInMinutes =
|
||||
[self.remoteConfigFlags sessionMaxDurationWithDefaultValue:sessionLengthInMinutes];
|
||||
}
|
||||
|
||||
// If the session max length gets set to 0, default it to 240 minutes.
|
||||
if (sessionLengthInMinutes == 0) {
|
||||
return 240;
|
||||
}
|
||||
return sessionLengthInMinutes;
|
||||
}
|
||||
|
||||
- (uint32_t)cpuSamplingFrequencyInForegroundInMS {
|
||||
uint32_t samplingFrequency = 100;
|
||||
if (self.remoteConfigFlags) {
|
||||
samplingFrequency = [self.remoteConfigFlags
|
||||
sessionGaugeCPUCaptureFrequencyInForegroundWithDefaultValue:samplingFrequency];
|
||||
}
|
||||
return samplingFrequency;
|
||||
}
|
||||
|
||||
- (uint32_t)cpuSamplingFrequencyInBackgroundInMS {
|
||||
uint32_t samplingFrequency = 0;
|
||||
if (self.remoteConfigFlags) {
|
||||
samplingFrequency = [self.remoteConfigFlags
|
||||
sessionGaugeCPUCaptureFrequencyInBackgroundWithDefaultValue:samplingFrequency];
|
||||
}
|
||||
return samplingFrequency;
|
||||
}
|
||||
|
||||
- (uint32_t)memorySamplingFrequencyInForegroundInMS {
|
||||
uint32_t samplingFrequency = 100;
|
||||
if (self.remoteConfigFlags) {
|
||||
samplingFrequency = [self.remoteConfigFlags
|
||||
sessionGaugeMemoryCaptureFrequencyInForegroundWithDefaultValue:samplingFrequency];
|
||||
}
|
||||
return samplingFrequency;
|
||||
}
|
||||
|
||||
- (uint32_t)memorySamplingFrequencyInBackgroundInMS {
|
||||
uint32_t samplingFrequency = 0;
|
||||
if (self.remoteConfigFlags) {
|
||||
samplingFrequency = [self.remoteConfigFlags
|
||||
sessionGaugeMemoryCaptureFrequencyInBackgroundWithDefaultValue:samplingFrequency];
|
||||
}
|
||||
return samplingFrequency;
|
||||
}
|
||||
|
||||
@end
|
||||
114
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags+Private.h
generated
Normal file
114
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags+Private.h
generated
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h"
|
||||
|
||||
#import "FirebaseRemoteConfig/Sources/Private/FIRRemoteConfig_Private.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class GULUserDefaults;
|
||||
|
||||
static NSString *const kFPRConfigPrefix = @"com.fireperf";
|
||||
|
||||
/** Interval at which the configurations can be fetched. Specified in seconds. */
|
||||
static NSInteger const kFPRConfigFetchIntervalInSeconds = 12 * 60 * 60;
|
||||
|
||||
/** Interval after which the configurations can be fetched. Specified in seconds. */
|
||||
static NSInteger const kFPRMinAppStartConfigFetchDelayInSeconds = 5;
|
||||
|
||||
/** This extension should only be used for testing. */
|
||||
@interface FPRRemoteConfigFlags ()
|
||||
|
||||
/** @brief Instance of remote config used for firebase performance namespace. */
|
||||
@property(nonatomic) FIRRemoteConfig *fprRemoteConfig;
|
||||
|
||||
/** @brief Last activated time of the configurations. */
|
||||
@property(atomic, nullable) NSDate *lastFetchedTime;
|
||||
|
||||
/** @brief User defaults used for caching. */
|
||||
@property(nonatomic) GULUserDefaults *userDefaults;
|
||||
|
||||
/** @brief Last activated time of the configurations. */
|
||||
@property(nonatomic) NSDate *applicationStartTime;
|
||||
|
||||
/** @brief Number of seconds delayed until the first config is made during app start. */
|
||||
@property(nonatomic) NSTimeInterval appStartConfigFetchDelayInSeconds;
|
||||
|
||||
/** @brief Status of the last remote config fetch. */
|
||||
@property(nonatomic) FIRRemoteConfigFetchStatus lastFetchStatus;
|
||||
|
||||
/**
|
||||
* Creates an instance of FPRRemoteConfigFlags.
|
||||
*
|
||||
* @param config RemoteConfig object to be used for configuration management.
|
||||
* @return Instance of remote config.
|
||||
*/
|
||||
- (instancetype)initWithRemoteConfig:(FIRRemoteConfig *)config NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
#pragma mark - Config fetch methods
|
||||
|
||||
/**
|
||||
* Gets and returns the string value for the provided remote config flag. If there are no values
|
||||
* returned from remote config, default value will be returned.
|
||||
* @param flagName Name of the flag for which the value needs to be fetched from RC.
|
||||
* @param defaultValue Default value that will be returned if no value is fetched from RC.
|
||||
*
|
||||
* @return string value for the flag from RC if available. Default value, otherwise.
|
||||
*/
|
||||
- (NSString *)getStringValueForFlag:(NSString *)flagName defaultValue:(NSString *)defaultValue;
|
||||
|
||||
/**
|
||||
* Gets and returns the int value for the provided remote config flag. If there are no values
|
||||
* returned from remote config, default value will be returned.
|
||||
* @param flagName Name of the flag for which the value needs to be fetched from RC.
|
||||
* @param defaultValue Default value that will be returned if no value is fetched from RC.
|
||||
*
|
||||
* @return Int value for the flag from RC if available. Default value, otherwise.
|
||||
*/
|
||||
- (int)getIntValueForFlag:(NSString *)flagName defaultValue:(int)defaultValue;
|
||||
|
||||
/**
|
||||
* Gets and returns the float value for the provided remote config flag. If there are no values
|
||||
* returned from remote config, default value will be returned.
|
||||
* @param flagName Name of the flag for which the value needs to be fetched from RC.
|
||||
* @param defaultValue Default value that will be returned if no value is fetched from RC.
|
||||
*
|
||||
* @return Float value for the flag from RC if available. Default value, otherwise.
|
||||
*/
|
||||
- (float)getFloatValueForFlag:(NSString *)flagName defaultValue:(float)defaultValue;
|
||||
|
||||
/**
|
||||
* Gets and returns the boolean value for the provided remote config flag. If there are no values
|
||||
* returned from remote config, default value will be returned.
|
||||
* @param flagName Name of the flag for which the value needs to be fetched from RC.
|
||||
* @param defaultValue Default value that will be returned if no value is fetched from RC.
|
||||
*
|
||||
* @return Bool value for the flag from RC if available. Default value, otherwise.
|
||||
*/
|
||||
- (BOOL)getBoolValueForFlag:(NSString *)flagName defaultValue:(BOOL)defaultValue;
|
||||
|
||||
/**
|
||||
* Caches the remote config values.
|
||||
*/
|
||||
- (void)cacheConfigValues;
|
||||
|
||||
/**
|
||||
* Reset (Clears) all the remote config keys and values that were cached.
|
||||
*/
|
||||
- (void)resetCache;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
203
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h
generated
Normal file
203
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h
generated
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* Configuration flags retrieved from Firebase Remote Configuration.
|
||||
*/
|
||||
@interface FPRRemoteConfigFlags : NSObject
|
||||
|
||||
/**
|
||||
* The name of the name space for which the remote config flags are fetched.
|
||||
*/
|
||||
@property(nonatomic, readonly, nonnull) NSString *remoteConfigNamespace;
|
||||
|
||||
#pragma mark - Instance methods
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Singleton instance of Firebase Remote Configuration flags. */
|
||||
+ (nullable instancetype)sharedInstance;
|
||||
|
||||
/**
|
||||
* Initiate a fetch of the flags from Firebase Remote Configuration and updates the configurations
|
||||
* at the end of the fetch.
|
||||
*
|
||||
* @note This method is throttled to initiate a fetch once in 12 hours. So, calling this method does
|
||||
* not guarantee a fetch from Firebase Remote Config.
|
||||
*/
|
||||
- (void)update;
|
||||
|
||||
#pragma mark - General configs.
|
||||
|
||||
/**
|
||||
* Returns if performance SDK is enabled.
|
||||
* Name in remote config: "fpr_enabled".
|
||||
*
|
||||
* @param sdkEnabled Default value to be returned if values does not exist in remote config.
|
||||
* @return Specifies if SDK should be enabled or not.
|
||||
*/
|
||||
- (BOOL)performanceSDKEnabledWithDefaultValue:(BOOL)sdkEnabled;
|
||||
|
||||
/**
|
||||
* Returns set of versions on which SDK is disabled.
|
||||
* Name in remote config: "fpr_disabled_ios_versions".
|
||||
*
|
||||
* @param sdkVersions Default value to be returned if values does not exist in remote config.
|
||||
* @return SDK versions list where the SDK has to be disabled.
|
||||
*/
|
||||
- (nullable NSSet<NSString *> *)sdkDisabledVersionsWithDefaultValue:
|
||||
(nullable NSSet<NSString *> *)sdkVersions;
|
||||
|
||||
/**
|
||||
* Returns the log source against which the events will be recorded.
|
||||
* Name in remote config: "fpr_log_source"
|
||||
*
|
||||
* @param logSource Default value to be returned if values does not exist in remote config.
|
||||
* @return Log source towards which the events would be logged.
|
||||
*/
|
||||
- (int)logSourceWithDefaultValue:(int)logSource;
|
||||
|
||||
#pragma mark - Rate limiting related configs.
|
||||
|
||||
/**
|
||||
* Returns the time limit for which the event are measured against. Measured in seconds.
|
||||
* Name in remote config: "fpr_rl_time_limit_sec"
|
||||
*
|
||||
* @param durationInSeconds Default value to be returned if values does not exist in remote config.
|
||||
* @return Time limit used for rate limiting in seconds.
|
||||
*/
|
||||
- (int)rateLimitTimeDurationWithDefaultValue:(int)durationInSeconds;
|
||||
|
||||
/**
|
||||
* Returns the number of trace events that are allowed when the app is in foreground.
|
||||
* Name in remote config: "fpr_rl_trace_event_count_fg"
|
||||
*
|
||||
* @param eventCount Default value to be returned if values does not exist in remote config.
|
||||
* @return Trace count limit when the app is in foreground.
|
||||
*/
|
||||
- (int)rateLimitTraceCountInForegroundWithDefaultValue:(int)eventCount;
|
||||
|
||||
/**
|
||||
* Returns the number of trace events that are allowed when the app is in background.
|
||||
* Name in remote config: "fpr_rl_trace_event_count_bg"
|
||||
*
|
||||
* @param eventCount Default value to be returned if values does not exist in remote config.
|
||||
* @return Trace count limit when the app is in background.
|
||||
*/
|
||||
- (int)rateLimitTraceCountInBackgroundWithDefaultValue:(int)eventCount;
|
||||
|
||||
/**
|
||||
* Returns the number of network trace events that are allowed when the app is in foreground.
|
||||
* Name in remote config: "fpr_rl_network_request_event_count_fg"
|
||||
*
|
||||
* @param eventCount Default value to be returned if values does not exist in remote config.
|
||||
* @return Network request count limit when the app is in foreground.
|
||||
*/
|
||||
- (int)rateLimitNetworkRequestCountInForegroundWithDefaultValue:(int)eventCount;
|
||||
|
||||
/**
|
||||
* Returns the number of network trace events that are allowed when the app is in background.
|
||||
* Name in remote config: "fpr_rl_network_request_event_count_bg"
|
||||
*
|
||||
* @param eventCount Default value to be returned if values does not exist in remote config.
|
||||
* @return Network request count limit when the app is in background.
|
||||
*/
|
||||
- (int)rateLimitNetworkRequestCountInBackgroundWithDefaultValue:(int)eventCount;
|
||||
|
||||
#pragma mark - Sampling related configs.
|
||||
|
||||
/**
|
||||
* Returns the sampling rate for traces. A value of 1 means all the events must be sent to the
|
||||
* backend. A value of 0 means, no data must be sent. Range [0-1]. A value of -1 means the value is
|
||||
* not found.
|
||||
* Name in remote config: "fpr_vc_trace_sampling_rate"
|
||||
*
|
||||
* @param samplingRate Default value to be returned if values does not exist in remote config.
|
||||
* @return Sampling rate used for the number of traces.
|
||||
*/
|
||||
- (float)traceSamplingRateWithDefaultValue:(float)samplingRate;
|
||||
|
||||
/**
|
||||
* Returns the sampling rate for network requests. A value of 1 means all the events must be sent to
|
||||
* the backend. A value of 0 means, no data must be sent. Range [0-1]. A value of -1 means the value
|
||||
* is not found.
|
||||
* Name in remote config: "fpr_vc_network_request_sampling_rate"
|
||||
*
|
||||
* @param samplingRate Default value to be returned if values does not exist in remote config.
|
||||
* @return Sampling rate used for the number of network request traces.
|
||||
*/
|
||||
- (float)networkRequestSamplingRateWithDefaultValue:(float)samplingRate;
|
||||
|
||||
#pragma mark - Session related configs.
|
||||
|
||||
/**
|
||||
* Returns the sampling rate for sessions. A value of 1 means all the events must be sent to the
|
||||
* backend. A value of 0 means, no data must be sent. Range [0-1]. A value of -1 means the value is
|
||||
* not found.
|
||||
* Name in remote config: "fpr_vc_session_sampling_rate"
|
||||
*
|
||||
* @param samplingRate Default value to be returned if values does not exist in remote config.
|
||||
* @return Session sampling rate used for the number of sessions generated.
|
||||
*/
|
||||
- (float)sessionSamplingRateWithDefaultValue:(float)samplingRate;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which CPU usage is measured when the app is in foreground. Measured in
|
||||
* milliseconds. Name in remote config: "fpr_session_gauge_cpu_capture_frequency_fg_ms"
|
||||
*
|
||||
* @param defaultFrequency Default value to be returned if values does not exist in remote config.
|
||||
* @return Frequency at which CPU information is captured when app is in foreground.
|
||||
*/
|
||||
- (int)sessionGaugeCPUCaptureFrequencyInForegroundWithDefaultValue:(int)defaultFrequency;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which CPU usage is measured when the app is in background. Measured in
|
||||
* milliseconds. Name in remote config: "fpr_session_gauge_cpu_capture_frequency_bg_ms"
|
||||
*
|
||||
* @param defaultFrequency Default value to be returned if values does not exist in remote config.
|
||||
* @return Frequency at which CPU information is captured when app is in background.
|
||||
*/
|
||||
- (int)sessionGaugeCPUCaptureFrequencyInBackgroundWithDefaultValue:(int)defaultFrequency;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which memory usage is measured when the app is in foreground. Measured
|
||||
* in milliseconds. Name in remote config: "fpr_session_gauge_memory_capture_frequency_fg_ms"
|
||||
*
|
||||
* @param defaultFrequency Default value to be returned if values does not exist in remote config.
|
||||
* @return Frequency at which memory information is captured when app is in foreground.
|
||||
*/
|
||||
- (int)sessionGaugeMemoryCaptureFrequencyInForegroundWithDefaultValue:(int)defaultFrequency;
|
||||
|
||||
/**
|
||||
* Returns the frequency at which memory usage is measured when the app is in background. Measured
|
||||
* in milliseconds. Name in remote config: "fpr_session_gauge_memory_capture_frequency_bg_ms"
|
||||
*
|
||||
* @param defaultFrequency Default value to be returned if values does not exist in remote config.
|
||||
* @return Frequency at which memory information is captured when app is in background.
|
||||
*/
|
||||
- (int)sessionGaugeMemoryCaptureFrequencyInBackgroundWithDefaultValue:(int)defaultFrequency;
|
||||
|
||||
/**
|
||||
* Returns the maximum allowed duration for the length of a session. Measured in minutes.
|
||||
* Name in remote config: "fpr_session_max_duration_min"
|
||||
*
|
||||
* @param maxDurationInMinutes Default value to be returned if values does not exist in remote
|
||||
* config.
|
||||
* @return Duration for which a sessions can be active.
|
||||
*/
|
||||
- (int)sessionMaxDurationWithDefaultValue:(int)maxDurationInMinutes;
|
||||
|
||||
@end
|
||||
346
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.m
generated
Normal file
346
Pods/FirebasePerformance/FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.m
generated
Normal file
@ -0,0 +1,346 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <GoogleUtilities/GULUserDefaults.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags+Private.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
|
||||
|
||||
#define ONE_DAY_SECONDS 24 * 60 * 60
|
||||
|
||||
static NSDate *FPRAppStartTime = nil;
|
||||
|
||||
typedef NS_ENUM(NSInteger, FPRConfigValueType) {
|
||||
// Config value type String.
|
||||
FPRConfigValueTypeString,
|
||||
// Config value type Bool.
|
||||
FPRConfigValueTypeBool,
|
||||
// Config value type Integer.
|
||||
FPRConfigValueTypeInteger,
|
||||
// Config value type Float.
|
||||
FPRConfigValueTypeFloat,
|
||||
};
|
||||
|
||||
@interface FPRRemoteConfigFlags ()
|
||||
|
||||
/** @brief Represents if a fetch is currently in progress. */
|
||||
@property(atomic) BOOL fetchInProgress;
|
||||
|
||||
/** @brief Dictionary of different config keys and value types. */
|
||||
@property(nonatomic) NSDictionary<NSString *, NSNumber *> *configKeys;
|
||||
|
||||
/** @brief Last time the configs were cached. */
|
||||
@property(nonatomic) NSDate *lastCachedTime;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRRemoteConfigFlags
|
||||
|
||||
+ (void)load {
|
||||
FPRAppStartTime = [NSDate date];
|
||||
}
|
||||
|
||||
+ (nullable instancetype)sharedInstance {
|
||||
static FPRRemoteConfigFlags *instance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
FIRRemoteConfig *rc = [FIRRemoteConfig remoteConfigWithFIRNamespace:@"fireperf"
|
||||
app:[FIRApp defaultApp]];
|
||||
instance = [[FPRRemoteConfigFlags alloc] initWithRemoteConfig:rc];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)initWithRemoteConfig:(FIRRemoteConfig *)config {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_fprRemoteConfig = config;
|
||||
_userDefaults = [FPRConfigurations sharedInstance].userDefaults;
|
||||
self.fetchInProgress = NO;
|
||||
|
||||
// Set the overall delay to 5+random(25) making the config fetch delay at a max of 30 seconds
|
||||
self.applicationStartTime = FPRAppStartTime;
|
||||
self.appStartConfigFetchDelayInSeconds =
|
||||
kFPRMinAppStartConfigFetchDelayInSeconds + arc4random_uniform(25);
|
||||
|
||||
NSMutableDictionary<NSString *, NSNumber *> *keysToCache =
|
||||
[[NSMutableDictionary<NSString *, NSNumber *> alloc] init];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger) forKey:@"fpr_log_source"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeBool) forKey:@"fpr_enabled"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeString) forKey:@"fpr_disabled_ios_versions"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger) forKey:@"fpr_rl_time_limit_sec"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger) forKey:@"fpr_rl_trace_event_count_fg"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger) forKey:@"fpr_rl_trace_event_count_bg"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger)
|
||||
forKey:@"fpr_rl_network_request_event_count_fg"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger)
|
||||
forKey:@"fpr_rl_network_request_event_count_bg"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeFloat) forKey:@"fpr_vc_trace_sampling_rate"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeFloat)
|
||||
forKey:@"fpr_vc_network_request_sampling_rate"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeFloat) forKey:@"fpr_vc_session_sampling_rate"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger)
|
||||
forKey:@"fpr_session_gauge_cpu_capture_frequency_fg_ms"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger)
|
||||
forKey:@"fpr_session_gauge_cpu_capture_frequency_bg_ms"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger)
|
||||
forKey:@"fpr_session_gauge_memory_capture_frequency_fg_ms"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger)
|
||||
forKey:@"fpr_session_gauge_memory_capture_frequency_bg_ms"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger) forKey:@"fpr_session_max_duration_min"];
|
||||
[keysToCache setObject:@(FPRConfigValueTypeInteger) forKey:@"fpr_prewarm_detection"];
|
||||
self.configKeys = [keysToCache copy];
|
||||
|
||||
[self update];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
// If a fetch is already happening, do not attempt a fetch.
|
||||
if (self.fetchInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSTimeInterval timeIntervalSinceLastFetch =
|
||||
[self.fprRemoteConfig.lastFetchTime timeIntervalSinceNow];
|
||||
NSTimeInterval timeSinceAppStart = [self.applicationStartTime timeIntervalSinceNow];
|
||||
if ((ABS(timeSinceAppStart) > self.appStartConfigFetchDelayInSeconds) &&
|
||||
(!self.fprRemoteConfig.lastFetchTime ||
|
||||
ABS(timeIntervalSinceLastFetch) > kFPRConfigFetchIntervalInSeconds)) {
|
||||
self.fetchInProgress = YES;
|
||||
[self.fprRemoteConfig
|
||||
fetchAndActivateWithCompletionHandler:^(FIRRemoteConfigFetchAndActivateStatus status,
|
||||
NSError *_Nullable error) {
|
||||
self.lastFetchStatus = self.fprRemoteConfig.lastFetchStatus;
|
||||
if (status == FIRRemoteConfigFetchAndActivateStatusError) {
|
||||
FPRLogError(kFPRConfigurationFetchFailure, @"Unable to fetch configurations.");
|
||||
} else {
|
||||
self.lastFetchedTime = self.fprRemoteConfig.lastFetchTime;
|
||||
// If a fetch was successful,
|
||||
// 1. Clear the old cache
|
||||
[self resetCache];
|
||||
// 2. Cache the new config values
|
||||
[self cacheConfigValues];
|
||||
}
|
||||
self.fetchInProgress = NO;
|
||||
}];
|
||||
} else if (self.fprRemoteConfig.lastFetchTime) {
|
||||
// Update the last fetched time to know that remote config fetch has happened in the past.
|
||||
self.lastFetchedTime = self.fprRemoteConfig.lastFetchTime;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Util methods.
|
||||
|
||||
- (void)resetCache {
|
||||
[self.configKeys
|
||||
enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *valueType, BOOL *stop) {
|
||||
NSString *cacheKey = [NSString stringWithFormat:@"%@.%@", kFPRConfigPrefix, key];
|
||||
[self.userDefaults removeObjectForKey:cacheKey];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)cacheConfigValues {
|
||||
[self.configKeys
|
||||
enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *valueType, BOOL *stop) {
|
||||
FIRRemoteConfigValue *rcValue = [self.fprRemoteConfig configValueForKey:key];
|
||||
|
||||
// Cache only values that comes from remote.
|
||||
if (rcValue != nil && rcValue.source == FIRRemoteConfigSourceRemote) {
|
||||
FPRConfigValueType configValueType = [valueType integerValue];
|
||||
NSString *cacheKey = [NSString stringWithFormat:@"%@.%@", kFPRConfigPrefix, key];
|
||||
|
||||
if (configValueType == FPRConfigValueTypeInteger) {
|
||||
NSInteger integerValue = [[rcValue numberValue] integerValue];
|
||||
[self.userDefaults setInteger:integerValue forKey:cacheKey];
|
||||
} else if (configValueType == FPRConfigValueTypeFloat) {
|
||||
float floatValue = [[rcValue numberValue] floatValue];
|
||||
[self.userDefaults setFloat:floatValue forKey:cacheKey];
|
||||
} else if (configValueType == FPRConfigValueTypeBool) {
|
||||
BOOL boolValue = [rcValue boolValue];
|
||||
[self.userDefaults setBool:boolValue forKey:cacheKey];
|
||||
} else if (configValueType == FPRConfigValueTypeString) {
|
||||
NSString *stringValue = [rcValue stringValue];
|
||||
[self.userDefaults setObject:stringValue forKey:cacheKey];
|
||||
}
|
||||
|
||||
self.lastCachedTime = [NSDate date];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (id)cachedValueForConfigFlag:(NSString *)configFlag {
|
||||
// If the cached value is too old, return nil.
|
||||
if (ABS([self.lastFetchedTime timeIntervalSinceNow]) > 7 * ONE_DAY_SECONDS) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *cacheKey = [NSString stringWithFormat:@"%@.%@", kFPRConfigPrefix, configFlag];
|
||||
id cachedValueObject = [self.userDefaults objectForKey:cacheKey];
|
||||
return cachedValueObject;
|
||||
}
|
||||
|
||||
#pragma mark - Config value fetch methods.
|
||||
|
||||
- (NSString *)getStringValueForFlag:(NSString *)flagName defaultValue:(NSString *)defaultValue {
|
||||
id cachedValueObject = [self cachedValueForConfigFlag:flagName];
|
||||
if ([cachedValueObject isKindOfClass:[NSString class]]) {
|
||||
return (NSString *)cachedValueObject;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
- (int)getIntValueForFlag:(NSString *)flagName defaultValue:(int)defaultValue {
|
||||
id cachedValueObject = [self cachedValueForConfigFlag:flagName];
|
||||
if (cachedValueObject) {
|
||||
return [cachedValueObject intValue];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
- (float)getFloatValueForFlag:(NSString *)flagName defaultValue:(float)defaultValue {
|
||||
id cachedValueObject = [self cachedValueForConfigFlag:flagName];
|
||||
if (cachedValueObject) {
|
||||
return [cachedValueObject floatValue];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
- (BOOL)getBoolValueForFlag:(NSString *)flagName defaultValue:(BOOL)defaultValue {
|
||||
id cachedValueObject = [self cachedValueForConfigFlag:flagName];
|
||||
if (cachedValueObject) {
|
||||
return [cachedValueObject boolValue];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
#pragma mark - Configuration methods.
|
||||
|
||||
- (int)logSourceWithDefaultValue:(int)logSource {
|
||||
return [self getIntValueForFlag:@"fpr_log_source" defaultValue:logSource];
|
||||
}
|
||||
|
||||
- (BOOL)performanceSDKEnabledWithDefaultValue:(BOOL)sdkEnabled {
|
||||
/* Order of preference:
|
||||
* 1. If remote config fetch was a failure, return NO.
|
||||
* 2. If the fetch was successful, but RC does not have the value (not a remote value),
|
||||
* return YES.
|
||||
* 3. Else, use the value from RC.
|
||||
*/
|
||||
|
||||
if (self.lastFetchStatus == FIRRemoteConfigFetchStatusFailure) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self getBoolValueForFlag:@"fpr_enabled" defaultValue:sdkEnabled];
|
||||
}
|
||||
|
||||
- (NSSet<NSString *> *)sdkDisabledVersionsWithDefaultValue:(NSSet<NSString *> *)sdkVersions {
|
||||
NSMutableSet<NSString *> *disabledVersions = [[NSMutableSet<NSString *> alloc] init];
|
||||
|
||||
NSString *sdkVersionsString = [[self getStringValueForFlag:@"fpr_disabled_ios_versions"
|
||||
defaultValue:@""]
|
||||
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
if (sdkVersionsString.length > 0) {
|
||||
NSArray<NSString *> *sdkVersionStrings = [sdkVersionsString componentsSeparatedByString:@";"];
|
||||
for (NSString *sdkVersionString in sdkVersionStrings) {
|
||||
NSString *trimmedString = [sdkVersionString
|
||||
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
if (trimmedString.length > 0) {
|
||||
[disabledVersions addObject:trimmedString];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return sdkVersions;
|
||||
}
|
||||
|
||||
return [disabledVersions copy];
|
||||
}
|
||||
|
||||
#pragma mark - Rate limiting flags
|
||||
|
||||
- (int)rateLimitTimeDurationWithDefaultValue:(int)durationInSeconds {
|
||||
return [self getIntValueForFlag:@"fpr_rl_time_limit_sec" defaultValue:durationInSeconds];
|
||||
}
|
||||
|
||||
- (int)rateLimitTraceCountInForegroundWithDefaultValue:(int)eventCount {
|
||||
return [self getIntValueForFlag:@"fpr_rl_trace_event_count_fg" defaultValue:eventCount];
|
||||
}
|
||||
|
||||
- (int)rateLimitTraceCountInBackgroundWithDefaultValue:(int)eventCount {
|
||||
return [self getIntValueForFlag:@"fpr_rl_trace_event_count_bg" defaultValue:eventCount];
|
||||
}
|
||||
|
||||
- (int)rateLimitNetworkRequestCountInForegroundWithDefaultValue:(int)eventCount {
|
||||
return [self getIntValueForFlag:@"fpr_rl_network_request_event_count_fg" defaultValue:eventCount];
|
||||
}
|
||||
|
||||
- (int)rateLimitNetworkRequestCountInBackgroundWithDefaultValue:(int)eventCount {
|
||||
return [self getIntValueForFlag:@"fpr_rl_network_request_event_count_bg" defaultValue:eventCount];
|
||||
}
|
||||
|
||||
#pragma mark - Sampling flags
|
||||
|
||||
- (float)traceSamplingRateWithDefaultValue:(float)samplingRate {
|
||||
return [self getFloatValueForFlag:@"fpr_vc_trace_sampling_rate" defaultValue:samplingRate];
|
||||
}
|
||||
|
||||
- (float)networkRequestSamplingRateWithDefaultValue:(float)samplingRate {
|
||||
return [self getFloatValueForFlag:@"fpr_vc_network_request_sampling_rate"
|
||||
defaultValue:samplingRate];
|
||||
}
|
||||
|
||||
#pragma mark - Session flags
|
||||
|
||||
- (float)sessionSamplingRateWithDefaultValue:(float)samplingRate {
|
||||
return [self getFloatValueForFlag:@"fpr_vc_session_sampling_rate" defaultValue:samplingRate];
|
||||
}
|
||||
|
||||
- (int)sessionGaugeCPUCaptureFrequencyInForegroundWithDefaultValue:(int)defaultFrequency {
|
||||
return [self getIntValueForFlag:@"fpr_session_gauge_cpu_capture_frequency_fg_ms"
|
||||
defaultValue:defaultFrequency];
|
||||
}
|
||||
|
||||
- (int)sessionGaugeCPUCaptureFrequencyInBackgroundWithDefaultValue:(int)defaultFrequency {
|
||||
return [self getIntValueForFlag:@"fpr_session_gauge_cpu_capture_frequency_bg_ms"
|
||||
defaultValue:defaultFrequency];
|
||||
}
|
||||
|
||||
- (int)sessionGaugeMemoryCaptureFrequencyInForegroundWithDefaultValue:(int)defaultFrequency {
|
||||
return [self getIntValueForFlag:@"fpr_session_gauge_memory_capture_frequency_fg_ms"
|
||||
defaultValue:defaultFrequency];
|
||||
}
|
||||
|
||||
- (int)sessionGaugeMemoryCaptureFrequencyInBackgroundWithDefaultValue:(int)defaultFrequency {
|
||||
return [self getIntValueForFlag:@"fpr_session_gauge_memory_capture_frequency_bg_ms"
|
||||
defaultValue:defaultFrequency];
|
||||
}
|
||||
|
||||
- (int)sessionMaxDurationWithDefaultValue:(int)maxDurationInMinutes {
|
||||
return [self getIntValueForFlag:@"fpr_session_max_duration_min"
|
||||
defaultValue:maxDurationInMinutes];
|
||||
}
|
||||
|
||||
@end
|
||||
27
Pods/FirebasePerformance/FirebasePerformance/Sources/FIRPerformance+Internal.h
generated
Normal file
27
Pods/FirebasePerformance/FirebasePerformance/Sources/FIRPerformance+Internal.h
generated
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
|
||||
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformanceAttributable.h"
|
||||
|
||||
/**
|
||||
* Extension that is added on top of the class FIRPerformance to make certain methods used
|
||||
* internally within the SDK, but not public facing. A category could be ideal, but Firebase
|
||||
* recommends not using categories as that mandates including -ObjC flag for build which is an extra
|
||||
* step for the developer.
|
||||
*/
|
||||
|
||||
@interface FIRPerformance (Attributable) <FIRPerformanceAttributable>
|
||||
|
||||
@end
|
||||
156
Pods/FirebasePerformance/FirebasePerformance/Sources/FIRPerformance.m
generated
Normal file
156
Pods/FirebasePerformance/FirebasePerformance/Sources/FIRPerformance.m
generated
Normal file
@ -0,0 +1,156 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
|
||||
#import "FirebasePerformance/Sources/FIRPerformance+Internal.h"
|
||||
#import "FirebasePerformance/Sources/FIRPerformance_Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/FPRClient+Private.h"
|
||||
#import "FirebasePerformance/Sources/FPRClient.h"
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
#import "FirebasePerformance/Sources/FPRDataUtils.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
|
||||
|
||||
static NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf";
|
||||
|
||||
@implementation FIRPerformance
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static FIRPerformance *firebasePerformance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
firebasePerformance = [[FIRPerformance alloc] init];
|
||||
});
|
||||
return firebasePerformance;
|
||||
}
|
||||
|
||||
+ (FIRTrace *)startTraceWithName:(NSString *)name {
|
||||
FIRTrace *trace = [[self sharedInstance] traceWithName:name];
|
||||
[trace start];
|
||||
return trace;
|
||||
}
|
||||
|
||||
- (FIRTrace *)traceWithName:(NSString *)name {
|
||||
if (![self isPerfConfigured]) {
|
||||
FPRLogError(kFPRTraceNotCreated, @"Failed creating trace %@. Firebase is not configured.",
|
||||
name);
|
||||
[NSException raise:kFirebasePerfErrorDomain
|
||||
format:@"The default Firebase app has not yet been configured. Add "
|
||||
@"`FirebaseApp.configure()` to your application initialization."];
|
||||
return nil;
|
||||
}
|
||||
FIRTrace *trace = [[FIRTrace alloc] initWithName:name];
|
||||
return trace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the SDK has been successfully configured.
|
||||
*
|
||||
* @return YES if SDK is configured successfully, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isPerfConfigured {
|
||||
return self.fprClient.isConfigured;
|
||||
}
|
||||
|
||||
#pragma mark - Internal methods
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_customAttributes = [[NSMutableDictionary<NSString *, NSString *> alloc] init];
|
||||
_customAttributesSerialQueue =
|
||||
dispatch_queue_create("com.google.perf.customAttributes", DISPATCH_QUEUE_SERIAL);
|
||||
_fprClient = [FPRClient sharedInstance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isDataCollectionEnabled {
|
||||
return [FPRConfigurations sharedInstance].isDataCollectionEnabled;
|
||||
}
|
||||
|
||||
- (void)setDataCollectionEnabled:(BOOL)dataCollectionEnabled {
|
||||
[[FPRConfigurations sharedInstance] setDataCollectionEnabled:dataCollectionEnabled];
|
||||
}
|
||||
|
||||
- (BOOL)isInstrumentationEnabled {
|
||||
return self.fprClient.isSwizzled || [FPRConfigurations sharedInstance].isInstrumentationEnabled;
|
||||
}
|
||||
|
||||
- (void)setInstrumentationEnabled:(BOOL)instrumentationEnabled {
|
||||
[[FPRConfigurations sharedInstance] setInstrumentationEnabled:instrumentationEnabled];
|
||||
if (instrumentationEnabled) {
|
||||
[self.fprClient checkAndStartInstrumentation];
|
||||
} else {
|
||||
if (self.fprClient.isSwizzled) {
|
||||
FPRLogError(kFPRInstrumentationDisabledAfterConfigure,
|
||||
@"Failed to disable instrumentation because Firebase Performance has already "
|
||||
@"been configured. It will be disabled when the app restarts.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Custom attributes related methods
|
||||
|
||||
- (NSDictionary<NSString *, NSString *> *)attributes {
|
||||
return [self.customAttributes copy];
|
||||
}
|
||||
|
||||
- (void)setValue:(NSString *)value forAttribute:(nonnull NSString *)attribute {
|
||||
NSString *validatedName = FPRReservableAttributeName(attribute);
|
||||
NSString *validatedValue = FPRValidatedAttributeValue(value);
|
||||
|
||||
BOOL canAddAttribute = YES;
|
||||
if (validatedName == nil) {
|
||||
FPRLogError(kFPRAttributeNoName,
|
||||
@"Failed to initialize because of a nil or zero length attribute name.");
|
||||
canAddAttribute = NO;
|
||||
}
|
||||
|
||||
if (validatedValue == nil) {
|
||||
FPRLogError(kFPRAttributeNoValue,
|
||||
@"Failed to initialize because of a nil or zero length attribute value.");
|
||||
canAddAttribute = NO;
|
||||
}
|
||||
|
||||
if (self.customAttributes.allKeys.count >= kFPRMaxGlobalCustomAttributesCount) {
|
||||
FPRLogError(kFPRMaxAttributesReached,
|
||||
@"Only %d attributes allowed. Already reached maximum attribute count.",
|
||||
kFPRMaxGlobalCustomAttributesCount);
|
||||
canAddAttribute = NO;
|
||||
}
|
||||
|
||||
if (canAddAttribute) {
|
||||
// Ensure concurrency during update of attributes.
|
||||
dispatch_sync(self.customAttributesSerialQueue, ^{
|
||||
self.customAttributes[validatedName] = validatedValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)valueForAttribute:(NSString *)attribute {
|
||||
// TODO(b/175053654): Should this be happening on the serial queue for thread safety?
|
||||
return self.customAttributes[attribute];
|
||||
}
|
||||
|
||||
- (void)removeAttribute:(NSString *)attribute {
|
||||
[self.customAttributes removeObjectForKey:attribute];
|
||||
}
|
||||
|
||||
@end
|
||||
33
Pods/FirebasePerformance/FirebasePerformance/Sources/FIRPerformance_Private.h
generated
Normal file
33
Pods/FirebasePerformance/FirebasePerformance/Sources/FIRPerformance_Private.h
generated
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRClient.h"
|
||||
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
|
||||
|
||||
/**
|
||||
* Extension that is added on top of the class FIRPerformances to make the private properties
|
||||
* visible between the implementation file and the unit tests.
|
||||
*/
|
||||
@interface FIRPerformance ()
|
||||
|
||||
/** Custom attribute managed internally. */
|
||||
@property(nonatomic) NSMutableDictionary<NSString *, NSString *> *customAttributes;
|
||||
|
||||
/** Serial queue to manage mutation of attributes. */
|
||||
@property(nonatomic, readwrite) dispatch_queue_t customAttributesSerialQueue;
|
||||
|
||||
/** Client object used for checking the status of the performance SDK before generating events. */
|
||||
@property(nonatomic, readwrite) FPRClient *fprClient;
|
||||
|
||||
@end
|
||||
75
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRClient+Private.h
generated
Normal file
75
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRClient+Private.h
generated
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRClient.h"
|
||||
#import "FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.h"
|
||||
|
||||
@class FPRGDTLogger;
|
||||
@class FPRConfigurations;
|
||||
@class FIRInstallations;
|
||||
|
||||
/// Protocol to define the Firebase performance provider for the component framework.
|
||||
@protocol FIRPerformanceProvider <NSObject>
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Extension that is added on top of the class FPRClient to make the private properties visible
|
||||
* between the implementation file and the unit tests.
|
||||
*/
|
||||
@interface FPRClient ()
|
||||
|
||||
@property(nonatomic, getter=isConfigured, readwrite) BOOL configured;
|
||||
|
||||
/** GDT Logger to transmit Fireperf events to Google Data Transport. */
|
||||
@property(nonatomic) FPRGDTLogger *gdtLogger;
|
||||
|
||||
/** The queue group all FPRClient work will run on. Used for testing only. */
|
||||
@property(nonatomic, readonly) dispatch_group_t eventsQueueGroup;
|
||||
|
||||
/** Serial queue used for processing events. */
|
||||
@property(nonatomic, readonly) dispatch_queue_t eventsQueue;
|
||||
|
||||
/** Firebase Remote Configuration object for FPRClient. */
|
||||
@property(nonatomic) FPRConfigurations *configuration;
|
||||
|
||||
/** Firebase Installations object for FPRClient. */
|
||||
@property(nonatomic) FIRInstallations *installations;
|
||||
|
||||
/** The Firebase Project ID of the project. */
|
||||
@property(nonatomic, readonly) NSString *projectID;
|
||||
|
||||
/** The bundle ID of the project*/
|
||||
@property(nonatomic, readonly) NSString *bundleID;
|
||||
/**
|
||||
* Determines the log directory path in the caches directory.
|
||||
*
|
||||
* @return The directory in which Clearcut logs are stored.
|
||||
*/
|
||||
+ (NSString *)logDirectoryPath;
|
||||
|
||||
/**
|
||||
* Cleans up the log directory path in the cache directory created for Clearcut logs storage.
|
||||
*
|
||||
* @remark This method (cleanup logic) should stay for a while until all of our apps have migrated
|
||||
* to a version which includes this logic.
|
||||
*/
|
||||
+ (void)cleanupClearcutCacheDirectory;
|
||||
|
||||
/** Performs post processing and logs a firebase_perf_v1_PerfMetric object to Google Data Transport.
|
||||
* @param event Reference to a firebase_perf_v1_PerfMetric proto object.
|
||||
*/
|
||||
- (void)processAndLogEvent:(firebase_perf_v1_PerfMetric)event;
|
||||
|
||||
@end
|
||||
85
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRClient.h
generated
Normal file
85
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRClient.h
generated
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Public/FirebasePerformance/FIRTrace.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/FPRConfiguration.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/FPRGaugeManager.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
|
||||
/** NSError codes for FPRClient related errors */
|
||||
typedef NS_ENUM(NSInteger, FPRClientErrorCode) {
|
||||
// Generic Error.
|
||||
FPRClientErrorCodeUnknown,
|
||||
|
||||
// Error starting the client.
|
||||
FPRClientErrorCodeStartupError
|
||||
};
|
||||
|
||||
/** This class is not exposed to the public and internally provides the primary entry point into
|
||||
* the Firebase Performance module's functionality.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRClient : NSObject
|
||||
|
||||
/** YES if SDK is configured, otherwise NO. */
|
||||
@property(nonatomic, getter=isConfigured, readonly) BOOL configured;
|
||||
|
||||
/** YES if methods have been swizzled, NO otherwise. */
|
||||
@property(nonatomic, getter=isSwizzled) BOOL swizzled;
|
||||
|
||||
/** Accesses the singleton instance. All Firebase Performance methods should be managed via this
|
||||
* shared instance.
|
||||
* @return Reference to the shared object if successful; <code>nil</code> if not.
|
||||
*/
|
||||
+ (nonnull FPRClient *)sharedInstance;
|
||||
|
||||
/** Enables performance reporting. This installs auto instrumentation and configures metric
|
||||
* uploading.
|
||||
*
|
||||
* @param config Configures perf reporting behavior.
|
||||
* @param error Populated with an NSError instance on failure.
|
||||
* @return <code>YES</code> if successful; <code>NO</code> if not.
|
||||
*/
|
||||
- (BOOL)startWithConfiguration:(nonnull FPRConfiguration *)config
|
||||
error:(NSError *__autoreleasing _Nullable *_Nullable)error;
|
||||
|
||||
/** Logs a trace event.
|
||||
*
|
||||
* @param trace Trace event that needs to be logged to Google Data Transport.
|
||||
*/
|
||||
- (void)logTrace:(nonnull FIRTrace *)trace;
|
||||
|
||||
/** Logs a network trace event.
|
||||
*
|
||||
* @param trace Network trace event that needs to be logged to Google Data Transport.
|
||||
*/
|
||||
- (void)logNetworkTrace:(nonnull FPRNetworkTrace *)trace;
|
||||
|
||||
/** Logs a gauge metric event.
|
||||
*
|
||||
* @param gaugeData Gauge metric event that needs to be logged to Google Data Transport.
|
||||
* @param sessionId SessionID with which the gauge data will be logged.
|
||||
*/
|
||||
- (void)logGaugeMetric:(nonnull NSArray *)gaugeData forSessionId:(nonnull NSString *)sessionId;
|
||||
|
||||
/** Checks if the instrumentation of the app is enabled. If enabled, setup the instrumentation. */
|
||||
- (void)checkAndStartInstrumentation;
|
||||
|
||||
/** Unswizzles any existing methods that have been instrumented and stops automatic instrumentation
|
||||
* for all future app starts unless explicitly enabled.
|
||||
*/
|
||||
- (void)disableInstrumentation;
|
||||
|
||||
@end
|
||||
370
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRClient.m
generated
Normal file
370
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRClient.m
generated
Normal file
@ -0,0 +1,370 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRClient.h"
|
||||
#import "FirebasePerformance/Sources/FPRClient+Private.h"
|
||||
|
||||
#import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h"
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker+Private.h"
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRScreenTraceTracker.h"
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager+Private.h"
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.h"
|
||||
#import "FirebasePerformance/Sources/Common/FPRConsoleURLGenerator.h"
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h"
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
#import "FirebasePerformance/Sources/FPRNanoPbUtils.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.h"
|
||||
#import "FirebasePerformance/Sources/Loggers/FPRGDTLogger.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
|
||||
|
||||
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
|
||||
|
||||
@import FirebaseSessions;
|
||||
|
||||
@interface FPRClient () <FIRLibrary, FIRPerformanceProvider, FIRSessionsSubscriber>
|
||||
|
||||
/** The original configuration object used to initialize the client. */
|
||||
@property(nonatomic, strong) FPRConfiguration *config;
|
||||
|
||||
/** The object that manages all automatic class instrumentation. */
|
||||
@property(nonatomic) FPRInstrumentation *instrumentation;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRClient
|
||||
|
||||
+ (void)load {
|
||||
[FIRApp registerInternalLibrary:[FPRClient class]
|
||||
withName:@"fire-perf"
|
||||
withVersion:[NSString stringWithUTF8String:kFPRSDKVersion]];
|
||||
[FIRSessionsDependencies addDependencyWithName:FIRSessionsSubscriberNamePerformance];
|
||||
}
|
||||
|
||||
#pragma mark - Component registration system
|
||||
|
||||
+ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
|
||||
FIRComponentCreationBlock creationBlock =
|
||||
^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
|
||||
if (!container.app.isDefaultApp) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
id<FIRSessionsProvider> sessions = FIR_COMPONENT(FIRSessionsProvider, container);
|
||||
|
||||
NSString *appName = container.app.name;
|
||||
FIRApp *app = [FIRApp appNamed:appName];
|
||||
FIROptions *options = app.options;
|
||||
NSError *error = nil;
|
||||
|
||||
// Based on the environment variable SDK decides if events are dispatched to Autopush or Prod.
|
||||
// By default, events are sent to Prod.
|
||||
BOOL useAutoPush = NO;
|
||||
NSDictionary<NSString *, NSString *> *environment = [NSProcessInfo processInfo].environment;
|
||||
if (environment[@"FPR_AUTOPUSH_ENV"] != nil &&
|
||||
[environment[@"FPR_AUTOPUSH_ENV"] isEqualToString:@"1"]) {
|
||||
useAutoPush = YES;
|
||||
}
|
||||
|
||||
FPRConfiguration *configuration = [FPRConfiguration configurationWithAppID:options.googleAppID
|
||||
APIKey:options.APIKey
|
||||
autoPush:useAutoPush];
|
||||
if (![[self sharedInstance] startWithConfiguration:configuration error:&error]) {
|
||||
FPRLogError(kFPRClientInitialize, @"Failed to initialize the client with error: %@.", error);
|
||||
}
|
||||
|
||||
if (sessions) {
|
||||
FPRLogDebug(kFPRClientInitialize, @"Registering Sessions SDK subscription for session data");
|
||||
|
||||
// Subscription should be made after the first call to [FPRClient sharedInstance] where
|
||||
// _configuration is initialized so that the sessions SDK can immediately get the data
|
||||
// collection state.
|
||||
[sessions registerWithSubscriber:[self sharedInstance]];
|
||||
}
|
||||
|
||||
*isCacheable = YES;
|
||||
|
||||
return [self sharedInstance];
|
||||
};
|
||||
|
||||
FIRComponent *component =
|
||||
[FIRComponent componentWithProtocol:@protocol(FIRPerformanceProvider)
|
||||
instantiationTiming:FIRInstantiationTimingEagerInDefaultApp
|
||||
creationBlock:creationBlock];
|
||||
|
||||
return @[ component ];
|
||||
}
|
||||
|
||||
+ (FPRClient *)sharedInstance {
|
||||
static FPRClient *sharedInstance = nil;
|
||||
static dispatch_once_t token;
|
||||
dispatch_once(&token, ^{
|
||||
sharedInstance = [[FPRClient alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_instrumentation = [[FPRInstrumentation alloc] init];
|
||||
_swizzled = NO;
|
||||
_eventsQueue = dispatch_queue_create("com.google.perf.FPREventsQueue", DISPATCH_QUEUE_SERIAL);
|
||||
_eventsQueueGroup = dispatch_group_create();
|
||||
_configuration = [FPRConfigurations sharedInstance];
|
||||
_projectID = [FIROptions defaultOptions].projectID;
|
||||
_bundleID = [FIROptions defaultOptions].bundleID;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)startWithConfiguration:(FPRConfiguration *)config error:(NSError *__autoreleasing *)error {
|
||||
self.config = config;
|
||||
NSInteger logSource = [self.configuration logSource];
|
||||
|
||||
dispatch_group_async(self.eventsQueueGroup, self.eventsQueue, ^{
|
||||
// Create the Logger for the Perf SDK events to be sent to Google Data Transport.
|
||||
self.gdtLogger = [[FPRGDTLogger alloc] initWithLogSource:logSource];
|
||||
|
||||
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
// Create telephony network information object ahead of time to avoid runtime delays.
|
||||
FPRNetworkInfo();
|
||||
#endif
|
||||
|
||||
// Update the configuration flags.
|
||||
[self.configuration update];
|
||||
|
||||
[FPRClient cleanupClearcutCacheDirectory];
|
||||
});
|
||||
|
||||
// Set up instrumentation.
|
||||
[self checkAndStartInstrumentation];
|
||||
|
||||
self.configured = YES;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
FPRLogInfo(kFPRClientInitialize,
|
||||
@"Firebase Performance Monitoring is successfully initialized! In a minute, visit "
|
||||
@"the Firebase console to view your data: %@",
|
||||
[FPRConsoleURLGenerator generateDashboardURLWithProjectID:self.projectID
|
||||
bundleID:self.bundleID]);
|
||||
});
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)checkAndStartInstrumentation {
|
||||
BOOL instrumentationEnabled = self.configuration.isInstrumentationEnabled;
|
||||
if (instrumentationEnabled && !self.isSwizzled) {
|
||||
[self.instrumentation registerInstrumentGroup:kFPRInstrumentationGroupNetworkKey];
|
||||
[self.instrumentation registerInstrumentGroup:kFPRInstrumentationGroupUIKitKey];
|
||||
self.swizzled = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (void)logTrace:(FIRTrace *)trace {
|
||||
if (self.configured == NO) {
|
||||
FPRLogError(kFPRClientPerfNotConfigured, @"Dropping trace event %@. Perf SDK not configured.",
|
||||
trace.name);
|
||||
return;
|
||||
}
|
||||
if ([trace isCompleteAndValid]) {
|
||||
dispatch_group_async(self.eventsQueueGroup, self.eventsQueue, ^{
|
||||
firebase_perf_v1_PerfMetric metric = FPRGetPerfMetricMessage(self.config.appID);
|
||||
FPRSetTraceMetric(&metric, FPRGetTraceMetric(trace));
|
||||
FPRSetApplicationProcessState(&metric,
|
||||
FPRApplicationProcessState(trace.backgroundTraceState));
|
||||
|
||||
// Log the trace metric with its console URL.
|
||||
if ([trace.name hasPrefix:kFPRPrefixForScreenTraceName]) {
|
||||
FPRLogInfo(kFPRClientMetricLogged,
|
||||
@"Logging trace metric - %@ %.4fms. In a minute, visit the Firebase console to "
|
||||
@"view your data: %@",
|
||||
trace.name, metric.trace_metric.duration_us / 1000.0,
|
||||
[FPRConsoleURLGenerator generateScreenTraceURLWithProjectID:self.projectID
|
||||
bundleID:self.bundleID
|
||||
traceName:trace.name]);
|
||||
} else {
|
||||
FPRLogInfo(kFPRClientMetricLogged,
|
||||
@"Logging trace metric - %@ %.4fms. In a minute, visit the Firebase console to "
|
||||
@"view your data: %@",
|
||||
trace.name, metric.trace_metric.duration_us / 1000.0,
|
||||
[FPRConsoleURLGenerator generateCustomTraceURLWithProjectID:self.projectID
|
||||
bundleID:self.bundleID
|
||||
traceName:trace.name]);
|
||||
}
|
||||
[self processAndLogEvent:metric];
|
||||
});
|
||||
} else {
|
||||
FPRLogWarning(kFPRClientInvalidTrace, @"Invalid trace, skipping send.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logNetworkTrace:(nonnull FPRNetworkTrace *)trace {
|
||||
if (self.configured == NO) {
|
||||
FPRLogError(kFPRClientPerfNotConfigured, @"Dropping trace event %@. Perf SDK not configured.",
|
||||
trace.URLRequest.URL.absoluteString);
|
||||
return;
|
||||
}
|
||||
dispatch_group_async(self.eventsQueueGroup, self.eventsQueue, ^{
|
||||
if ([trace isValid]) {
|
||||
firebase_perf_v1_NetworkRequestMetric networkRequestMetric =
|
||||
FPRGetNetworkRequestMetric(trace);
|
||||
int64_t duration = networkRequestMetric.has_time_to_response_completed_us
|
||||
? networkRequestMetric.time_to_response_completed_us
|
||||
: 0;
|
||||
|
||||
NSString *responseCode = networkRequestMetric.has_http_response_code
|
||||
? [@(networkRequestMetric.http_response_code) stringValue]
|
||||
: @"UNKNOWN";
|
||||
FPRLogInfo(kFPRClientMetricLogged,
|
||||
@"Logging network request trace - %@, Response code: %@, %.4fms",
|
||||
trace.trimmedURLString, responseCode, duration / 1000.0);
|
||||
firebase_perf_v1_PerfMetric metric = FPRGetPerfMetricMessage(self.config.appID);
|
||||
FPRSetNetworkRequestMetric(&metric, networkRequestMetric);
|
||||
FPRSetApplicationProcessState(&metric,
|
||||
FPRApplicationProcessState(trace.backgroundTraceState));
|
||||
|
||||
[self processAndLogEvent:metric];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)logGaugeMetric:(nonnull NSArray *)gaugeData forSessionId:(nonnull NSString *)sessionId {
|
||||
if (self.configured == NO) {
|
||||
FPRLogError(kFPRClientPerfNotConfigured, @"Dropping session event. Perf SDK not configured.");
|
||||
return;
|
||||
}
|
||||
dispatch_group_async(self.eventsQueueGroup, self.eventsQueue, ^{
|
||||
firebase_perf_v1_PerfMetric metric = FPRGetPerfMetricMessage(self.config.appID);
|
||||
firebase_perf_v1_GaugeMetric gaugeMetric = firebase_perf_v1_GaugeMetric_init_default;
|
||||
if ((gaugeData != nil && gaugeData.count != 0) && (sessionId != nil && sessionId.length != 0)) {
|
||||
gaugeMetric = FPRGetGaugeMetric(gaugeData, sessionId);
|
||||
}
|
||||
FPRSetGaugeMetric(&metric, gaugeMetric);
|
||||
[self processAndLogEvent:metric];
|
||||
});
|
||||
|
||||
// Check and update the sessionID if the session is running for too long.
|
||||
[[FPRSessionManager sharedInstance] stopGaugesIfRunningTooLong];
|
||||
}
|
||||
|
||||
- (void)processAndLogEvent:(firebase_perf_v1_PerfMetric)event {
|
||||
BOOL tracingEnabled = self.configuration.isDataCollectionEnabled;
|
||||
if (!tracingEnabled) {
|
||||
FPRLogDebug(kFPRClientPerfNotConfigured, @"Dropping event since data collection is disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL sdkEnabled = [self.configuration sdkEnabled];
|
||||
if (!sdkEnabled) {
|
||||
FPRLogInfo(kFPRClientSDKDisabled, @"Dropping event since Performance SDK is disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
if (self.installations == nil) {
|
||||
// Delayed initialization of installations because FIRApp needs to be configured first.
|
||||
self.installations = [FIRInstallations installations];
|
||||
}
|
||||
});
|
||||
|
||||
// Attempts to dispatch events if successfully retrieve installation ID.
|
||||
[self.installations
|
||||
installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) {
|
||||
if (error) {
|
||||
FPRLogError(kFPRClientInstanceIDNotAvailable, @"FIRInstallations error: %@",
|
||||
error.description);
|
||||
} else {
|
||||
dispatch_group_async(self.eventsQueueGroup, self.eventsQueue, ^{
|
||||
firebase_perf_v1_PerfMetric updatedEvent = event;
|
||||
updatedEvent.application_info.app_instance_id = FPREncodeString(identifier);
|
||||
[self.gdtLogger logEvent:updatedEvent];
|
||||
});
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Clearcut log directory removal methods
|
||||
|
||||
+ (void)cleanupClearcutCacheDirectory {
|
||||
NSString *logDirectoryPath = [FPRClient logDirectoryPath];
|
||||
|
||||
if (logDirectoryPath != nil) {
|
||||
BOOL logDirectoryExists = [[NSFileManager defaultManager] fileExistsAtPath:logDirectoryPath];
|
||||
|
||||
if (logDirectoryExists) {
|
||||
NSError *directoryError = nil;
|
||||
[[NSFileManager defaultManager] removeItemAtPath:logDirectoryPath error:&directoryError];
|
||||
|
||||
if (directoryError) {
|
||||
FPRLogDebug(kFPRClientTempDirectory,
|
||||
@"Failed to delete the stale log directory at path: %@ with error: %@.",
|
||||
logDirectoryPath, directoryError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)logDirectoryPath {
|
||||
static NSString *cacheDir;
|
||||
static NSString *fireperfCacheDir;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
cacheDir =
|
||||
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
|
||||
|
||||
if (!cacheDir) {
|
||||
fireperfCacheDir = nil;
|
||||
} else {
|
||||
fireperfCacheDir = [cacheDir stringByAppendingPathComponent:@"firebase_perf_logging"];
|
||||
}
|
||||
});
|
||||
|
||||
return fireperfCacheDir;
|
||||
}
|
||||
|
||||
#pragma mark - Unswizzling, use only for unit tests
|
||||
|
||||
- (void)disableInstrumentation {
|
||||
[self.instrumentation deregisterInstrumentGroup:kFPRInstrumentationGroupNetworkKey];
|
||||
[self.instrumentation deregisterInstrumentGroup:kFPRInstrumentationGroupUIKitKey];
|
||||
self.swizzled = NO;
|
||||
[self.configuration setInstrumentationEnabled:NO];
|
||||
}
|
||||
|
||||
#pragma mark - FIRSessionsSubscriber
|
||||
|
||||
- (void)onSessionChanged:(FIRSessionDetails *_Nonnull)session {
|
||||
[[FPRSessionManager sharedInstance] updateSessionId:session.sessionId];
|
||||
}
|
||||
|
||||
- (BOOL)isDataCollectionEnabled {
|
||||
return self.configuration.isDataCollectionEnabled;
|
||||
}
|
||||
|
||||
- (FIRSessionsSubscriberName)sessionsSubscriberName {
|
||||
return FIRSessionsSubscriberNamePerformance;
|
||||
}
|
||||
|
||||
@end
|
||||
50
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConfiguration.h
generated
Normal file
50
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConfiguration.h
generated
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* @brief Configures the behavior of FPR.
|
||||
*/
|
||||
@interface FPRConfiguration : NSObject <NSCopying>
|
||||
|
||||
/**
|
||||
* Designated initializer.
|
||||
* @brief Creates a new configuration.
|
||||
*
|
||||
* @param appID Identifies app on Firebase
|
||||
* @param APIKey Authenticates app on Firebase
|
||||
* @param autoPush Google Data Transport destination - prod/autopush
|
||||
*/
|
||||
- (instancetype)initWithAppID:(NSString *)appID
|
||||
APIKey:(NSString *)APIKey
|
||||
autoPush:(BOOL)autoPush NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** This is a class method for initWithAppID:APIKey:autoPush:. */
|
||||
+ (instancetype)configurationWithAppID:(NSString *)appID
|
||||
APIKey:(NSString *)APIKey
|
||||
autoPush:(BOOL)autoPush;
|
||||
|
||||
/** @brief Identifies app on Firebase. */
|
||||
@property(readonly, nonatomic, copy) NSString *appID;
|
||||
|
||||
/** @brief Authenticates app on Firebase. */
|
||||
@property(readonly, nonatomic, copy) NSString *APIKey;
|
||||
|
||||
/** @brief Use autopush or prod logging. */
|
||||
@property(readonly, nonatomic, assign, getter=isAutoPush) BOOL autoPush;
|
||||
|
||||
@end
|
||||
47
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConfiguration.m
generated
Normal file
47
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConfiguration.m
generated
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRConfiguration.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
|
||||
@implementation FPRConfiguration
|
||||
|
||||
- (instancetype)init {
|
||||
FPRAssert(NO, @"init called on NS_UNAVAILABLE init");
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithAppID:(NSString *)appID APIKey:(NSString *)APIKey autoPush:(BOOL)autoPush {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_appID = [appID copy];
|
||||
_APIKey = [APIKey copy];
|
||||
_autoPush = autoPush;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)configurationWithAppID:(NSString *)appID
|
||||
APIKey:(NSString *)APIKey
|
||||
autoPush:(BOOL)autoPush {
|
||||
return [[self alloc] initWithAppID:appID APIKey:APIKey autoPush:autoPush];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
return self; // This class is immutable
|
||||
}
|
||||
|
||||
@end
|
||||
95
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConsoleLogger.h
generated
Normal file
95
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConsoleLogger.h
generated
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebaseCore/Extension/FIRLogger.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXTERN NSString* const kFIRLoggerPerf;
|
||||
|
||||
#define FPRLogDebug(messageCode, ...) FIRLogDebug(kFIRLoggerPerf, messageCode, __VA_ARGS__)
|
||||
#define FPRLogError(messageCode, ...) FIRLogError(kFIRLoggerPerf, messageCode, __VA_ARGS__)
|
||||
#define FPRLogInfo(messageCode, ...) FIRLogInfo(kFIRLoggerPerf, messageCode, __VA_ARGS__)
|
||||
#define FPRLogNotice(messageCode, ...) FIRLogNotice(kFIRLoggerPerf, messageCode, __VA_ARGS__)
|
||||
#define FPRLogWarning(messageCode, ...) FIRLogWarning(kFIRLoggerPerf, messageCode, __VA_ARGS__)
|
||||
|
||||
// FPR Client message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientInitialize;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientTempDirectory;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientCreateWorkingDirectory;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientClearcutUpload;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientInstanceIDNotAvailable;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientNameTruncated;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientNameReserved;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientInvalidTrace;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientMetricLogged;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientDataUpload;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientNameLengthCheckFailed;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientPerfNotConfigured;
|
||||
FOUNDATION_EXTERN NSString* const kFPRClientSDKDisabled;
|
||||
|
||||
// FPR Trace message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceNoName;
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceAlreadyStopped;
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceNotStarted;
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceDisabled;
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceEmptyName;
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceStartedNotStopped;
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceNotCreated;
|
||||
FOUNDATION_EXTERN NSString* const kFPRTraceInvalidName;
|
||||
|
||||
// FPR NetworkTrace message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRNetworkTraceFileError;
|
||||
FOUNDATION_EXTERN NSString* const kFPRNetworkTraceInvalidInputs;
|
||||
FOUNDATION_EXTERN NSString* const kFPRNetworkTraceURLLengthExceeds;
|
||||
FOUNDATION_EXTERN NSString* const kFPRNetworkTraceURLLengthTruncation;
|
||||
FOUNDATION_EXTERN NSString* const kFPRNetworkTraceNotTrackable;
|
||||
|
||||
// FPR LogSampler message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRSamplerInvalidConfigs;
|
||||
|
||||
// FPR attributes message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRAttributeNoName;
|
||||
FOUNDATION_EXTERN NSString* const kFPRAttributeNoValue;
|
||||
FOUNDATION_EXTERN NSString* const kFPRMaxAttributesReached;
|
||||
FOUNDATION_EXTERN NSString* const kFPRAttributeNameIllegalCharacters;
|
||||
|
||||
// Manual network instrumentation codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRInstrumentationInvalidInputs;
|
||||
FOUNDATION_EXTERN NSString* const kFPRInstrumentationDisabledAfterConfigure;
|
||||
|
||||
// FPR diagnostic message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRDiagnosticInfo;
|
||||
FOUNDATION_EXTERN NSString* const kFPRDiagnosticFailure;
|
||||
FOUNDATION_EXTERN NSString* const kFPRDiagnosticLog;
|
||||
|
||||
// FPR Configuration related error codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRConfigurationFetchFailure;
|
||||
|
||||
// FPR URL filtering message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRURLAllowlistingEnabled;
|
||||
|
||||
// FPR Gauge manager codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRGaugeManagerDataCollected;
|
||||
FOUNDATION_EXTERN NSString* const kFPRSessionId;
|
||||
FOUNDATION_EXTERN NSString* const kFPRCPUCollection;
|
||||
FOUNDATION_EXTERN NSString* const kFPRMemoryCollection;
|
||||
|
||||
// FPRSDKConfiguration message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRSDKFeaturesBlock;
|
||||
|
||||
// FPRGDTEvent message codes.
|
||||
FOUNDATION_EXTERN NSString* const kFPRTransportBytesError;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
86
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConsoleLogger.m
generated
Normal file
86
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRConsoleLogger.m
generated
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
// The Firebase service used in the Firebase logger.
|
||||
FIRLoggerService kFIRLoggerPerf = @"[FirebasePerformance]";
|
||||
|
||||
// FPR Client message codes.
|
||||
NSString* const kFPRClientInitialize = @"I-PRF100001";
|
||||
NSString* const kFPRClientTempDirectory = @"I-PRF100002";
|
||||
NSString* const kFPRClientCreateWorkingDirectory = @"I-PRF100003";
|
||||
NSString* const kFPRClientClearcutUpload = @"I-PRF100004";
|
||||
NSString* const kFPRClientInstanceIDNotAvailable = @"I-PRF100005";
|
||||
NSString* const kFPRClientNameTruncated = @"I-PRF100006";
|
||||
NSString* const kFPRClientNameReserved = @"I-PRF100007";
|
||||
NSString* const kFPRClientInvalidTrace = @"I-PRF100008";
|
||||
NSString* const kFPRClientMetricLogged = @"I-PRF100009";
|
||||
NSString* const kFPRClientDataUpload = @"I-PRF100010";
|
||||
NSString* const kFPRClientNameLengthCheckFailed = @"I-PRF100012";
|
||||
NSString* const kFPRClientPerfNotConfigured = @"I-PRF100013";
|
||||
NSString* const kFPRClientSDKDisabled = @"I-PRF100014";
|
||||
|
||||
// FPR Trace message codes.
|
||||
NSString* const kFPRTraceNoName = @"I-PRF200001";
|
||||
NSString* const kFPRTraceAlreadyStopped = @"I-PRF200002";
|
||||
NSString* const kFPRTraceNotStarted = @"I-PRF200003";
|
||||
NSString* const kFPRTraceDisabled = @"I-PRF200004";
|
||||
NSString* const kFPRTraceEmptyName = @"I-PRF200005";
|
||||
NSString* const kFPRTraceStartedNotStopped = @"I-PRF200006";
|
||||
NSString* const kFPRTraceNotCreated = @"I-PRF200007";
|
||||
NSString* const kFPRTraceInvalidName = @"I-PRF200008";
|
||||
|
||||
// FPR NetworkTrace message codes.
|
||||
NSString* const kFPRNetworkTraceFileError = @"I-PRF300001";
|
||||
NSString* const kFPRNetworkTraceInvalidInputs = @"I-PRF300002";
|
||||
NSString* const kFPRNetworkTraceURLLengthExceeds = @"I-PRF300003";
|
||||
NSString* const kFPRNetworkTraceNotTrackable = @"I-PRF300004";
|
||||
NSString* const kFPRNetworkTraceURLLengthTruncation = @"I-PRF300005";
|
||||
|
||||
// FPR LogSampler message codes.
|
||||
NSString* const kFPRSamplerInvalidConfigs = @"I-PRF400001";
|
||||
|
||||
// FPR Attributes message codes.
|
||||
NSString* const kFPRAttributeNoName = @"I-PRF500001";
|
||||
NSString* const kFPRAttributeNoValue = @"I-PRF500002";
|
||||
NSString* const kFPRMaxAttributesReached = @"I-PRF500003";
|
||||
NSString* const kFPRAttributeNameIllegalCharacters = @"I-PRF500004";
|
||||
|
||||
// Manual network instrumentation codes.
|
||||
NSString* const kFPRInstrumentationInvalidInputs = @"I-PRF600001";
|
||||
NSString* const kFPRInstrumentationDisabledAfterConfigure = @"I-PRF600002";
|
||||
|
||||
// FPR diagnostic message codes.
|
||||
NSString* const kFPRDiagnosticInfo = @"I-PRF700001";
|
||||
NSString* const kFPRDiagnosticFailure = @"I-PRF700002";
|
||||
NSString* const kFPRDiagnosticLog = @"I-PRF700003";
|
||||
|
||||
// FPR Configuration related error codes.
|
||||
NSString* const kFPRConfigurationFetchFailure = @"I-PRF710001";
|
||||
|
||||
// FPR URL filtering message codes.
|
||||
NSString* const kFPRURLAllowlistingEnabled = @"I-PRF800001";
|
||||
|
||||
// FPR Gauge manager codes.
|
||||
NSString* const kFPRGaugeManagerDataCollected = @"I-PRF900001";
|
||||
NSString* const kFPRSessionId = @"I-PRF900002";
|
||||
NSString* const kFPRCPUCollection = @"I-PRF900003";
|
||||
NSString* const kFPRMemoryCollection = @"I-PRF900004";
|
||||
|
||||
// FPRSDKConfiguration message codes.
|
||||
NSString* const kFPRSDKFeaturesBlock = @"I-PRF910001";
|
||||
|
||||
// FPRGDTEvent message codes.
|
||||
NSString* const kFPRTransportBytesError = @"I-PRF920001";
|
||||
48
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRDataUtils.h
generated
Normal file
48
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRDataUtils.h
generated
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/** Trims the given name string and checks if the name is reservable.
|
||||
*
|
||||
* @param name The name to be checked for reservability.
|
||||
* @return Reservable name or nil if there is an error.
|
||||
*/
|
||||
FOUNDATION_EXTERN NSString *FPRReservableName(NSString *name);
|
||||
|
||||
/** Trims the given name string and checks if the name is reservable.
|
||||
*
|
||||
* @param name The name to be checked for reservability for an attribute name.
|
||||
* @return Reservable name or nil if there is an error.
|
||||
*/
|
||||
FOUNDATION_EXTERN NSString *FPRReservableAttributeName(NSString *name);
|
||||
|
||||
/** Checks if the given attribute value follows length restrictions.
|
||||
*
|
||||
* @param value The value to be checked.
|
||||
* @return Valid value or nil if that does not adhere to length restrictions.
|
||||
*/
|
||||
FOUNDATION_EXTERN NSString *FPRValidatedAttributeValue(NSString *value);
|
||||
|
||||
/** Truncates the URL string if the length of the URL going beyond the defined limit. The truncation
|
||||
* will happen upto the end of a complete query sub path whose length is less than limit.
|
||||
* For example: If the URL is abc.com/one/two/three/four and if the URL max length is 20, trimmed
|
||||
* URL will be to abc.com/one/two and not abc.com/one/two/thre (three is incomplete).
|
||||
* If the domain name goes beyond 2000 characters (which is unlikely), that might result in an
|
||||
* empty string being returned.
|
||||
*
|
||||
* @param URLString A URL string.
|
||||
* @return The unchanged url string or a truncated version if the length goes beyond the limit.
|
||||
*/
|
||||
FOUNDATION_EXTERN NSString *FPRTruncatedURLString(NSString *URLString);
|
||||
127
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRDataUtils.m
generated
Normal file
127
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRDataUtils.m
generated
Normal file
@ -0,0 +1,127 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRDataUtils.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
#pragma mark - Public functions
|
||||
|
||||
NSString *FPRReservableName(NSString *name) {
|
||||
NSString *reservableName =
|
||||
[name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
if ([reservableName hasPrefix:kFPRInternalNamePrefix]) {
|
||||
FPRLogError(kFPRClientNameReserved, @"%@ prefix is reserved. Dropped %@.",
|
||||
kFPRInternalNamePrefix, reservableName);
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (reservableName.length == 0) {
|
||||
FPRLogError(kFPRClientNameLengthCheckFailed, @"Given name is empty.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (reservableName.length > kFPRMaxNameLength) {
|
||||
FPRLogError(kFPRClientNameLengthCheckFailed, @"%@ is greater than %d characters, dropping it.",
|
||||
reservableName, kFPRMaxNameLength);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return reservableName;
|
||||
}
|
||||
|
||||
NSString *FPRReservableAttributeName(NSString *name) {
|
||||
NSString *reservableName =
|
||||
[name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
|
||||
static NSArray<NSString *> *reservedPrefix = nil;
|
||||
static NSPredicate *characterCheck = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
reservedPrefix = @[ @"firebase_", @"google_", @"ga_" ];
|
||||
NSString *characterRegex = @"[A-Z0-9a-z_]*";
|
||||
characterCheck = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", characterRegex];
|
||||
});
|
||||
|
||||
__block BOOL containsReservedPrefix = NO;
|
||||
[reservedPrefix enumerateObjectsUsingBlock:^(NSString *prefix, NSUInteger idx, BOOL *stop) {
|
||||
if ([reservableName hasPrefix:prefix]) {
|
||||
FPRLogError(kFPRClientNameReserved, @"%@ prefix is reserved. Dropped %@.", prefix,
|
||||
reservableName);
|
||||
*stop = YES;
|
||||
containsReservedPrefix = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
if (containsReservedPrefix) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (reservableName.length == 0) {
|
||||
FPRLogError(kFPRClientNameLengthCheckFailed, @"Given name is empty.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([characterCheck evaluateWithObject:reservableName] == NO) {
|
||||
FPRLogError(kFPRAttributeNameIllegalCharacters,
|
||||
@"Illegal characters used for attribute name, "
|
||||
"characters allowed are alphanumeric or underscore.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (reservableName.length > kFPRMaxAttributeNameLength) {
|
||||
FPRLogError(kFPRClientNameLengthCheckFailed, @"%@ is greater than %d characters, dropping it.",
|
||||
reservableName, kFPRMaxAttributeNameLength);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return reservableName;
|
||||
}
|
||||
|
||||
NSString *FPRValidatedAttributeValue(NSString *value) {
|
||||
if (value.length == 0) {
|
||||
FPRLogError(kFPRClientNameLengthCheckFailed, @"Given value is empty.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (value.length > kFPRMaxAttributeValueLength) {
|
||||
FPRLogError(kFPRClientNameLengthCheckFailed, @"%@ is greater than %d characters, dropping it.",
|
||||
value, kFPRMaxAttributeValueLength);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
NSString *FPRTruncatedURLString(NSString *URLString) {
|
||||
NSString *truncatedURLString = URLString;
|
||||
NSString *pathSeparator = @"/";
|
||||
if (truncatedURLString.length > kFPRMaxURLLength) {
|
||||
NSString *truncationCharacter =
|
||||
[truncatedURLString substringWithRange:NSMakeRange(kFPRMaxURLLength, 1)];
|
||||
|
||||
truncatedURLString = [URLString substringToIndex:kFPRMaxURLLength];
|
||||
if (![pathSeparator isEqual:truncationCharacter]) {
|
||||
NSRange rangeOfTruncation = [truncatedURLString rangeOfString:pathSeparator
|
||||
options:NSBackwardsSearch];
|
||||
if (rangeOfTruncation.location != NSNotFound) {
|
||||
truncatedURLString = [URLString substringToIndex:rangeOfTruncation.location];
|
||||
}
|
||||
}
|
||||
FPRLogWarning(kFPRClientNameTruncated, @"URL exceeds %d characters. Truncated url: %@",
|
||||
kFPRMaxURLLength, truncatedURLString);
|
||||
}
|
||||
return truncatedURLString;
|
||||
}
|
||||
161
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRNanoPbUtils.h
generated
Normal file
161
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRNanoPbUtils.h
generated
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2021 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
|
||||
//
|
||||
// http://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 <TargetConditionals.h>
|
||||
#if __has_include("CoreTelephony/CTTelephonyNetworkInfo.h") && !TARGET_OS_MACCATALYST
|
||||
#define TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
||||
#endif
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRTrace.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.h"
|
||||
|
||||
/**nanopb struct of encoded NSDictionary<NSString *, NSString *>.*/
|
||||
typedef struct {
|
||||
pb_bytes_array_t* _Nonnull key;
|
||||
pb_bytes_array_t* _Nonnull value;
|
||||
} StringToStringMap;
|
||||
|
||||
/**nanopb struct of encoded NSDictionary<NSString *, NSNumber *>.*/
|
||||
typedef struct {
|
||||
pb_bytes_array_t* _Nonnull key;
|
||||
bool has_value;
|
||||
int64_t value;
|
||||
} StringToNumberMap;
|
||||
|
||||
/** Callocs a pb_bytes_array and copies the given NSData bytes into the bytes array.
|
||||
*
|
||||
* @note Memory needs to be free manually, through pb_free or pb_release.
|
||||
* @param data The data to copy into the new bytes array.
|
||||
* @return pb_byte array
|
||||
*/
|
||||
extern pb_bytes_array_t* _Nullable FPREncodeData(NSData* _Nonnull data);
|
||||
|
||||
/** Callocs a pb_bytes_array and copies the given NSString's bytes into the bytes array.
|
||||
*
|
||||
* @note Memory needs to be free manually, through pb_free or pb_release.
|
||||
* @param string The string to encode as pb_bytes.
|
||||
* @return pb_byte array
|
||||
*/
|
||||
extern pb_bytes_array_t* _Nullable FPREncodeString(NSString* _Nonnull string);
|
||||
|
||||
/** Callocs a nanopb StringToStringMap and copies the given NSDictionary bytes into the
|
||||
* StringToStringMap.
|
||||
*
|
||||
* @param dict The dict to copy into the new StringToStringMap.
|
||||
* @return A reference to StringToStringMap
|
||||
*/
|
||||
extern StringToStringMap* _Nullable FPREncodeStringToStringMap(NSDictionary* _Nullable dict);
|
||||
|
||||
/** Callocs a nanopb StringToNumberMap and copies the given NSDictionary bytes into the
|
||||
* StringToStringMap.
|
||||
*
|
||||
* @param dict The dict to copy into the new StringToNumberMap.
|
||||
* @return A reference to StringToNumberMap
|
||||
*/
|
||||
extern StringToNumberMap* _Nullable FPREncodeStringToNumberMap(NSDictionary* _Nullable dict);
|
||||
|
||||
/** Creates a new firebase_perf_v1_PerfMetric struct populated with system metadata.
|
||||
* @param appID The Google app id to put into the message
|
||||
* @return A firebase_perf_v1_PerfMetric struct.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
extern firebase_perf_v1_PerfMetric FPRGetPerfMetricMessage(NSString* _Nonnull appID);
|
||||
|
||||
/** Creates a new firebase_perf_v1_ApplicationInfo struct populated with system metadata.
|
||||
* @return A firebase_perf_v1_ApplicationInfo struct.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
extern firebase_perf_v1_ApplicationInfo FPRGetApplicationInfoMessage(void);
|
||||
|
||||
/** Converts the FIRTrace object to a firebase_perf_v1_TraceMetric struct.
|
||||
* @return A firebase_perf_v1_TraceMetric struct.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
extern firebase_perf_v1_TraceMetric FPRGetTraceMetric(FIRTrace* _Nonnull trace);
|
||||
|
||||
/** Converts the FPRNetworkTrace object to a firebase_perf_v1_NetworkRequestMetric struct.
|
||||
* @return A firebase_perf_v1_NetworkRequestMetric struct.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
extern firebase_perf_v1_NetworkRequestMetric FPRGetNetworkRequestMetric(
|
||||
FPRNetworkTrace* _Nonnull trace);
|
||||
|
||||
/** Converts the gaugeData array object to a firebase_perf_v1_GaugeMetric struct.
|
||||
* @return A firebase_perf_v1_GaugeMetric struct.
|
||||
*/
|
||||
extern firebase_perf_v1_GaugeMetric FPRGetGaugeMetric(NSArray* _Nonnull gaugeData,
|
||||
NSString* _Nonnull sessionId);
|
||||
|
||||
/** Converts the FPRTraceState to a firebase_perf_v1_ApplicationProcessState struct.
|
||||
* @return A firebase_perf_v1_ApplicationProcessState struct.
|
||||
*/
|
||||
extern firebase_perf_v1_ApplicationProcessState FPRApplicationProcessState(FPRTraceState state);
|
||||
|
||||
/** Populate a firebase_perf_v1_PerfMetric object with the given firebase_perf_v1_ApplicationInfo.
|
||||
*
|
||||
* @param perfMetric The reference to a firebase_perf_v1_PerfMetric object to be populated.
|
||||
* @param appInfo The firebase_perf_v1_ApplicationInfo object that will be added to
|
||||
* firebase_perf_v1_PerfMetric.
|
||||
*/
|
||||
extern void FPRSetApplicationInfo(firebase_perf_v1_PerfMetric* _Nonnull perfMetric,
|
||||
firebase_perf_v1_ApplicationInfo appInfo);
|
||||
|
||||
/** Populate a firebase_perf_v1_PerfMetric object with the given firebase_perf_v1_TraceMetric.
|
||||
*
|
||||
* @param perfMetric The reference to firebase_perf_v1_PerfMetric to be populated.
|
||||
* @param traceMetric The firebase_perf_v1_TraceMetric object that will be added to
|
||||
* firebase_perf_v1_PerfMetric.
|
||||
*/
|
||||
extern void FPRSetTraceMetric(firebase_perf_v1_PerfMetric* _Nonnull perfMetric,
|
||||
firebase_perf_v1_TraceMetric traceMetric);
|
||||
|
||||
/** Populate a firebase_perf_v1_PerfMetric object with the given
|
||||
* firebase_perf_v1_NetworkRequestMetric.
|
||||
*
|
||||
* @param perfMetric The reference to a firebase_perf_v1_PerfMetric object to be populated.
|
||||
* @param networkMetric The firebase_perf_v1_NetworkRequestMetric object that will be added to
|
||||
* firebase_perf_v1_PerfMetric.
|
||||
*/
|
||||
extern void FPRSetNetworkRequestMetric(firebase_perf_v1_PerfMetric* _Nonnull perfMetric,
|
||||
firebase_perf_v1_NetworkRequestMetric networkMetric);
|
||||
|
||||
/** Populate a firebase_perf_v1_PerfMetric object with the given firebase_perf_v1_GaugeMetric.
|
||||
*
|
||||
* @param perfMetric The reference to a firebase_perf_v1_PerfMetric object to be populated.
|
||||
* @param gaugeMetric The firebase_perf_v1_GaugeMetric object that will be added to
|
||||
* firebase_perf_v1_PerfMetric.
|
||||
*/
|
||||
extern void FPRSetGaugeMetric(firebase_perf_v1_PerfMetric* _Nonnull perfMetric,
|
||||
firebase_perf_v1_GaugeMetric gaugeMetric);
|
||||
|
||||
/** Populate a firebase_perf_v1_PerfMetric object with the given
|
||||
* firebase_perf_v1_ApplicationProcessState.
|
||||
*
|
||||
* @param perfMetric The reference to a firebase_perf_v1_PerfMetric object to be populated.
|
||||
* @param state The firebase_perf_v1_ApplicationProcessState object that will be added to
|
||||
* firebase_perf_v1_PerfMetric.
|
||||
*/
|
||||
extern void FPRSetApplicationProcessState(firebase_perf_v1_PerfMetric* _Nonnull perfMetric,
|
||||
firebase_perf_v1_ApplicationProcessState state);
|
||||
|
||||
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
/** Obtain a CTTelephonyNetworkInfo object to determine device network attributes.
|
||||
* @return CTTelephonyNetworkInfo object.
|
||||
*/
|
||||
extern CTTelephonyNetworkInfo* _Nullable FPRNetworkInfo(void);
|
||||
#endif
|
||||
472
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRNanoPbUtils.m
generated
Normal file
472
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRNanoPbUtils.m
generated
Normal file
@ -0,0 +1,472 @@
|
||||
// Copyright 2021 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRNanoPbUtils.h"
|
||||
|
||||
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
#import <CoreTelephony/CTCarrier.h>
|
||||
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
||||
#endif
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/FIRPerformance+Internal.h"
|
||||
#import "FirebasePerformance/Sources/FPRDataUtils.h"
|
||||
#import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
|
||||
#import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h"
|
||||
|
||||
#define BYTES_TO_KB(x) (x / 1024)
|
||||
|
||||
static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
|
||||
NSString *methodString);
|
||||
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkType(void);
|
||||
#endif
|
||||
NSArray<FPRSessionDetails *> *FPRMakeFirstSessionVerbose(NSArray<FPRSessionDetails *> *sessions);
|
||||
|
||||
#pragma mark - Nanopb creation utilities
|
||||
|
||||
/** Converts the network method string to a value defined in the enum
|
||||
* firebase_perf_v1_NetworkRequestMetric_HttpMethod.
|
||||
* @return Enum value of the method string. If there is no mapping value defined for the method
|
||||
* firebase_perf_v1_NetworkRequestMetric_HttpMethod_HTTP_METHOD_UNKNOWN is returned.
|
||||
*/
|
||||
static firebase_perf_v1_NetworkRequestMetric_HttpMethod FPRHTTPMethodForString(
|
||||
NSString *methodString) {
|
||||
static NSDictionary<NSString *, NSNumber *> *HTTPToFPRNetworkTraceMethod;
|
||||
static dispatch_once_t onceToken = 0;
|
||||
dispatch_once(&onceToken, ^{
|
||||
HTTPToFPRNetworkTraceMethod = @{
|
||||
@"GET" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_GET),
|
||||
@"POST" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_POST),
|
||||
@"PUT" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_PUT),
|
||||
@"DELETE" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_DELETE),
|
||||
@"HEAD" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_HEAD),
|
||||
@"PATCH" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_PATCH),
|
||||
@"OPTIONS" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_OPTIONS),
|
||||
@"TRACE" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_TRACE),
|
||||
@"CONNECT" : @(firebase_perf_v1_NetworkRequestMetric_HttpMethod_CONNECT),
|
||||
};
|
||||
});
|
||||
|
||||
NSNumber *HTTPMethod = HTTPToFPRNetworkTraceMethod[methodString];
|
||||
if (HTTPMethod == nil) {
|
||||
return firebase_perf_v1_NetworkRequestMetric_HttpMethod_HTTP_METHOD_UNKNOWN;
|
||||
}
|
||||
return HTTPMethod.intValue;
|
||||
}
|
||||
|
||||
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
/** Get the current cellular network connection type in
|
||||
* firebase_perf_v1_NetworkConnectionInfo_MobileSubtype format.
|
||||
* @return Current cellular network connection type.
|
||||
*/
|
||||
static firebase_perf_v1_NetworkConnectionInfo_MobileSubtype FPRCellularNetworkType(void) {
|
||||
static NSDictionary<NSString *, NSNumber *> *cellularNetworkToMobileSubtype;
|
||||
static dispatch_once_t onceToken = 0;
|
||||
dispatch_once(&onceToken, ^{
|
||||
cellularNetworkToMobileSubtype = @{
|
||||
CTRadioAccessTechnologyGPRS : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_GPRS),
|
||||
CTRadioAccessTechnologyEdge : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EDGE),
|
||||
CTRadioAccessTechnologyWCDMA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_CDMA),
|
||||
CTRadioAccessTechnologyHSDPA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_HSDPA),
|
||||
CTRadioAccessTechnologyHSUPA : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_HSUPA),
|
||||
CTRadioAccessTechnologyCDMA1x : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_CDMA),
|
||||
CTRadioAccessTechnologyCDMAEVDORev0 :
|
||||
@(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_0),
|
||||
CTRadioAccessTechnologyCDMAEVDORevA :
|
||||
@(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_A),
|
||||
CTRadioAccessTechnologyCDMAEVDORevB :
|
||||
@(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EVDO_B),
|
||||
CTRadioAccessTechnologyeHRPD : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_EHRPD),
|
||||
CTRadioAccessTechnologyLTE : @(firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_LTE)
|
||||
};
|
||||
});
|
||||
|
||||
NSDictionary<NSString *, NSString *> *radioAccessors =
|
||||
FPRNetworkInfo().serviceCurrentRadioAccessTechnology;
|
||||
if (radioAccessors.count > 0) {
|
||||
NSString *networkString = [radioAccessors.allValues objectAtIndex:0];
|
||||
NSNumber *cellularNetworkType = cellularNetworkToMobileSubtype[networkString];
|
||||
return cellularNetworkType.intValue;
|
||||
}
|
||||
|
||||
return firebase_perf_v1_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma mark - Nanopb decode and encode helper methods
|
||||
|
||||
pb_bytes_array_t *FPREncodeData(NSData *data) {
|
||||
pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length));
|
||||
if (pbBytesArray != NULL) {
|
||||
[data getBytes:pbBytesArray->bytes length:data.length];
|
||||
pbBytesArray->size = (pb_size_t)data.length;
|
||||
}
|
||||
return pbBytesArray;
|
||||
}
|
||||
|
||||
pb_bytes_array_t *FPREncodeString(NSString *string) {
|
||||
NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||
return FPREncodeData(stringBytes);
|
||||
}
|
||||
|
||||
StringToStringMap *_Nullable FPREncodeStringToStringMap(NSDictionary *_Nullable dict) {
|
||||
StringToStringMap *map = calloc(dict.count, sizeof(StringToStringMap));
|
||||
__block NSUInteger index = 0;
|
||||
[dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
|
||||
map[index].key = FPREncodeString(key);
|
||||
map[index].value = FPREncodeString(value);
|
||||
index++;
|
||||
}];
|
||||
return map;
|
||||
}
|
||||
|
||||
StringToNumberMap *_Nullable FPREncodeStringToNumberMap(NSDictionary *_Nullable dict) {
|
||||
StringToNumberMap *map = calloc(dict.count, sizeof(StringToNumberMap));
|
||||
__block NSUInteger index = 0;
|
||||
[dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *value, BOOL *stop) {
|
||||
map[index].key = FPREncodeString(key);
|
||||
map[index].value = [value longLongValue];
|
||||
map[index].has_value = true;
|
||||
index++;
|
||||
}];
|
||||
return map;
|
||||
}
|
||||
|
||||
firebase_perf_v1_PerfSession *FPREncodePerfSessions(NSArray<FPRSessionDetails *> *sessions,
|
||||
NSInteger count) {
|
||||
firebase_perf_v1_PerfSession *perfSessions = calloc(count, sizeof(firebase_perf_v1_PerfSession));
|
||||
__block NSUInteger perfSessionIndex = 0;
|
||||
|
||||
[sessions enumerateObjectsUsingBlock:^(FPRSessionDetails *_Nonnull session, NSUInteger index,
|
||||
BOOL *_Nonnull stop) {
|
||||
perfSessions[perfSessionIndex].session_id = FPREncodeString(session.sessionId);
|
||||
perfSessions[perfSessionIndex].session_verbosity_count = 0;
|
||||
if ((session.options & FPRSessionOptionsEvents) ||
|
||||
(session.options & FPRSessionOptionsGauges)) {
|
||||
perfSessions[perfSessionIndex].session_verbosity_count = 1;
|
||||
perfSessions[perfSessionIndex].session_verbosity =
|
||||
calloc(perfSessions[perfSessionIndex].session_verbosity_count,
|
||||
sizeof(firebase_perf_v1_SessionVerbosity));
|
||||
perfSessions[perfSessionIndex].session_verbosity[0] =
|
||||
firebase_perf_v1_SessionVerbosity_GAUGES_AND_SYSTEM_EVENTS;
|
||||
}
|
||||
perfSessionIndex++;
|
||||
}];
|
||||
return perfSessions;
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
firebase_perf_v1_PerfMetric FPRGetPerfMetricMessage(NSString *appID) {
|
||||
firebase_perf_v1_PerfMetric perfMetricMessage = firebase_perf_v1_PerfMetric_init_default;
|
||||
FPRSetApplicationInfo(&perfMetricMessage, FPRGetApplicationInfoMessage());
|
||||
perfMetricMessage.application_info.google_app_id = FPREncodeString(appID);
|
||||
|
||||
return perfMetricMessage;
|
||||
}
|
||||
|
||||
firebase_perf_v1_ApplicationInfo FPRGetApplicationInfoMessage(void) {
|
||||
firebase_perf_v1_ApplicationInfo appInfoMessage = firebase_perf_v1_ApplicationInfo_init_default;
|
||||
firebase_perf_v1_IosApplicationInfo iosAppInfo = firebase_perf_v1_IosApplicationInfo_init_default;
|
||||
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||
iosAppInfo.bundle_short_version =
|
||||
FPREncodeString([mainBundle infoDictionary][@"CFBundleShortVersionString"]);
|
||||
iosAppInfo.sdk_version = FPREncodeString([NSString stringWithUTF8String:kFPRSDKVersion]);
|
||||
iosAppInfo.network_connection_info.network_type =
|
||||
[FPRAppActivityTracker sharedInstance].networkType;
|
||||
iosAppInfo.has_network_connection_info = true;
|
||||
iosAppInfo.network_connection_info.has_network_type = true;
|
||||
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
if (iosAppInfo.network_connection_info.network_type ==
|
||||
firebase_perf_v1_NetworkConnectionInfo_NetworkType_MOBILE) {
|
||||
iosAppInfo.network_connection_info.mobile_subtype = FPRCellularNetworkType();
|
||||
iosAppInfo.network_connection_info.has_mobile_subtype = true;
|
||||
}
|
||||
#endif
|
||||
appInfoMessage.ios_app_info = iosAppInfo;
|
||||
appInfoMessage.has_ios_app_info = true;
|
||||
|
||||
NSDictionary<NSString *, NSString *> *attributes =
|
||||
[[FIRPerformance sharedInstance].attributes mutableCopy];
|
||||
appInfoMessage.custom_attributes_count = (pb_size_t)attributes.count;
|
||||
appInfoMessage.custom_attributes =
|
||||
(firebase_perf_v1_ApplicationInfo_CustomAttributesEntry *)FPREncodeStringToStringMap(
|
||||
attributes);
|
||||
|
||||
return appInfoMessage;
|
||||
}
|
||||
|
||||
firebase_perf_v1_TraceMetric FPRGetTraceMetric(FIRTrace *trace) {
|
||||
firebase_perf_v1_TraceMetric traceMetric = firebase_perf_v1_TraceMetric_init_default;
|
||||
traceMetric.name = FPREncodeString(trace.name);
|
||||
|
||||
// Set if the trace is an internally created trace.
|
||||
traceMetric.is_auto = trace.isInternal;
|
||||
traceMetric.has_is_auto = true;
|
||||
|
||||
// Convert the trace duration from seconds to microseconds.
|
||||
traceMetric.duration_us = trace.totalTraceTimeInterval * USEC_PER_SEC;
|
||||
traceMetric.has_duration_us = true;
|
||||
|
||||
// Convert the start time from seconds to microseconds.
|
||||
traceMetric.client_start_time_us = trace.startTimeSinceEpoch * USEC_PER_SEC;
|
||||
traceMetric.has_client_start_time_us = true;
|
||||
|
||||
// Filling counters
|
||||
NSDictionary<NSString *, NSNumber *> *counters = trace.counters;
|
||||
traceMetric.counters_count = (pb_size_t)counters.count;
|
||||
traceMetric.counters =
|
||||
(firebase_perf_v1_TraceMetric_CountersEntry *)FPREncodeStringToNumberMap(counters);
|
||||
|
||||
// Filling subtraces
|
||||
traceMetric.subtraces_count = (pb_size_t)[trace.stages count];
|
||||
firebase_perf_v1_TraceMetric *subtraces =
|
||||
calloc(traceMetric.subtraces_count, sizeof(firebase_perf_v1_TraceMetric));
|
||||
__block NSUInteger subtraceIndex = 0;
|
||||
[trace.stages
|
||||
enumerateObjectsUsingBlock:^(FIRTrace *_Nonnull stage, NSUInteger idx, BOOL *_Nonnull stop) {
|
||||
subtraces[subtraceIndex] = FPRGetTraceMetric(stage);
|
||||
subtraceIndex++;
|
||||
}];
|
||||
traceMetric.subtraces = subtraces;
|
||||
|
||||
// Filling custom attributes
|
||||
NSDictionary<NSString *, NSString *> *attributes = [trace.attributes mutableCopy];
|
||||
traceMetric.custom_attributes_count = (pb_size_t)attributes.count;
|
||||
traceMetric.custom_attributes =
|
||||
(firebase_perf_v1_TraceMetric_CustomAttributesEntry *)FPREncodeStringToStringMap(attributes);
|
||||
|
||||
// Filling session details
|
||||
NSArray<FPRSessionDetails *> *orderedSessions = FPRMakeFirstSessionVerbose(trace.sessions);
|
||||
traceMetric.perf_sessions_count = (pb_size_t)[orderedSessions count];
|
||||
traceMetric.perf_sessions =
|
||||
FPREncodePerfSessions(orderedSessions, traceMetric.perf_sessions_count);
|
||||
|
||||
return traceMetric;
|
||||
}
|
||||
|
||||
firebase_perf_v1_NetworkRequestMetric FPRGetNetworkRequestMetric(FPRNetworkTrace *trace) {
|
||||
firebase_perf_v1_NetworkRequestMetric networkMetric =
|
||||
firebase_perf_v1_NetworkRequestMetric_init_default;
|
||||
networkMetric.url = FPREncodeString(trace.trimmedURLString);
|
||||
networkMetric.http_method = FPRHTTPMethodForString(trace.URLRequest.HTTPMethod);
|
||||
networkMetric.has_http_method = true;
|
||||
|
||||
// Convert the start time from seconds to microseconds.
|
||||
networkMetric.client_start_time_us = trace.startTimeSinceEpoch * USEC_PER_SEC;
|
||||
networkMetric.has_client_start_time_us = true;
|
||||
|
||||
networkMetric.request_payload_bytes = trace.requestSize;
|
||||
networkMetric.has_request_payload_bytes = true;
|
||||
networkMetric.response_payload_bytes = trace.responseSize;
|
||||
networkMetric.has_response_payload_bytes = true;
|
||||
|
||||
networkMetric.http_response_code = trace.responseCode;
|
||||
networkMetric.has_http_response_code = true;
|
||||
networkMetric.response_content_type = FPREncodeString(trace.responseContentType);
|
||||
|
||||
if (trace.responseError) {
|
||||
networkMetric.network_client_error_reason =
|
||||
firebase_perf_v1_NetworkRequestMetric_NetworkClientErrorReason_GENERIC_CLIENT_ERROR;
|
||||
networkMetric.has_network_client_error_reason = true;
|
||||
}
|
||||
|
||||
NSTimeInterval requestTimeUs =
|
||||
USEC_PER_SEC *
|
||||
[trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
|
||||
andState:FPRNetworkTraceCheckpointStateRequestCompleted];
|
||||
if (requestTimeUs > 0) {
|
||||
networkMetric.time_to_request_completed_us = requestTimeUs;
|
||||
networkMetric.has_time_to_request_completed_us = true;
|
||||
}
|
||||
|
||||
NSTimeInterval responseIntiationTimeUs =
|
||||
USEC_PER_SEC *
|
||||
[trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
|
||||
andState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
if (responseIntiationTimeUs > 0) {
|
||||
networkMetric.time_to_response_initiated_us = responseIntiationTimeUs;
|
||||
networkMetric.has_time_to_response_initiated_us = true;
|
||||
}
|
||||
|
||||
NSTimeInterval responseCompletedUs =
|
||||
USEC_PER_SEC *
|
||||
[trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
|
||||
andState:FPRNetworkTraceCheckpointStateResponseCompleted];
|
||||
if (responseCompletedUs > 0) {
|
||||
networkMetric.time_to_response_completed_us = responseCompletedUs;
|
||||
networkMetric.has_time_to_response_completed_us = true;
|
||||
}
|
||||
|
||||
// Filling custom attributes
|
||||
NSDictionary<NSString *, NSString *> *attributes = [trace.attributes mutableCopy];
|
||||
networkMetric.custom_attributes_count = (pb_size_t)attributes.count;
|
||||
networkMetric.custom_attributes =
|
||||
(firebase_perf_v1_NetworkRequestMetric_CustomAttributesEntry *)FPREncodeStringToStringMap(
|
||||
attributes);
|
||||
|
||||
// Filling session details
|
||||
NSArray<FPRSessionDetails *> *orderedSessions = FPRMakeFirstSessionVerbose(trace.sessions);
|
||||
networkMetric.perf_sessions_count = (pb_size_t)[orderedSessions count];
|
||||
networkMetric.perf_sessions =
|
||||
FPREncodePerfSessions(orderedSessions, networkMetric.perf_sessions_count);
|
||||
|
||||
return networkMetric;
|
||||
}
|
||||
|
||||
firebase_perf_v1_GaugeMetric FPRGetGaugeMetric(NSArray *gaugeData, NSString *sessionId) {
|
||||
firebase_perf_v1_GaugeMetric gaugeMetric = firebase_perf_v1_GaugeMetric_init_default;
|
||||
gaugeMetric.session_id = FPREncodeString(sessionId);
|
||||
|
||||
__block NSInteger cpuReadingsCount = 0;
|
||||
__block NSInteger memoryReadingsCount = 0;
|
||||
|
||||
firebase_perf_v1_CpuMetricReading *cpuReadings =
|
||||
calloc([gaugeData count], sizeof(firebase_perf_v1_CpuMetricReading));
|
||||
firebase_perf_v1_IosMemoryReading *memoryReadings =
|
||||
calloc([gaugeData count], sizeof(firebase_perf_v1_IosMemoryReading));
|
||||
[gaugeData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if ([obj isKindOfClass:[FPRCPUGaugeData class]]) {
|
||||
FPRCPUGaugeData *gaugeData = (FPRCPUGaugeData *)obj;
|
||||
cpuReadings[cpuReadingsCount].client_time_us =
|
||||
gaugeData.collectionTime.timeIntervalSince1970 * USEC_PER_SEC;
|
||||
cpuReadings[cpuReadingsCount].has_client_time_us = true;
|
||||
cpuReadings[cpuReadingsCount].system_time_us = gaugeData.systemTime;
|
||||
cpuReadings[cpuReadingsCount].has_system_time_us = true;
|
||||
cpuReadings[cpuReadingsCount].user_time_us = gaugeData.userTime;
|
||||
cpuReadings[cpuReadingsCount].has_user_time_us = true;
|
||||
cpuReadingsCount++;
|
||||
}
|
||||
|
||||
if ([obj isKindOfClass:[FPRMemoryGaugeData class]]) {
|
||||
FPRMemoryGaugeData *gaugeData = (FPRMemoryGaugeData *)obj;
|
||||
memoryReadings[memoryReadingsCount].client_time_us =
|
||||
gaugeData.collectionTime.timeIntervalSince1970 * USEC_PER_SEC;
|
||||
memoryReadings[memoryReadingsCount].has_client_time_us = true;
|
||||
memoryReadings[memoryReadingsCount].used_app_heap_memory_kb =
|
||||
(int32_t)BYTES_TO_KB(gaugeData.heapUsed);
|
||||
memoryReadings[memoryReadingsCount].has_used_app_heap_memory_kb = true;
|
||||
memoryReadings[memoryReadingsCount].free_app_heap_memory_kb =
|
||||
(int32_t)BYTES_TO_KB(gaugeData.heapAvailable);
|
||||
memoryReadings[memoryReadingsCount].has_free_app_heap_memory_kb = true;
|
||||
memoryReadingsCount++;
|
||||
}
|
||||
}];
|
||||
cpuReadings = realloc(cpuReadings, cpuReadingsCount * sizeof(firebase_perf_v1_CpuMetricReading));
|
||||
memoryReadings =
|
||||
realloc(memoryReadings, memoryReadingsCount * sizeof(firebase_perf_v1_IosMemoryReading));
|
||||
|
||||
gaugeMetric.cpu_metric_readings = cpuReadings;
|
||||
gaugeMetric.cpu_metric_readings_count = (pb_size_t)cpuReadingsCount;
|
||||
gaugeMetric.ios_memory_readings = memoryReadings;
|
||||
gaugeMetric.ios_memory_readings_count = (pb_size_t)memoryReadingsCount;
|
||||
return gaugeMetric;
|
||||
}
|
||||
|
||||
firebase_perf_v1_ApplicationProcessState FPRApplicationProcessState(FPRTraceState state) {
|
||||
firebase_perf_v1_ApplicationProcessState processState =
|
||||
firebase_perf_v1_ApplicationProcessState_APPLICATION_PROCESS_STATE_UNKNOWN;
|
||||
switch (state) {
|
||||
case FPRTraceStateForegroundOnly:
|
||||
processState = firebase_perf_v1_ApplicationProcessState_FOREGROUND;
|
||||
break;
|
||||
|
||||
case FPRTraceStateBackgroundOnly:
|
||||
processState = firebase_perf_v1_ApplicationProcessState_BACKGROUND;
|
||||
break;
|
||||
|
||||
case FPRTraceStateBackgroundAndForeground:
|
||||
processState = firebase_perf_v1_ApplicationProcessState_FOREGROUND_BACKGROUND;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return processState;
|
||||
}
|
||||
|
||||
#ifdef TARGET_HAS_MOBILE_CONNECTIVITY
|
||||
CTTelephonyNetworkInfo *FPRNetworkInfo(void) {
|
||||
static CTTelephonyNetworkInfo *networkInfo;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
networkInfo = [[CTTelephonyNetworkInfo alloc] init];
|
||||
});
|
||||
return networkInfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Reorders the list of sessions to make sure the first session is verbose if at least one session
|
||||
* in the list is verbose.
|
||||
* @return Ordered list of sessions.
|
||||
*/
|
||||
NSArray<FPRSessionDetails *> *FPRMakeFirstSessionVerbose(NSArray<FPRSessionDetails *> *sessions) {
|
||||
NSMutableArray<FPRSessionDetails *> *orderedSessions =
|
||||
[[NSMutableArray<FPRSessionDetails *> alloc] initWithArray:sessions];
|
||||
|
||||
NSInteger firstVerboseSessionIndex = -1;
|
||||
for (int i = 0; i < [sessions count]; i++) {
|
||||
if ([sessions[i] isVerbose]) {
|
||||
firstVerboseSessionIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstVerboseSessionIndex > 0) {
|
||||
FPRSessionDetails *verboseSession = orderedSessions[firstVerboseSessionIndex];
|
||||
[orderedSessions removeObjectAtIndex:firstVerboseSessionIndex];
|
||||
[orderedSessions insertObject:verboseSession atIndex:0];
|
||||
}
|
||||
|
||||
return [orderedSessions copy];
|
||||
}
|
||||
|
||||
#pragma mark - Nanopb struct fields populating helper methods
|
||||
|
||||
void FPRSetApplicationInfo(firebase_perf_v1_PerfMetric *perfMetric,
|
||||
firebase_perf_v1_ApplicationInfo appInfo) {
|
||||
perfMetric->application_info = appInfo;
|
||||
perfMetric->has_application_info = true;
|
||||
}
|
||||
|
||||
void FPRSetTraceMetric(firebase_perf_v1_PerfMetric *perfMetric,
|
||||
firebase_perf_v1_TraceMetric traceMetric) {
|
||||
perfMetric->trace_metric = traceMetric;
|
||||
perfMetric->has_trace_metric = true;
|
||||
}
|
||||
|
||||
void FPRSetNetworkRequestMetric(firebase_perf_v1_PerfMetric *perfMetric,
|
||||
firebase_perf_v1_NetworkRequestMetric networkMetric) {
|
||||
perfMetric->network_request_metric = networkMetric;
|
||||
perfMetric->has_network_request_metric = true;
|
||||
}
|
||||
|
||||
void FPRSetGaugeMetric(firebase_perf_v1_PerfMetric *perfMetric,
|
||||
firebase_perf_v1_GaugeMetric gaugeMetric) {
|
||||
perfMetric->gauge_metric = gaugeMetric;
|
||||
perfMetric->has_gauge_metric = true;
|
||||
}
|
||||
|
||||
void FPRSetApplicationProcessState(firebase_perf_v1_PerfMetric *perfMetric,
|
||||
firebase_perf_v1_ApplicationProcessState state) {
|
||||
perfMetric->application_info.application_process_state = state;
|
||||
perfMetric->application_info.has_application_process_state = true;
|
||||
}
|
||||
43
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRURLFilter.h
generated
Normal file
43
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRURLFilter.h
generated
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Allows the filtering of URLs based on a allowlist specified in the Info.plist. */
|
||||
@interface FPRURLFilter : NSObject
|
||||
|
||||
/** Returns a singleton URL filterer.
|
||||
*
|
||||
* @return The singleton instance. */
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/** Default initializer is disabled.
|
||||
*/
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Checks the allowlist and denylist, and returns a YES or NO depending on their state.
|
||||
*
|
||||
* @note The current implementation is very naive. The denylist is only set by the SDK, and these
|
||||
* URLs will not be allowed, even if we explicitly allow them.
|
||||
*
|
||||
* @param URL The URL string to check.
|
||||
* @return YES if the URL should be instrumented, NO otherwise.
|
||||
*/
|
||||
- (BOOL)shouldInstrumentURL:(NSString *)URL;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
147
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRURLFilter.m
generated
Normal file
147
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRURLFilter.m
generated
Normal file
@ -0,0 +1,147 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/FPRURLFilter.h"
|
||||
#import "FirebasePerformance/Sources/FPRURLFilter_Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
#import <GoogleDataTransport/GoogleDataTransport.h>
|
||||
|
||||
/** The expected key of the domain allowlist array. */
|
||||
static NSString *const kFPRAllowlistDomainsKey = @"FPRWhitelistedDomains";
|
||||
|
||||
/** Allowlist status enums. */
|
||||
typedef NS_ENUM(NSInteger, FPRURLAllowlistStatus) {
|
||||
|
||||
/** No allowlist is present, so the URL will be allowed. */
|
||||
FPRURLAllowlistStatusDoesNotExist = 1,
|
||||
|
||||
/** The URL is allowed. */
|
||||
FPRURLAllowlistStatusAllowed = 2,
|
||||
|
||||
/** The URL is NOT allowed. */
|
||||
FPRURLAllowlistStatusNotAllowed = 3
|
||||
};
|
||||
|
||||
/** Returns the set of denied URL strings.
|
||||
*
|
||||
* @return the set of denied URL strings.
|
||||
*/
|
||||
NSSet<NSString *> *GetSystemDenyListURLStrings(void) {
|
||||
// The denylist of URLs for uploading events to avoid cyclic generation of those network events.
|
||||
static NSSet *denylist = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
denylist = [[NSSet alloc] initWithArray:@[
|
||||
[[GDTCOREndpoints uploadURLForTarget:kGDTCORTargetCCT] absoluteString],
|
||||
[[GDTCOREndpoints uploadURLForTarget:kGDTCORTargetFLL] absoluteString]
|
||||
]];
|
||||
});
|
||||
return denylist;
|
||||
}
|
||||
|
||||
@implementation FPRURLFilter
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static FPRURLFilter *sharedInstance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[FPRURLFilter alloc] initWithBundle:[NSBundle mainBundle]];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBundle:(NSBundle *)bundle {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_mainBundle = bundle;
|
||||
_allowlistDomains = [self retrieveAllowlistFromPlist];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)shouldInstrumentURL:(NSString *)URL {
|
||||
if ([self isURLDeniedByTheSDK:URL]) {
|
||||
return NO;
|
||||
}
|
||||
FPRURLAllowlistStatus allowlistStatus = [self isURLAllowed:URL];
|
||||
if (allowlistStatus == FPRURLAllowlistStatusDoesNotExist) {
|
||||
return YES;
|
||||
}
|
||||
return allowlistStatus == FPRURLAllowlistStatusAllowed;
|
||||
}
|
||||
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
/** Determines if the URL is denied by the SDK.
|
||||
*
|
||||
* @param URL the URL string to check.
|
||||
* @return YES if the URL is allowed by the SDK, NO otherwise.
|
||||
*/
|
||||
- (BOOL)isURLDeniedByTheSDK:(NSString *)URL {
|
||||
BOOL shouldDenyURL = NO;
|
||||
|
||||
for (NSString *denyListURL in GetSystemDenyListURLStrings()) {
|
||||
if ([URL hasPrefix:denyListURL]) {
|
||||
shouldDenyURL = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return shouldDenyURL;
|
||||
}
|
||||
|
||||
/** Determines if the URL is allowed by the Developer.
|
||||
*
|
||||
* @param URL The URL string to check.
|
||||
* @return FPRURLAllowlistStatusAllowed if the URL is allowed,
|
||||
* FPRURLAllowlistStatusNotAllowed if the URL is not allowed, or
|
||||
* FPRURLAllowlistStatusDoesNotExist if the allowlist does not exist.
|
||||
*/
|
||||
- (FPRURLAllowlistStatus)isURLAllowed:(NSString *)URL {
|
||||
if (self.allowlistDomains && !self.disablePlist) {
|
||||
for (NSString *allowlistDomain in self.allowlistDomains) {
|
||||
NSURLComponents *components = [[NSURLComponents alloc] initWithString:URL];
|
||||
if ([components.host containsString:allowlistDomain]) {
|
||||
return FPRURLAllowlistStatusAllowed;
|
||||
}
|
||||
}
|
||||
return FPRURLAllowlistStatusNotAllowed;
|
||||
}
|
||||
return FPRURLAllowlistStatusDoesNotExist;
|
||||
}
|
||||
|
||||
/** Retrieves the allowlist from an Info.plist.
|
||||
*
|
||||
* @return An array of the allowlist values, or nil if the allowlist key is not found.
|
||||
*/
|
||||
- (nullable NSArray<NSString *> *)retrieveAllowlistFromPlist {
|
||||
NSArray<NSString *> *allowlist = nil;
|
||||
id plistObject = [self.mainBundle objectForInfoDictionaryKey:kFPRAllowlistDomainsKey];
|
||||
if (!plistObject) {
|
||||
NSBundle *localBundle = [NSBundle bundleForClass:[self class]];
|
||||
plistObject = [localBundle objectForInfoDictionaryKey:kFPRAllowlistDomainsKey];
|
||||
}
|
||||
if ([plistObject isKindOfClass:[NSArray class]]) {
|
||||
FPRLogInfo(kFPRURLAllowlistingEnabled, @"A domain allowlist was detected. Domains not "
|
||||
"explicitly allowlisted will not be instrumented.");
|
||||
allowlist = plistObject;
|
||||
}
|
||||
|
||||
return allowlist;
|
||||
}
|
||||
|
||||
@end
|
||||
45
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRURLFilter_Private.h
generated
Normal file
45
Pods/FirebasePerformance/FirebasePerformance/Sources/FPRURLFilter_Private.h
generated
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This extension should only be used for testing. */
|
||||
@interface FPRURLFilter ()
|
||||
|
||||
/** Set to YES to disable the retrieval of allowed domains from the Info.plist. This property
|
||||
* should only be used in tests in order to prevent the need for mocks.
|
||||
*/
|
||||
@property(nonatomic) BOOL disablePlist;
|
||||
|
||||
/** List of domains that are allowed for instrumenting network requests.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSArray *allowlistDomains;
|
||||
|
||||
/** NSBundle that is used for referring to allowed domains.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSBundle *mainBundle;
|
||||
|
||||
/** Custom initializer to be used in unit tests for taking in a custom bundle and return an instance
|
||||
* of FPRURLFilter.
|
||||
*
|
||||
* @param bundle Custom bundle to use for initialization.
|
||||
* @return Instance of FPRURLFilter.
|
||||
*/
|
||||
- (instancetype)initWithBundle:(NSBundle *)bundle;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
39
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector+Private.h
generated
Normal file
39
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector+Private.h
generated
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXTERN FPRCPUGaugeData *fprCollectCPUMetric(void);
|
||||
|
||||
/** This extension should only be used for testing. */
|
||||
@interface FPRCPUGaugeCollector ()
|
||||
|
||||
/** @brief Override configurations. */
|
||||
@property(nonatomic) FPRConfigurations *configurations;
|
||||
|
||||
/** @brief Stop CPU data collection. */
|
||||
- (void)stopCollecting;
|
||||
|
||||
/** @brief Resumes CPU data collection. */
|
||||
- (void)resumeCollecting;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
64
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.h
generated
Normal file
64
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.h
generated
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/FPRGaugeCollector.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FPRCPUGaugeCollector;
|
||||
|
||||
/** Delegate method for the CPU Gauge collector to report back the CPU gauge data. */
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@protocol FPRCPUGaugeCollectorDelegate
|
||||
|
||||
/**
|
||||
* Reports the collected CPU gauge data back to its delegate.
|
||||
*
|
||||
* @param collector CPU gauge collector that collected the information.
|
||||
* @param gaugeData CPU gauge data.
|
||||
*/
|
||||
- (void)cpuGaugeCollector:(FPRCPUGaugeCollector *)collector gaugeData:(FPRCPUGaugeData *)gaugeData;
|
||||
|
||||
@end
|
||||
|
||||
/** CPU Gauge collector implementation. This class collects the CPU utilization and reports back
|
||||
* to the delegate.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRCPUGaugeCollector : NSObject <FPRGaugeCollector>
|
||||
|
||||
/** Reference to the delegate object. */
|
||||
@property(nonatomic, weak, readonly) id<FPRCPUGaugeCollectorDelegate> delegate;
|
||||
|
||||
/**
|
||||
* Initializes the CPU collector object with the delegate object provided.
|
||||
*
|
||||
* @param delegate Delegate object to which the CPU gauge data is provided.
|
||||
* @return Instance of the CPU Gauge collector.
|
||||
*/
|
||||
- (instancetype)initWithDelegate:(id<FPRCPUGaugeCollectorDelegate>)delegate
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Initializer for the CPU Gauge collector. This is not available.
|
||||
*/
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
174
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.m
generated
Normal file
174
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.m
generated
Normal file
@ -0,0 +1,174 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
#import <assert.h>
|
||||
#import <mach/mach.h>
|
||||
|
||||
@interface FPRCPUGaugeCollector ()
|
||||
|
||||
/** @brief Timer property used for the frequency of CPU data collection. */
|
||||
@property(nonatomic) dispatch_source_t timerSource;
|
||||
|
||||
/** @brief Gauge collector queue on which the gauge data collected. */
|
||||
@property(nonatomic) dispatch_queue_t gaugeCollectorQueue;
|
||||
|
||||
/** @brief Boolean to see if the timer is active or paused. */
|
||||
@property(nonatomic) BOOL timerPaused;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Fetches the CPU metric and returns an instance of FPRCPUGaugeData.
|
||||
*
|
||||
* This implementation is inspired by the following references:
|
||||
* http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_basic_info.html
|
||||
* https://stackoverflow.com/a/8382889
|
||||
*
|
||||
* @return Instance of FPRCPUGaugeData.
|
||||
*/
|
||||
FPRCPUGaugeData *fprCollectCPUMetric(void) {
|
||||
kern_return_t kernelReturnValue;
|
||||
mach_msg_type_number_t task_info_count;
|
||||
task_info_data_t taskInfo;
|
||||
thread_array_t threadList;
|
||||
mach_msg_type_number_t threadCount;
|
||||
task_basic_info_t taskBasicInfo;
|
||||
thread_basic_info_t threadBasicInfo;
|
||||
|
||||
NSDate *collectionTime = [NSDate date];
|
||||
// Get the task info to find out the CPU time used by terminated threads.
|
||||
task_info_count = TASK_BASIC_INFO_COUNT;
|
||||
kernelReturnValue =
|
||||
task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)taskInfo, &task_info_count);
|
||||
if (kernelReturnValue != KERN_SUCCESS) {
|
||||
return nil;
|
||||
}
|
||||
taskBasicInfo = (task_basic_info_t)taskInfo;
|
||||
|
||||
// Get the current set of threads and find their CPU time.
|
||||
kernelReturnValue = task_threads(mach_task_self(), &threadList, &threadCount);
|
||||
if (kernelReturnValue != KERN_SUCCESS) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
uint64_t totalUserTimeUsec =
|
||||
taskBasicInfo->user_time.seconds * USEC_PER_SEC + taskBasicInfo->user_time.microseconds;
|
||||
uint64_t totalSystemTimeUsec =
|
||||
taskBasicInfo->system_time.seconds * USEC_PER_SEC + taskBasicInfo->system_time.microseconds;
|
||||
thread_info_data_t threadInfo;
|
||||
mach_msg_type_number_t threadInfoCount;
|
||||
|
||||
for (int i = 0; i < (int)threadCount; i++) {
|
||||
threadInfoCount = THREAD_INFO_MAX;
|
||||
kernelReturnValue =
|
||||
thread_info(threadList[i], THREAD_BASIC_INFO, (thread_info_t)threadInfo, &threadInfoCount);
|
||||
if (kernelReturnValue != KERN_SUCCESS) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
threadBasicInfo = (thread_basic_info_t)threadInfo;
|
||||
if (!(threadBasicInfo->flags & TH_FLAGS_IDLE)) {
|
||||
totalUserTimeUsec += threadBasicInfo->user_time.seconds * USEC_PER_SEC +
|
||||
threadBasicInfo->user_time.microseconds;
|
||||
totalSystemTimeUsec += threadBasicInfo->system_time.seconds * USEC_PER_SEC +
|
||||
threadBasicInfo->system_time.microseconds;
|
||||
}
|
||||
}
|
||||
|
||||
kernelReturnValue =
|
||||
vm_deallocate(mach_task_self(), (vm_offset_t)threadList, threadCount * sizeof(thread_t));
|
||||
assert(kernelReturnValue == KERN_SUCCESS);
|
||||
|
||||
FPRCPUGaugeData *gaugeData = [[FPRCPUGaugeData alloc] initWithCollectionTime:collectionTime
|
||||
systemTime:totalSystemTimeUsec
|
||||
userTime:totalUserTimeUsec];
|
||||
return gaugeData;
|
||||
}
|
||||
|
||||
@implementation FPRCPUGaugeCollector
|
||||
|
||||
- (instancetype)initWithDelegate:(id<FPRCPUGaugeCollectorDelegate>)delegate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_delegate = delegate;
|
||||
_gaugeCollectorQueue =
|
||||
dispatch_queue_create("com.google.firebase.FPRCPUGaugeCollector", DISPATCH_QUEUE_SERIAL);
|
||||
_configurations = [FPRConfigurations sharedInstance];
|
||||
_timerPaused = YES;
|
||||
[self updateSamplingFrequencyForApplicationState:[FPRAppActivityTracker sharedInstance]
|
||||
.applicationState];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)stopCollecting {
|
||||
if (self.timerPaused == NO) {
|
||||
dispatch_source_cancel(self.timerSource);
|
||||
self.timerPaused = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resumeCollecting {
|
||||
[self updateSamplingFrequencyForApplicationState:[FPRAppActivityTracker sharedInstance]
|
||||
.applicationState];
|
||||
}
|
||||
|
||||
- (void)updateSamplingFrequencyForApplicationState:(FPRApplicationState)applicationState {
|
||||
uint32_t frequencyInMs = (applicationState == FPRApplicationStateBackground)
|
||||
? [self.configurations cpuSamplingFrequencyInBackgroundInMS]
|
||||
: [self.configurations cpuSamplingFrequencyInForegroundInMS];
|
||||
[self captureCPUGaugeAtFrequency:frequencyInMs];
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures the CPU gauge at a defined frequency.
|
||||
*
|
||||
* @param frequencyInMs Frequency at which the CPU gauges are collected.
|
||||
*/
|
||||
- (void)captureCPUGaugeAtFrequency:(uint32_t)frequencyInMs {
|
||||
[self stopCollecting];
|
||||
if (frequencyInMs > 0) {
|
||||
self.timerSource =
|
||||
dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.gaugeCollectorQueue);
|
||||
dispatch_source_set_timer(self.timerSource,
|
||||
dispatch_time(DISPATCH_TIME_NOW, frequencyInMs * NSEC_PER_MSEC),
|
||||
frequencyInMs * NSEC_PER_MSEC, (1ull * NSEC_PER_SEC) / 10);
|
||||
FPRCPUGaugeCollector __weak *weakSelf = self;
|
||||
dispatch_source_set_event_handler(weakSelf.timerSource, ^{
|
||||
FPRCPUGaugeCollector *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
[strongSelf collectMetric];
|
||||
}
|
||||
});
|
||||
dispatch_resume(self.timerSource);
|
||||
self.timerPaused = NO;
|
||||
} else {
|
||||
FPRLogDebug(kFPRCPUCollection, @"CPU metric collection is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)collectMetric {
|
||||
FPRCPUGaugeData *gaugeMetric = fprCollectCPUMetric();
|
||||
[self.delegate cpuGaugeCollector:self gaugeData:gaugeMetric];
|
||||
}
|
||||
|
||||
@end
|
||||
49
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h
generated
Normal file
49
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h
generated
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Class that contains CPU gauge information for any point in time.
|
||||
*/
|
||||
@interface FPRCPUGaugeData : NSObject
|
||||
|
||||
/** @brief Time which which CPU data was measured. */
|
||||
@property(nonatomic, readonly) NSDate *collectionTime;
|
||||
|
||||
/** @brief CPU system time used in microseconds. */
|
||||
@property(nonatomic, readonly) uint64_t systemTime;
|
||||
|
||||
/** @brief CPU user time used in microseconds. */
|
||||
@property(nonatomic, readonly) uint64_t userTime;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Creates an instance of CPU gauge data with the provided information.
|
||||
*
|
||||
* @param collectionTime Time at which the gauge data was collected.
|
||||
* @param systemTime CPU system time in microseconds.
|
||||
* @param userTime CPU user time in microseconds.
|
||||
* @return Instance of CPU gauge data.
|
||||
*/
|
||||
- (instancetype)initWithCollectionTime:(NSDate *)collectionTime
|
||||
systemTime:(uint64_t)systemTime
|
||||
userTime:(uint64_t)userTime NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
31
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.m
generated
Normal file
31
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.m
generated
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h"
|
||||
|
||||
@implementation FPRCPUGaugeData
|
||||
|
||||
- (instancetype)initWithCollectionTime:(NSDate *)collectionTime
|
||||
systemTime:(uint64_t)systemTime
|
||||
userTime:(uint64_t)userTime {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_collectionTime = collectionTime;
|
||||
_systemTime = systemTime;
|
||||
_userTime = userTime;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
34
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeCollector.h
generated
Normal file
34
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeCollector.h
generated
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRAppActivityTracker.h"
|
||||
|
||||
@protocol FPRGaugeCollector <NSObject>
|
||||
|
||||
/** Initiates a fetch for the gauge metric. */
|
||||
- (void)collectMetric;
|
||||
|
||||
/**
|
||||
* Adapts to application state and starts capturing the gauge metric at a pre-configured rate as
|
||||
* defined in the configuration system.
|
||||
*
|
||||
* @note Call this method when the application state has changed.
|
||||
*
|
||||
* @param applicationState Application state.
|
||||
*/
|
||||
- (void)updateSamplingFrequencyForApplicationState:(FPRApplicationState)applicationState;
|
||||
|
||||
@end
|
||||
51
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeManager+Private.h
generated
Normal file
51
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeManager+Private.h
generated
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Gauges/FPRGaugeManager.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.h"
|
||||
|
||||
/** This extension should only be used for testing. */
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRGaugeManager ()
|
||||
|
||||
/** @brief Tracks if gauge collection is enabled. */
|
||||
@property(nonatomic, readonly) BOOL gaugeCollectionEnabled;
|
||||
|
||||
/** @brief CPU gauge collector. */
|
||||
@property(nonatomic, readwrite, nullable) FPRCPUGaugeCollector *cpuGaugeCollector;
|
||||
|
||||
/** @brief Memory gauge collector. */
|
||||
@property(nonatomic, readwrite, nullable) FPRMemoryGaugeCollector *memoryGaugeCollector;
|
||||
|
||||
/** @brief Serial queue to manage gauge data collection. */
|
||||
@property(nonatomic, readwrite, nonnull) dispatch_queue_t gaugeDataProtectionQueue;
|
||||
|
||||
/** @brief Tracks if this session is a cold start of the application. */
|
||||
@property(nonatomic) BOOL isColdStart;
|
||||
|
||||
/**
|
||||
* Creates an instance of FPRGaugeManager with the gauges required.
|
||||
*/
|
||||
- (nonnull instancetype)initWithGauges:(FPRGauges)gauges;
|
||||
|
||||
/**
|
||||
* Prepares for dispatching the current set of gauge data to Google Data Transport.
|
||||
*
|
||||
* @param sessionId SessionId that will be used for dispatching the gauge data
|
||||
*/
|
||||
- (void)prepareAndDispatchCollectedGaugeDataWithSessionId:(nullable NSString *)sessionId;
|
||||
|
||||
@end
|
||||
79
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeManager.h
generated
Normal file
79
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeManager.h
generated
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXTERN NSInteger const kGaugeDataBatchSize;
|
||||
|
||||
/** List of gauges the gauge manager controls. */
|
||||
typedef NS_OPTIONS(NSUInteger, FPRGauges) {
|
||||
FPRGaugeNone = 0,
|
||||
FPRGaugeCPU = (1 << 0),
|
||||
FPRGaugeMemory = (1 << 1),
|
||||
};
|
||||
|
||||
/** This class controls different gauge collection in the system. List of the gauges this class
|
||||
manages are listed above. */
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRGaugeManager : NSObject
|
||||
|
||||
/** @brief List of gauges that are currently being actively captured. */
|
||||
@property(nonatomic, readonly) FPRGauges activeGauges;
|
||||
|
||||
/**
|
||||
* Creates an instance of GaugeManager.
|
||||
*
|
||||
* @return Instance of GaugeManager.
|
||||
*/
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
/**
|
||||
* Initializer for the gauge manager. This is not available.
|
||||
*/
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Starts collecting gauge metrics for the specified set of gauges. Calling this will dispatch all
|
||||
* the currently existing gauge data and will start collecting the new data with the new sessionId.
|
||||
*
|
||||
* @param gauges Gauges that needs to be collected.
|
||||
* @param sessionId SessionId for which the gauges are collected.
|
||||
*/
|
||||
- (void)startCollectingGauges:(FPRGauges)gauges forSessionId:(NSString *)sessionId;
|
||||
|
||||
/**
|
||||
* Stops collecting gauge metrics for the specified set of gauges. Calling this will dispatch all
|
||||
* the existing gauge data.
|
||||
*
|
||||
* @param gauges Gauges that needs to be stopped collecting.
|
||||
*/
|
||||
- (void)stopCollectingGauges:(FPRGauges)gauges;
|
||||
|
||||
/**
|
||||
* Collects all the gauges.
|
||||
*/
|
||||
- (void)collectAllGauges;
|
||||
|
||||
/**
|
||||
* Takes a gauge metric and tries to dispatch the gauge metric.
|
||||
*
|
||||
* @param gaugeMetric Gauge metric that needs to be dispatched.
|
||||
*/
|
||||
- (void)dispatchMetric:(id)gaugeMetric;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
223
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeManager.m
generated
Normal file
223
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/FPRGaugeManager.m
generated
Normal file
@ -0,0 +1,223 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Gauges/FPRGaugeManager.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/FPRGaugeManager+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/FPRClient.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeCollector.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
// Number of gauge data information after which that gets flushed to Google Data Transport.
|
||||
NSInteger const kGaugeDataBatchSize = 25;
|
||||
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRGaugeManager () <FPRCPUGaugeCollectorDelegate, FPRMemoryGaugeCollectorDelegate>
|
||||
|
||||
/** @brief List of gauges that are currently being actively captured. */
|
||||
@property(nonatomic, readwrite) FPRGauges activeGauges;
|
||||
|
||||
/** @brief List of gauge information collected. Intentionally this is not a typed collection. Gauge
|
||||
* data could be CPU Gauge data or Memory gauge data.
|
||||
*/
|
||||
@property(nonatomic) NSMutableArray *gaugeData;
|
||||
|
||||
/** @brief Currently active sessionID. */
|
||||
@property(nonatomic, readwrite, copy) NSString *currentSessionId;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRGaugeManager
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static FPRGaugeManager *instance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[FPRGaugeManager alloc] initWithGauges:FPRGaugeNone];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)initWithGauges:(FPRGauges)gauges {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_activeGauges = FPRGaugeNone;
|
||||
_gaugeData = [[NSMutableArray alloc] init];
|
||||
_gaugeDataProtectionQueue =
|
||||
dispatch_queue_create("com.google.perf.gaugeManager.gaugeData", DISPATCH_QUEUE_SERIAL);
|
||||
_isColdStart = YES;
|
||||
[self startAppActivityTracking];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts tracking the application state changes.
|
||||
*/
|
||||
- (void)startAppActivityTracking {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appStateChanged:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appStateChanged:)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:[UIApplication sharedApplication]];
|
||||
}
|
||||
|
||||
- (void)appStateChanged:(NSNotification *)notification {
|
||||
FPRApplicationState applicationState = [FPRAppActivityTracker sharedInstance].applicationState;
|
||||
[self.cpuGaugeCollector updateSamplingFrequencyForApplicationState:applicationState];
|
||||
[self.memoryGaugeCollector updateSamplingFrequencyForApplicationState:applicationState];
|
||||
self.isColdStart = NO;
|
||||
}
|
||||
|
||||
#pragma mark - Implementation methods
|
||||
|
||||
- (BOOL)gaugeCollectionEnabled {
|
||||
// Allow gauge collection to happen during cold start. During dispatch time, we do another check
|
||||
// to make sure if gauge collection is enabled. This is to accommodate gauge metric collection
|
||||
// during app_start scenario.
|
||||
if (self.isColdStart) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Check if the SDK is enabled to collect gauge data.
|
||||
BOOL sdkEnabled = [[FPRConfigurations sharedInstance] sdkEnabled];
|
||||
if (!sdkEnabled) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [FPRConfigurations sharedInstance].isDataCollectionEnabled;
|
||||
}
|
||||
|
||||
- (void)startCollectingGauges:(FPRGauges)gauges forSessionId:(NSString *)sessionId {
|
||||
// Dispatch the already available gauge data with old sessionId.
|
||||
[self prepareAndDispatchCollectedGaugeDataWithSessionId:self.currentSessionId];
|
||||
|
||||
self.currentSessionId = sessionId;
|
||||
if (self.gaugeCollectionEnabled) {
|
||||
if ((gauges & FPRGaugeCPU) == FPRGaugeCPU) {
|
||||
self.cpuGaugeCollector = [[FPRCPUGaugeCollector alloc] initWithDelegate:self];
|
||||
}
|
||||
if ((gauges & FPRGaugeMemory) == FPRGaugeMemory) {
|
||||
self.memoryGaugeCollector = [[FPRMemoryGaugeCollector alloc] initWithDelegate:self];
|
||||
}
|
||||
|
||||
self.activeGauges = self.activeGauges | gauges;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopCollectingGauges:(FPRGauges)gauges {
|
||||
if ((gauges & FPRGaugeCPU) == FPRGaugeCPU) {
|
||||
self.cpuGaugeCollector = nil;
|
||||
}
|
||||
|
||||
if ((gauges & FPRGaugeMemory) == FPRGaugeMemory) {
|
||||
self.memoryGaugeCollector = nil;
|
||||
}
|
||||
|
||||
self.activeGauges = self.activeGauges & ~(gauges);
|
||||
|
||||
// Flush out all the already collected gauge metrics
|
||||
[self prepareAndDispatchCollectedGaugeDataWithSessionId:self.currentSessionId];
|
||||
}
|
||||
|
||||
- (void)collectAllGauges {
|
||||
if (self.cpuGaugeCollector) {
|
||||
[self.cpuGaugeCollector collectMetric];
|
||||
}
|
||||
|
||||
if (self.memoryGaugeCollector) {
|
||||
[self.memoryGaugeCollector collectMetric];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dispatchMetric:(id)gaugeMetric {
|
||||
// If the gauge metric is of type CPU, then dispatch only if CPU collection is enabled.
|
||||
if ([gaugeMetric isKindOfClass:[FPRCPUGaugeData class]] &&
|
||||
((self.activeGauges & FPRGaugeCPU) == FPRGaugeCPU)) {
|
||||
[self addGaugeData:gaugeMetric];
|
||||
}
|
||||
|
||||
// If the gauge metric is of type memory, then dispatch only if memory collection is enabled.
|
||||
if ([gaugeMetric isKindOfClass:[FPRMemoryGaugeData class]] &&
|
||||
((self.activeGauges & FPRGaugeMemory) == FPRGaugeMemory)) {
|
||||
[self addGaugeData:gaugeMetric];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Utils
|
||||
|
||||
- (void)prepareAndDispatchCollectedGaugeDataWithSessionId:(nullable NSString *)sessionId {
|
||||
dispatch_async(self.gaugeDataProtectionQueue, ^{
|
||||
NSArray *dispatchGauges = [self.gaugeData copy];
|
||||
self.gaugeData = [[NSMutableArray alloc] init];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
if (dispatchGauges.count > 0 && sessionId != nil) {
|
||||
[[FPRClient sharedInstance] logGaugeMetric:dispatchGauges forSessionId:sessionId];
|
||||
FPRLogInfo(kFPRGaugeManagerDataCollected, @"Logging %lu gauge metrics.",
|
||||
(unsigned long)dispatchGauges.count);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the gauge to the batch and decide on when to dispatch the events to Google Data Transport.
|
||||
*
|
||||
* @param gauge Gauge data received from the collectors.
|
||||
*/
|
||||
- (void)addGaugeData:(id)gauge {
|
||||
dispatch_async(self.gaugeDataProtectionQueue, ^{
|
||||
if (gauge) {
|
||||
[self.gaugeData addObject:gauge];
|
||||
|
||||
if (self.gaugeData.count >= kGaugeDataBatchSize) {
|
||||
[self prepareAndDispatchCollectedGaugeDataWithSessionId:self.currentSessionId];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - FPRCPUGaugeCollectorDelegate methods
|
||||
|
||||
- (void)cpuGaugeCollector:(FPRCPUGaugeCollector *)collector gaugeData:(FPRCPUGaugeData *)gaugeData {
|
||||
[self addGaugeData:gaugeData];
|
||||
}
|
||||
|
||||
#pragma mark - FPRMemoryGaugeCollectorDelegate methods
|
||||
|
||||
- (void)memoryGaugeCollector:(FPRMemoryGaugeCollector *)collector
|
||||
gaugeData:(FPRMemoryGaugeData *)gaugeData {
|
||||
[self addGaugeData:gaugeData];
|
||||
}
|
||||
|
||||
@end
|
||||
39
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector+Private.h
generated
Normal file
39
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector+Private.h
generated
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXTERN FPRMemoryGaugeData *fprCollectMemoryMetric(void);
|
||||
|
||||
/** This extension should only be used for testing. */
|
||||
@interface FPRMemoryGaugeCollector ()
|
||||
|
||||
/** @brief Override configurations. */
|
||||
@property(nonatomic) FPRConfigurations *configurations;
|
||||
|
||||
/** @brief Stop memory data collection. */
|
||||
- (void)stopCollecting;
|
||||
|
||||
/** @brief Resumes memory data collection. */
|
||||
- (void)resumeCollecting;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
61
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.h
generated
Normal file
61
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.h
generated
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/Gauges/FPRGaugeCollector.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FPRMemoryGaugeCollector;
|
||||
|
||||
/** Delegate method for the memory Gauge collector to report back the memory gauge data. */
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@protocol FPRMemoryGaugeCollectorDelegate
|
||||
|
||||
/**
|
||||
* Reports the collected memory gauge data back to its delegate.
|
||||
*
|
||||
* @param collector memory gauge collector that collected the information.
|
||||
* @param gaugeData memory gauge data.
|
||||
*/
|
||||
- (void)memoryGaugeCollector:(FPRMemoryGaugeCollector *)collector
|
||||
gaugeData:(FPRMemoryGaugeData *)gaugeData;
|
||||
|
||||
@end
|
||||
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRMemoryGaugeCollector : NSObject <FPRGaugeCollector>
|
||||
|
||||
/** Reference to the delegate object. */
|
||||
@property(nonatomic, weak, readonly) id<FPRMemoryGaugeCollectorDelegate> delegate;
|
||||
|
||||
/**
|
||||
* Initializes the memory collector object with the delegate object provided.
|
||||
*
|
||||
* @param delegate Delegate object to which the memory gauge data is provided.
|
||||
* @return Instance of the memory gauge collector.
|
||||
*/
|
||||
- (instancetype)initWithDelegate:(id<FPRMemoryGaugeCollectorDelegate>)delegate
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Initializer for the memory Gauge collector. This is not available.
|
||||
*/
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
116
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.m
generated
Normal file
116
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.m
generated
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
|
||||
#include <malloc/malloc.h>
|
||||
|
||||
@interface FPRMemoryGaugeCollector ()
|
||||
|
||||
/** @brief Timer property used for the frequency of CPU data collection. */
|
||||
@property(nonatomic) dispatch_source_t timerSource;
|
||||
|
||||
/** @brief Gauge collector queue on which the gauge data collected. */
|
||||
@property(nonatomic) dispatch_queue_t gaugeCollectorQueue;
|
||||
|
||||
/** @brief Boolean to see if the timer is active or paused. */
|
||||
@property(nonatomic) BOOL timerPaused;
|
||||
|
||||
@end
|
||||
|
||||
FPRMemoryGaugeData *fprCollectMemoryMetric(void) {
|
||||
NSDate *collectionTime = [NSDate date];
|
||||
|
||||
struct mstats ms = mstats();
|
||||
FPRMemoryGaugeData *gaugeData = [[FPRMemoryGaugeData alloc] initWithCollectionTime:collectionTime
|
||||
heapUsed:ms.bytes_used
|
||||
heapAvailable:ms.bytes_free];
|
||||
return gaugeData;
|
||||
}
|
||||
|
||||
@implementation FPRMemoryGaugeCollector
|
||||
|
||||
- (instancetype)initWithDelegate:(id<FPRMemoryGaugeCollectorDelegate>)delegate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_delegate = delegate;
|
||||
_gaugeCollectorQueue =
|
||||
dispatch_queue_create("com.google.firebase.FPRMemoryGaugeCollector", DISPATCH_QUEUE_SERIAL);
|
||||
_configurations = [FPRConfigurations sharedInstance];
|
||||
_timerPaused = YES;
|
||||
[self updateSamplingFrequencyForApplicationState:[FPRAppActivityTracker sharedInstance]
|
||||
.applicationState];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)stopCollecting {
|
||||
if (self.timerPaused == NO) {
|
||||
dispatch_source_cancel(self.timerSource);
|
||||
self.timerPaused = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resumeCollecting {
|
||||
[self updateSamplingFrequencyForApplicationState:[FPRAppActivityTracker sharedInstance]
|
||||
.applicationState];
|
||||
}
|
||||
|
||||
- (void)updateSamplingFrequencyForApplicationState:(FPRApplicationState)applicationState {
|
||||
uint32_t frequencyInMs = (applicationState == FPRApplicationStateBackground)
|
||||
? [self.configurations memorySamplingFrequencyInBackgroundInMS]
|
||||
: [self.configurations memorySamplingFrequencyInForegroundInMS];
|
||||
[self captureMemoryGaugeAtFrequency:frequencyInMs];
|
||||
}
|
||||
|
||||
#pragma mark - Internal methods.
|
||||
|
||||
/**
|
||||
* Captures the memory gauge at a defined frequency.
|
||||
*
|
||||
* @param frequencyInMs Frequency at which the memory gauges are collected.
|
||||
*/
|
||||
- (void)captureMemoryGaugeAtFrequency:(uint32_t)frequencyInMs {
|
||||
[self stopCollecting];
|
||||
if (frequencyInMs > 0) {
|
||||
self.timerSource =
|
||||
dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.gaugeCollectorQueue);
|
||||
dispatch_source_set_timer(self.timerSource,
|
||||
dispatch_time(DISPATCH_TIME_NOW, frequencyInMs * NSEC_PER_MSEC),
|
||||
frequencyInMs * NSEC_PER_MSEC, (1ull * NSEC_PER_SEC) / 10);
|
||||
FPRMemoryGaugeCollector __weak *weakSelf = self;
|
||||
dispatch_source_set_event_handler(weakSelf.timerSource, ^{
|
||||
FPRMemoryGaugeCollector *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
[strongSelf collectMetric];
|
||||
}
|
||||
});
|
||||
dispatch_resume(self.timerSource);
|
||||
self.timerPaused = NO;
|
||||
} else {
|
||||
FPRLogDebug(kFPRMemoryCollection, @"Memory metric collection is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)collectMetric {
|
||||
FPRMemoryGaugeData *gaugeMetric = fprCollectMemoryMetric();
|
||||
[self.delegate memoryGaugeCollector:self gaugeData:gaugeMetric];
|
||||
}
|
||||
|
||||
@end
|
||||
49
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h
generated
Normal file
49
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h
generated
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Class that contains memory gauge information for any point in time.
|
||||
*/
|
||||
@interface FPRMemoryGaugeData : NSObject
|
||||
|
||||
/** @brief Time at which memory data was measured. */
|
||||
@property(nonatomic, readonly) NSDate *collectionTime;
|
||||
|
||||
/** @brief Heap memory that is used. */
|
||||
@property(nonatomic, readonly) u_long heapUsed;
|
||||
|
||||
/** @brief Heap memory that is available. */
|
||||
@property(nonatomic, readonly) u_long heapAvailable;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Creates an instance of memory gauge data with the provided information.
|
||||
*
|
||||
* @param collectionTime Time at which the gauge data was collected.
|
||||
* @param heapUsed Heap memory that is used.
|
||||
* @param heapAvailable Heap memory that is available.
|
||||
* @return Instance of memory gauge data.
|
||||
*/
|
||||
- (instancetype)initWithCollectionTime:(NSDate *)collectionTime
|
||||
heapUsed:(u_long)heapUsed
|
||||
heapAvailable:(u_long)heapAvailable NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
31
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.m
generated
Normal file
31
Pods/FirebasePerformance/FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.m
generated
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h"
|
||||
|
||||
@implementation FPRMemoryGaugeData
|
||||
|
||||
- (instancetype)initWithCollectionTime:(NSDate *)collectionTime
|
||||
heapUsed:(u_long)heapUsed
|
||||
heapAvailable:(u_long)heapAvailable {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_collectionTime = collectionTime;
|
||||
_heapUsed = heapUsed;
|
||||
_heapAvailable = heapAvailable;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
23
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler+Internal.h
generated
Normal file
23
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler+Internal.h
generated
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2019 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.h"
|
||||
|
||||
FOUNDATION_EXPORT const NSString *const kGULSwizzlerAssociatedObjectKey;
|
||||
|
||||
@interface FPRObjectSwizzler (Internal)
|
||||
|
||||
- (void)swizzledObjectHasBeenDeallocatedWithGeneratedSubclass:(BOOL)isInstanceOfGeneratedSubclass;
|
||||
|
||||
@end
|
||||
123
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.h
generated
Normal file
123
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.h
generated
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Enums that map to their OBJC-prefixed counterparts. */
|
||||
typedef OBJC_ENUM(uintptr_t, GUL_ASSOCIATION){
|
||||
|
||||
// Is a weak association.
|
||||
GUL_ASSOCIATION_ASSIGN,
|
||||
|
||||
// Is a nonatomic strong association.
|
||||
GUL_ASSOCIATION_RETAIN_NONATOMIC,
|
||||
|
||||
// Is a nonatomic copy association.
|
||||
GUL_ASSOCIATION_COPY_NONATOMIC,
|
||||
|
||||
// Is an atomic strong association.
|
||||
GUL_ASSOCIATION_RETAIN,
|
||||
|
||||
// Is an atomic copy association.
|
||||
GUL_ASSOCIATION_COPY};
|
||||
|
||||
/** This class handles swizzling a specific instance of a class by generating a
|
||||
* dynamic subclass and installing selectors and properties onto the dynamic
|
||||
* subclass. Then, the instance's class is set to the dynamic subclass. There
|
||||
* should be a 1:1 ratio of object swizzlers to swizzled instances.
|
||||
*/
|
||||
@interface FPRObjectSwizzler : NSObject
|
||||
|
||||
/** The subclass that is generated. */
|
||||
@property(nullable, nonatomic, readonly) Class generatedClass;
|
||||
|
||||
/** Sets an associated object in the runtime. This mechanism can be used to
|
||||
* simulate adding properties.
|
||||
*
|
||||
* @param object The object that will be queried for the associated object.
|
||||
* @param key The key of the associated object.
|
||||
* @param value The value to associate to the swizzled object.
|
||||
* @param association The mechanism to use when associating the objects.
|
||||
*/
|
||||
+ (void)setAssociatedObject:(id)object
|
||||
key:(const void *)key
|
||||
value:(nullable id)value
|
||||
association:(GUL_ASSOCIATION)association;
|
||||
|
||||
/** Gets an associated object in the runtime. This mechanism can be used to
|
||||
* simulate adding properties.
|
||||
*
|
||||
* @param object The object that will be queried for the associated object.
|
||||
* @param key The key of the associated object.
|
||||
*/
|
||||
+ (nullable id)getAssociatedObject:(id)object key:(const void *)key;
|
||||
|
||||
/** Please use the designated initializer. */
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Instantiates an object swizzler using an object it will operate on.
|
||||
* Generates a new class pair.
|
||||
*
|
||||
* @note There is no need to store this object. After calling -swizzle, this
|
||||
* object can be found by calling -gul_objectSwizzler
|
||||
*
|
||||
* @param object The object to be swizzled.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (instancetype)initWithObject:(id)object NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Sets an associated object in the runtime. This mechanism can be used to
|
||||
* simulate adding properties.
|
||||
*
|
||||
* @param key The key of the associated object.
|
||||
* @param value The value to associate to the swizzled object.
|
||||
* @param association The mechanism to use when associating the objects.
|
||||
*/
|
||||
- (void)setAssociatedObjectWithKey:(const void *)key
|
||||
value:(id)value
|
||||
association:(GUL_ASSOCIATION)association;
|
||||
|
||||
/** Gets an associated object in the runtime. This mechanism can be used to
|
||||
* simulate adding properties.
|
||||
*
|
||||
* @param key The key of the associated object.
|
||||
*/
|
||||
- (nullable id)getAssociatedObjectForKey:(const void *)key;
|
||||
|
||||
/** Copies a selector from an existing class onto the generated dynamic subclass
|
||||
* that this object will adopt. This mechanism can be used to add methods to
|
||||
* specific instances of a class.
|
||||
*
|
||||
* @note Should not be called after calling -swizzle.
|
||||
* @param selector The selector to add to the instance.
|
||||
* @param aClass The class supplying an implementation of the method.
|
||||
* @param isClassSelector A BOOL specifying whether the selector is a class or
|
||||
* instance selector.
|
||||
*/
|
||||
- (void)copySelector:(SEL)selector fromClass:(Class)aClass isClassSelector:(BOOL)isClassSelector;
|
||||
|
||||
/** Swizzles the object, changing its class to the generated class. Registers
|
||||
* the class pair. */
|
||||
- (void)swizzle;
|
||||
|
||||
/** @return The value of -[objectBeingSwizzled isProxy] */
|
||||
- (BOOL)isSwizzlingProxyObject;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
212
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.m
generated
Normal file
212
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.m
generated
Normal file
@ -0,0 +1,212 @@
|
||||
// Copyright 2018 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler+Internal.h"
|
||||
#import "FirebasePerformance/Sources/ISASwizzler/FPRSwizzledObject.h"
|
||||
|
||||
@implementation FPRObjectSwizzler {
|
||||
// The swizzled object.
|
||||
__weak id _swizzledObject;
|
||||
|
||||
// The original class of the object.
|
||||
Class _originalClass;
|
||||
|
||||
// The dynamically generated subclass of _originalClass.
|
||||
Class _generatedClass;
|
||||
}
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (void)setAssociatedObject:(id)object
|
||||
key:(const void *)key
|
||||
value:(nullable id)value
|
||||
association:(GUL_ASSOCIATION)association {
|
||||
objc_AssociationPolicy resolvedAssociation;
|
||||
switch (association) {
|
||||
case GUL_ASSOCIATION_ASSIGN:
|
||||
resolvedAssociation = OBJC_ASSOCIATION_ASSIGN;
|
||||
break;
|
||||
|
||||
case GUL_ASSOCIATION_RETAIN_NONATOMIC:
|
||||
resolvedAssociation = OBJC_ASSOCIATION_RETAIN_NONATOMIC;
|
||||
break;
|
||||
|
||||
case GUL_ASSOCIATION_COPY_NONATOMIC:
|
||||
resolvedAssociation = OBJC_ASSOCIATION_COPY_NONATOMIC;
|
||||
break;
|
||||
|
||||
case GUL_ASSOCIATION_RETAIN:
|
||||
resolvedAssociation = OBJC_ASSOCIATION_RETAIN;
|
||||
break;
|
||||
|
||||
case GUL_ASSOCIATION_COPY:
|
||||
resolvedAssociation = OBJC_ASSOCIATION_COPY;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
objc_setAssociatedObject(object, key, value, resolvedAssociation);
|
||||
}
|
||||
|
||||
+ (nullable id)getAssociatedObject:(id)object key:(const void *)key {
|
||||
return objc_getAssociatedObject(object, key);
|
||||
}
|
||||
|
||||
#pragma mark - Instance methods
|
||||
|
||||
/** Instantiates an instance of this class.
|
||||
*
|
||||
* @param object The object to swizzle.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (instancetype)initWithObject:(id)object {
|
||||
if (object == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
FPRObjectSwizzler *existingSwizzler =
|
||||
[[self class] getAssociatedObject:object key:&kGULSwizzlerAssociatedObjectKey];
|
||||
if ([existingSwizzler isKindOfClass:[FPRObjectSwizzler class]]) {
|
||||
// The object has been swizzled already, no need to swizzle again.
|
||||
return existingSwizzler;
|
||||
}
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_swizzledObject = object;
|
||||
_originalClass = object_getClass(object);
|
||||
NSString *newClassName = [NSString stringWithFormat:@"fir_%@_%@", [[NSUUID UUID] UUIDString],
|
||||
NSStringFromClass(_originalClass)];
|
||||
_generatedClass = objc_allocateClassPair(_originalClass, newClassName.UTF8String, 0);
|
||||
NSAssert(_generatedClass, @"Wasn't able to allocate the class pair.");
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)copySelector:(SEL)selector fromClass:(Class)aClass isClassSelector:(BOOL)isClassSelector {
|
||||
NSAssert(_generatedClass, @"This object has already been unswizzled.");
|
||||
Method method = isClassSelector ? class_getClassMethod(aClass, selector)
|
||||
: class_getInstanceMethod(aClass, selector);
|
||||
Class targetClass = isClassSelector ? object_getClass(_generatedClass) : _generatedClass;
|
||||
IMP implementation = method_getImplementation(method);
|
||||
|
||||
const char *typeEncoding = method_getTypeEncoding(method);
|
||||
class_replaceMethod(targetClass, selector, implementation, typeEncoding);
|
||||
}
|
||||
|
||||
- (void)setAssociatedObjectWithKey:(const void *)key
|
||||
value:(id)value
|
||||
association:(GUL_ASSOCIATION)association {
|
||||
__strong id swizzledObject = _swizzledObject;
|
||||
if (swizzledObject) {
|
||||
[[self class] setAssociatedObject:swizzledObject key:key value:value association:association];
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable id)getAssociatedObjectForKey:(const void *)key {
|
||||
__strong id swizzledObject = _swizzledObject;
|
||||
if (swizzledObject) {
|
||||
return [[self class] getAssociatedObject:swizzledObject key:key];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)swizzle {
|
||||
__strong id swizzledObject = _swizzledObject;
|
||||
FPRObjectSwizzler *existingSwizzler =
|
||||
[[self class] getAssociatedObject:swizzledObject key:&kGULSwizzlerAssociatedObjectKey];
|
||||
if (existingSwizzler != nil) {
|
||||
NSAssert(existingSwizzler == self, @"The swizzled object has a different swizzler.");
|
||||
// The object has been swizzled already.
|
||||
return;
|
||||
}
|
||||
|
||||
if (swizzledObject) {
|
||||
[FPRObjectSwizzler setAssociatedObject:swizzledObject
|
||||
key:&kGULSwizzlerAssociatedObjectKey
|
||||
value:self
|
||||
association:GUL_ASSOCIATION_RETAIN];
|
||||
|
||||
[FPRSwizzledObject copyDonorSelectorsUsingObjectSwizzler:self];
|
||||
|
||||
NSAssert(_originalClass == object_getClass(swizzledObject),
|
||||
@"The original class is not the reported class now.");
|
||||
NSAssert(class_getInstanceSize(_originalClass) == class_getInstanceSize(_generatedClass),
|
||||
@"The instance size of the generated class must be equal to the original class.");
|
||||
objc_registerClassPair(_generatedClass);
|
||||
Class doubleCheckOriginalClass __unused = object_setClass(_swizzledObject, _generatedClass);
|
||||
NSAssert(_originalClass == doubleCheckOriginalClass,
|
||||
@"The original class must be the same as the class returned by object_setClass");
|
||||
} else {
|
||||
NSAssert(NO, @"You can't swizzle a nil object");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// When the Zombies instrument is enabled, a zombie is created for the swizzled object upon
|
||||
// deallocation. Because this zombie subclasses the generated class, the swizzler should not
|
||||
// dispose it during the swizzler's deallocation.
|
||||
//
|
||||
// There are other special cases where the generated class might be subclassed by a third-party
|
||||
// generated classes, for example: https://github.com/firebase/firebase-ios-sdk/issues/9083
|
||||
// To avoid errors in such cases, the environment variable `GULGeneratedClassDisposeDisabled` can
|
||||
// be set with `YES`.
|
||||
NSDictionary *environment = [[NSProcessInfo processInfo] environment];
|
||||
if ([[environment objectForKey:@"NSZombieEnabled"] boolValue] ||
|
||||
[[environment objectForKey:@"GULGeneratedClassDisposeDisabled"] boolValue]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_generatedClass) {
|
||||
if (_swizzledObject == nil) {
|
||||
// The swizzled object has been deallocated already, so the generated class can be disposed
|
||||
// now.
|
||||
objc_disposeClassPair(_generatedClass);
|
||||
return;
|
||||
}
|
||||
|
||||
// FPRSwizzledObject is retained by the swizzled object which means that the swizzled object is
|
||||
// being deallocated now. Let's see if we should schedule the generated class disposal.
|
||||
|
||||
// If the swizzled object has a different class, it most likely indicates that the object was
|
||||
// ISA swizzled one more time. In this case it is not safe to dispose the generated class. We
|
||||
// will have to keep it to prevent a crash.
|
||||
|
||||
// TODO: Consider adding a flag that can be set by the host application to dispose the class
|
||||
// pair unconditionally. It may be used by apps that use ISA Swizzling themself and are
|
||||
// confident in disposing their subclasses.
|
||||
BOOL isSwizzledObjectInstanceOfGeneratedClass =
|
||||
object_getClass(_swizzledObject) == _generatedClass;
|
||||
|
||||
if (isSwizzledObjectInstanceOfGeneratedClass) {
|
||||
Class generatedClass = _generatedClass;
|
||||
|
||||
// Schedule the generated class disposal after the swizzled object has been deallocated.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
objc_disposeClassPair(generatedClass);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isSwizzlingProxyObject {
|
||||
return [_swizzledObject isProxy];
|
||||
}
|
||||
|
||||
@end
|
||||
46
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRSwizzledObject.h
generated
Normal file
46
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRSwizzledObject.h
generated
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FPRObjectSwizzler;
|
||||
|
||||
/** This class exists as a method donor. These methods will be added to all objects that are
|
||||
* swizzled by the object swizzler. This class should not be instantiated.
|
||||
*/
|
||||
@interface FPRSwizzledObject : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Copies the methods below to the swizzled object.
|
||||
*
|
||||
* @param objectSwizzler The swizzler to use when adding the methods below.
|
||||
*/
|
||||
+ (void)copyDonorSelectorsUsingObjectSwizzler:(FPRObjectSwizzler *)objectSwizzler;
|
||||
|
||||
#pragma mark - Donor methods.
|
||||
|
||||
/** @return The generated subclass. Used in respondsToSelector: calls. */
|
||||
- (Class)gul_class;
|
||||
|
||||
/** @return The object swizzler that manages this object. */
|
||||
- (FPRObjectSwizzler *)gul_objectSwizzler;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
64
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRSwizzledObject.m
generated
Normal file
64
Pods/FirebasePerformance/FirebasePerformance/Sources/ISASwizzler/FPRSwizzledObject.m
generated
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2018 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
|
||||
//
|
||||
// http://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 <objc/runtime.h>
|
||||
|
||||
#import "FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler+Internal.h"
|
||||
#import "FirebasePerformance/Sources/ISASwizzler/FPRSwizzledObject.h"
|
||||
|
||||
const NSString *const kGULSwizzlerAssociatedObjectKey = @"gul_objectSwizzler";
|
||||
|
||||
@interface FPRSwizzledObject ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRSwizzledObject
|
||||
|
||||
+ (void)copyDonorSelectorsUsingObjectSwizzler:(FPRObjectSwizzler *)objectSwizzler {
|
||||
[objectSwizzler copySelector:@selector(gul_objectSwizzler) fromClass:self isClassSelector:NO];
|
||||
[objectSwizzler copySelector:@selector(gul_class) fromClass:self isClassSelector:NO];
|
||||
|
||||
// This is needed because NSProxy objects usually override -[NSObjectProtocol respondsToSelector:]
|
||||
// and ask this question to the underlying object. Since we don't swizzle the underlying object
|
||||
// but swizzle the proxy, when someone calls -[NSObjectProtocol respondsToSelector:] on the proxy,
|
||||
// the answer ends up being NO even if we added new methods to the subclass through ISA Swizzling.
|
||||
// To solve that, we override -[NSObjectProtocol respondsToSelector:] in such a way that takes
|
||||
// into account the fact that we've added new methods.
|
||||
if ([objectSwizzler isSwizzlingProxyObject]) {
|
||||
[objectSwizzler copySelector:@selector(respondsToSelector:) fromClass:self isClassSelector:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
NSAssert(NO, @"Do not instantiate this class, it's only a donor class");
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (FPRObjectSwizzler *)gul_objectSwizzler {
|
||||
return [FPRObjectSwizzler getAssociatedObject:self key:&kGULSwizzlerAssociatedObjectKey];
|
||||
}
|
||||
|
||||
#pragma mark - Donor methods
|
||||
|
||||
- (Class)gul_class {
|
||||
return [[self gul_objectSwizzler] generatedClass];
|
||||
}
|
||||
|
||||
// Only added to a class when we detect it is a proxy.
|
||||
- (BOOL)respondsToSelector:(SEL)aSelector {
|
||||
Class gulClass = [[self gul_objectSwizzler] generatedClass];
|
||||
return [gulClass instancesRespondToSelector:aSelector] || [super respondsToSelector:aSelector];
|
||||
}
|
||||
|
||||
@end
|
||||
37
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FIRHTTPMetric+Private.h
generated
Normal file
37
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FIRHTTPMetric+Private.h
generated
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
|
||||
/**
|
||||
* Extension that is added on top of the class FIRHTTPMetric to make the private properties visible
|
||||
* between the implementation file and the unit tests.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FIRHTTPMetric ()
|
||||
|
||||
/* Network trace to capture the HTTPMetric information. */
|
||||
@property(nonatomic, strong) FPRNetworkTrace *networkTrace;
|
||||
|
||||
/**
|
||||
* Marks the end time of the request.
|
||||
*/
|
||||
- (void)markRequestComplete;
|
||||
|
||||
/**
|
||||
* Marks the start time of the response.
|
||||
*/
|
||||
- (void)markResponseStart;
|
||||
|
||||
@end
|
||||
155
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FIRHTTPMetric.m
generated
Normal file
155
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FIRHTTPMetric.m
generated
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Public/FirebasePerformance/FIRHTTPMetric.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FIRHTTPMetric+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
#import "FirebasePerformance/Sources/FPRDataUtils.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
|
||||
@interface FIRHTTPMetric ()
|
||||
|
||||
/* A placeholder URLRequest used for SDK metric tracking. */
|
||||
@property(nonatomic, strong) NSURLRequest *URLRequest;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRHTTPMetric
|
||||
|
||||
- (nullable instancetype)initWithURL:(nonnull NSURL *)URL HTTPMethod:(FIRHTTPMethod)httpMethod {
|
||||
BOOL tracingEnabled = [FPRConfigurations sharedInstance].isDataCollectionEnabled;
|
||||
if (!tracingEnabled) {
|
||||
FPRLogInfo(kFPRTraceDisabled, @"Trace feature is disabled. Dropping http metric - %@",
|
||||
URL.absoluteString);
|
||||
return nil;
|
||||
}
|
||||
|
||||
BOOL sdkEnabled = [[FPRConfigurations sharedInstance] sdkEnabled];
|
||||
if (!sdkEnabled) {
|
||||
FPRLogInfo(kFPRTraceDisabled, @"Dropping event since Performance SDK is disabled.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableURLRequest *URLRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
|
||||
NSString *HTTPMethodString = nil;
|
||||
switch (httpMethod) {
|
||||
case FIRHTTPMethodGET:
|
||||
HTTPMethodString = @"GET";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodPUT:
|
||||
HTTPMethodString = @"PUT";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodPOST:
|
||||
HTTPMethodString = @"POST";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodHEAD:
|
||||
HTTPMethodString = @"HEAD";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodDELETE:
|
||||
HTTPMethodString = @"DELETE";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodPATCH:
|
||||
HTTPMethodString = @"PATCH";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodOPTIONS:
|
||||
HTTPMethodString = @"OPTIONS";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodTRACE:
|
||||
HTTPMethodString = @"TRACE";
|
||||
break;
|
||||
|
||||
case FIRHTTPMethodCONNECT:
|
||||
HTTPMethodString = @"CONNECT";
|
||||
break;
|
||||
}
|
||||
[URLRequest setHTTPMethod:HTTPMethodString];
|
||||
|
||||
if (URLRequest && HTTPMethodString != nil) {
|
||||
self = [super init];
|
||||
_networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
|
||||
_URLRequest = [URLRequest copy];
|
||||
return self;
|
||||
}
|
||||
|
||||
FPRLogError(kFPRInstrumentationInvalidInputs, @"Invalid URL");
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)start {
|
||||
[self.networkTrace start];
|
||||
}
|
||||
|
||||
- (void)markRequestComplete {
|
||||
[self.networkTrace checkpointState:FPRNetworkTraceCheckpointStateRequestCompleted];
|
||||
}
|
||||
|
||||
- (void)markResponseStart {
|
||||
[self.networkTrace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
}
|
||||
|
||||
- (void)stop {
|
||||
self.networkTrace.requestSize = self.requestPayloadSize;
|
||||
self.networkTrace.responseSize = self.responsePayloadSize;
|
||||
// Create a dummy URL Response that will be used for data extraction.
|
||||
NSString *responsePayloadSize =
|
||||
[[NSString alloc] initWithFormat:@"%ld", self.responsePayloadSize];
|
||||
NSMutableDictionary<NSString *, NSString *> *headerFields =
|
||||
[[NSMutableDictionary<NSString *, NSString *> alloc] init];
|
||||
if (self.responseContentType) {
|
||||
[headerFields setObject:self.responseContentType forKey:@"Content-Type"];
|
||||
}
|
||||
[headerFields setObject:responsePayloadSize forKey:@"Content-Length"];
|
||||
|
||||
if (self.responseCode == 0) {
|
||||
FPRLogError(kFPRInstrumentationInvalidInputs, @"Response code not set for request - %@",
|
||||
self.URLRequest.URL);
|
||||
return;
|
||||
}
|
||||
NSHTTPURLResponse *URLResponse = [[NSHTTPURLResponse alloc] initWithURL:self.URLRequest.URL
|
||||
statusCode:self.responseCode
|
||||
HTTPVersion:nil
|
||||
headerFields:headerFields];
|
||||
|
||||
[self.networkTrace didCompleteRequestWithResponse:URLResponse error:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Custom attributes related methods
|
||||
|
||||
- (NSDictionary<NSString *, NSString *> *)attributes {
|
||||
return [self.networkTrace attributes];
|
||||
}
|
||||
|
||||
- (void)setValue:(NSString *)value forAttribute:(nonnull NSString *)attribute {
|
||||
[self.networkTrace setValue:value forAttribute:attribute];
|
||||
}
|
||||
|
||||
- (NSString *)valueForAttribute:(NSString *)attribute {
|
||||
return [self.networkTrace valueForAttribute:attribute];
|
||||
}
|
||||
|
||||
- (void)removeAttribute:(NSString *)attribute {
|
||||
[self.networkTrace removeAttribute:attribute];
|
||||
}
|
||||
|
||||
@end
|
||||
62
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor.h
generated
Normal file
62
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor.h
generated
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
@class FPRSelectorInstrumentor;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* Each instrumented class (even classes within class clusters) needs to have its own instrumentor.
|
||||
*/
|
||||
@interface FPRClassInstrumentor : NSObject
|
||||
|
||||
/** The class being instrumented. */
|
||||
@property(nonatomic, readonly) Class instrumentedClass;
|
||||
|
||||
/** Please use the designated initializer. */
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Initializes with a class name and stores a reference to that string. This is the designated
|
||||
* initializer.
|
||||
*
|
||||
* @param aClass The class to be instrumented.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (instancetype)initWithClass:(Class)aClass NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Creates and adds a class selector instrumentor to this class instrumentor.
|
||||
*
|
||||
* @param selector The selector to build and add to this class instrumentor;
|
||||
* @return An FPRSelectorInstrumentor if the class/selector combination exists, nil otherwise.
|
||||
*/
|
||||
- (nullable FPRSelectorInstrumentor *)instrumentorForClassSelector:(SEL)selector;
|
||||
|
||||
/** Creates and adds an instance selector instrumentor to this class instrumentor.
|
||||
*
|
||||
* @param selector The selector to build and add to this class instrumentor;
|
||||
* @return An FPRSelectorInstrumentor if the class/selector combination exists, nil otherwise.
|
||||
*/
|
||||
- (nullable FPRSelectorInstrumentor *)instrumentorForInstanceSelector:(SEL)selector;
|
||||
|
||||
/** Swizzles the set of selector instrumentors. */
|
||||
- (void)swizzle;
|
||||
|
||||
/** Removes all selector instrumentors and unswizzles their implementations. */
|
||||
- (BOOL)unswizzle;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
103
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor.m
generated
Normal file
103
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor.m
generated
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor_Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.h"
|
||||
|
||||
/** Use ivars instead of properties to reduce message sending overhead. */
|
||||
@interface FPRClassInstrumentor () {
|
||||
// The selector instrumentors associated with this class.
|
||||
NSMutableSet<FPRSelectorInstrumentor *> *_selectorInstrumentors;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRClassInstrumentor
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (instancetype)init {
|
||||
FPRAssert(NO, @"%@: please use the designated initializer.", NSStringFromClass([self class]));
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithClass:(Class)aClass {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
FPRAssert(aClass, @"You must supply a class in order to instrument its methods");
|
||||
_instrumentedClass = aClass;
|
||||
_selectorInstrumentors = [[NSMutableSet<FPRSelectorInstrumentor *> alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable FPRSelectorInstrumentor *)instrumentorForClassSelector:(SEL)selector {
|
||||
return [self buildAndAddSelectorInstrumentorForSelector:selector isClassSelector:YES];
|
||||
}
|
||||
|
||||
- (nullable FPRSelectorInstrumentor *)instrumentorForInstanceSelector:(SEL)selector {
|
||||
return [self buildAndAddSelectorInstrumentorForSelector:selector isClassSelector:NO];
|
||||
}
|
||||
|
||||
- (void)swizzle {
|
||||
for (FPRSelectorInstrumentor *selectorInstrumentor in _selectorInstrumentors) {
|
||||
[selectorInstrumentor swizzle];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)unswizzle {
|
||||
for (FPRSelectorInstrumentor *selectorInstrumentor in _selectorInstrumentors) {
|
||||
[selectorInstrumentor unswizzle];
|
||||
}
|
||||
[_selectorInstrumentors removeAllObjects];
|
||||
return _selectorInstrumentors.count == 0;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
/** Creates and adds a selector instrumentor to this class instrumentor.
|
||||
*
|
||||
* @param selector The selector to build and add to this class instrumentor;
|
||||
* @param isClassSelector If YES, then the selector is a class selector.
|
||||
* @return An FPRSelectorInstrumentor if the class/selector combination exists, nil otherwise.
|
||||
*/
|
||||
- (nullable FPRSelectorInstrumentor *)buildAndAddSelectorInstrumentorForSelector:(SEL)selector
|
||||
isClassSelector:
|
||||
(BOOL)isClassSelector {
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[[FPRSelectorInstrumentor alloc] initWithSelector:selector
|
||||
class:_instrumentedClass
|
||||
isClassSelector:isClassSelector];
|
||||
if (selectorInstrumentor) {
|
||||
[self addSelectorInstrumentor:selectorInstrumentor];
|
||||
}
|
||||
return selectorInstrumentor;
|
||||
}
|
||||
|
||||
/** Adds a selector instrumentors to an existing running list of instrumented selectors.
|
||||
*
|
||||
* @param selectorInstrumentor A non-nil selector instrumentor, whose SEL objects will be swizzled.
|
||||
*/
|
||||
- (void)addSelectorInstrumentor:(nonnull FPRSelectorInstrumentor *)selectorInstrumentor {
|
||||
if ([_selectorInstrumentors containsObject:selectorInstrumentor]) {
|
||||
FPRAssert(NO, @"You cannot instrument the same selector (%@) twice",
|
||||
NSStringFromSelector(selectorInstrumentor.selector));
|
||||
}
|
||||
[_selectorInstrumentors addObject:selectorInstrumentor];
|
||||
}
|
||||
|
||||
@end
|
||||
24
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor_Private.h
generated
Normal file
24
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor_Private.h
generated
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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.
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FPRClassInstrumentor ()
|
||||
|
||||
/** The set of selector instrumentors on this class. Only used for testing. */
|
||||
@property(nonatomic, readonly) NSSet *selectorInstrumentors;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
60
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrument.h
generated
Normal file
60
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrument.h
generated
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
@class FPRClassInstrumentor;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** FPRInstrument instances can instrument many different classes, but should try to instrument
|
||||
* only a single class in the general case. Due to class clusters, FPRInstruments need to be able
|
||||
* to support logical groups of classes, even if the public API is a single class (e.g.
|
||||
* NSDictionary or NSURLSession. FPRInstrument is expected to be subclassed by other classes that
|
||||
* actually implement the instrument. Subclasses should provide their own implementations of
|
||||
* registerInstrumentor
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRInstrument : NSObject
|
||||
|
||||
/** The list of class instrumentors. count should == 1 in most cases, and be > 1 for class clusters.
|
||||
*/
|
||||
@property(nonatomic, readonly) NSArray<FPRClassInstrumentor *> *classInstrumentors;
|
||||
|
||||
/** A set of the instrumented classes. */
|
||||
@property(nonatomic, readonly) NSSet<Class> *instrumentedClasses;
|
||||
|
||||
/**
|
||||
* Checks if the given object is instrumentable and returns YES if instrumentable. NO, otherwise.
|
||||
*
|
||||
* @param object Object that needs to be validated.
|
||||
* @return Yes if instrumentable, NO otherwise.
|
||||
*/
|
||||
- (BOOL)isObjectInstrumentable:(id)object;
|
||||
|
||||
/** Registers all instrumentors this instrument will utilize. Should be instrumented in a subclass.
|
||||
*
|
||||
* @note This method is thread-safe.
|
||||
*/
|
||||
- (void)registerInstrumentors;
|
||||
|
||||
/** Deregisters the instrumentors by using API provided by FPRClassInstrumentor. Called by dealloc.
|
||||
*
|
||||
* @note This method is thread-safe.
|
||||
*/
|
||||
- (void)deregisterInstrumentors;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
78
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrument.m
generated
Normal file
78
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrument.m
generated
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRInstrument.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRInstrument_Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.h"
|
||||
|
||||
@implementation FPRInstrument {
|
||||
NSMutableArray<FPRClassInstrumentor *> *_classInstrumentors;
|
||||
|
||||
NSMutableSet<Class> *_instrumentedClasses;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_classInstrumentors = [[NSMutableArray<FPRClassInstrumentor *> alloc] init];
|
||||
_instrumentedClasses = [[NSMutableSet<Class> alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSMutableArray<FPRClassInstrumentor *> *)classInstrumentors {
|
||||
return _classInstrumentors;
|
||||
}
|
||||
|
||||
- (NSMutableSet<Class> *)instrumentedClasses {
|
||||
return _instrumentedClasses;
|
||||
}
|
||||
|
||||
- (void)registerInstrumentors {
|
||||
FPRAssert(NO, @"registerInstrumentors should be implemented in a concrete subclass.");
|
||||
}
|
||||
|
||||
- (BOOL)isObjectInstrumentable:(id)object {
|
||||
if ([object isKindOfClass:[NSOperation class]]) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)registerClassInstrumentor:(FPRClassInstrumentor *)instrumentor {
|
||||
@synchronized(self) {
|
||||
if ([_instrumentedClasses containsObject:instrumentor.instrumentedClass] ||
|
||||
[instrumentor.instrumentedClass instancesRespondToSelector:@selector(gul_class)]) {
|
||||
return NO;
|
||||
}
|
||||
[_instrumentedClasses addObject:instrumentor.instrumentedClass];
|
||||
[_classInstrumentors addObject:instrumentor];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)deregisterInstrumentors {
|
||||
@synchronized(self) {
|
||||
for (FPRClassInstrumentor *classInstrumentor in self.classInstrumentors) {
|
||||
[classInstrumentor unswizzle];
|
||||
}
|
||||
[_classInstrumentors removeAllObjects];
|
||||
[_instrumentedClasses removeAllObjects];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
30
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrument_Private.h
generated
Normal file
30
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrument_Private.h
generated
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRInstrument.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FPRInstrument ()
|
||||
|
||||
/** Registers an instrumentor for a class. Should be called by subclasses.
|
||||
*
|
||||
* @param instrumentor The instrumentor to register.
|
||||
* @return NO if the class has already been instrumented, YES otherwise.
|
||||
*/
|
||||
- (BOOL)registerClassInstrumentor:(FPRClassInstrumentor *)instrumentor;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
45
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.h
generated
Normal file
45
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.h
generated
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** The key for the network instrumentation group. */
|
||||
FOUNDATION_EXTERN NSString *const kFPRInstrumentationGroupNetworkKey;
|
||||
|
||||
/** The key for the UIKit instrumentation group. */
|
||||
FOUNDATION_EXTERN NSString *const kFPRInstrumentationGroupUIKitKey;
|
||||
|
||||
/** This class manages all automatic instrumentation. */
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRInstrumentation : NSObject
|
||||
|
||||
/** Registers the instrument group.
|
||||
*
|
||||
* @param group The group whose instrumentation should be registered.
|
||||
* @return The number of instruments in the group.
|
||||
*/
|
||||
- (NSUInteger)registerInstrumentGroup:(NSString *)group;
|
||||
|
||||
/** Deregisters the instrument group.
|
||||
*
|
||||
* @param group The group whose instrumentation should be deregistered.
|
||||
* @return YES if there are no registered instruments in the group, NO otherwise.
|
||||
*/
|
||||
- (BOOL)deregisterInstrumentGroup:(NSString *)group;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
92
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.m
generated
Normal file
92
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.m
generated
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRInstrumentation.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRInstrument.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/Network/FPRNSURLConnectionInstrument.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/Network/FPRNSURLSessionInstrument.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/UIKit/FPRUIViewControllerInstrument.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
|
||||
// The instrumentation group keys.
|
||||
NSString *const kFPRInstrumentationGroupNetworkKey = @"network";
|
||||
NSString *const kFPRInstrumentationGroupUIKitKey = @"uikit";
|
||||
|
||||
/** Use ivars instead of properties to reduce message sending overhead. */
|
||||
@interface FPRInstrumentation () {
|
||||
// A dictionary of the instrument groups.
|
||||
NSDictionary<NSString *, NSMutableArray *> *_instrumentGroups;
|
||||
}
|
||||
|
||||
/** Registers an instrument in the given group.
|
||||
*
|
||||
* @param instrument The instrument to register.
|
||||
* @param group The group to register the instrument in.
|
||||
*/
|
||||
- (void)registerInstrument:(FPRInstrument *)instrument group:(NSString *)group;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRInstrumentation
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_instrumentGroups = @{
|
||||
kFPRInstrumentationGroupNetworkKey : [[NSMutableArray alloc] init],
|
||||
kFPRInstrumentationGroupUIKitKey : [[NSMutableArray alloc] init]
|
||||
};
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)registerInstrument:(FPRInstrument *)instrument group:(NSString *)group {
|
||||
FPRAssert(instrument, @"Instrument must be non-nil.");
|
||||
FPRAssert(_instrumentGroups[group], @"groups and group must be non-nil, and groups[group] must be"
|
||||
"non-nil.");
|
||||
if (instrument != nil) {
|
||||
[_instrumentGroups[group] addObject:instrument];
|
||||
}
|
||||
[instrument registerInstrumentors];
|
||||
}
|
||||
|
||||
- (NSUInteger)registerInstrumentGroup:(NSString *)group {
|
||||
FPRAssert(_instrumentGroups[group], @"The group key does not exist", group);
|
||||
FPRAssert(_instrumentGroups[group].count == 0, @"This group is already instrumented");
|
||||
|
||||
if ([group isEqualToString:kFPRInstrumentationGroupNetworkKey]) {
|
||||
[self registerInstrument:[[FPRNSURLSessionInstrument alloc] init] group:group];
|
||||
[self registerInstrument:[[FPRNSURLConnectionInstrument alloc] init] group:group];
|
||||
}
|
||||
|
||||
if ([group isEqualToString:kFPRInstrumentationGroupUIKitKey]) {
|
||||
[self registerInstrument:[[FPRUIViewControllerInstrument alloc] init] group:group];
|
||||
}
|
||||
|
||||
return _instrumentGroups[group].count;
|
||||
}
|
||||
|
||||
- (BOOL)deregisterInstrumentGroup:(NSString *)group {
|
||||
FPRAssert(_instrumentGroups[group], @"You're attempting to deregister an invalid group key.");
|
||||
for (FPRInstrument *instrument in _instrumentGroups[group]) {
|
||||
[instrument deregisterInstrumentors];
|
||||
}
|
||||
[_instrumentGroups[group] removeAllObjects];
|
||||
return _instrumentGroups[group].count == 0;
|
||||
}
|
||||
|
||||
@end
|
||||
31
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace+Private.h
generated
Normal file
31
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace+Private.h
generated
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionDetails.h"
|
||||
|
||||
/**
|
||||
* Extension that is added on top of the class FPRNetworkTrace to make the private properties
|
||||
* visible between the implementation file and the unit tests.
|
||||
*/
|
||||
@interface FPRNetworkTrace ()
|
||||
|
||||
/** @brief List of sessions the trace is associated with. */
|
||||
@property(nonatomic, readwrite, nonnull) NSMutableArray<FPRSessionDetails *> *activeSessions;
|
||||
|
||||
/** Serial queue to manage concurrency. */
|
||||
@property(nonatomic, readwrite, nonnull) dispatch_queue_t syncQueue;
|
||||
|
||||
@end
|
||||
195
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h
generated
Normal file
195
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h
generated
Normal file
@ -0,0 +1,195 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/AppActivity/FPRTraceBackgroundActivityTracker.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionDetails.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/FIRPerformance+Internal.h"
|
||||
|
||||
/** Possible checkpoint states of network trace */
|
||||
typedef NS_ENUM(NSInteger, FPRNetworkTraceCheckpointState) {
|
||||
FPRNetworkTraceCheckpointStateUnknown,
|
||||
|
||||
// Network request has been initiated.
|
||||
FPRNetworkTraceCheckpointStateInitiated,
|
||||
|
||||
// Network request is completed (All necessary uploads for the request is complete).
|
||||
FPRNetworkTraceCheckpointStateRequestCompleted,
|
||||
|
||||
// Network request has received its first response. There could be more.
|
||||
FPRNetworkTraceCheckpointStateResponseReceived,
|
||||
|
||||
// Network request has completed (Could be network error/request successful completion).
|
||||
FPRNetworkTraceCheckpointStateResponseCompleted
|
||||
};
|
||||
|
||||
@protocol FPRNetworkResponseHandler <NSObject>
|
||||
|
||||
/**
|
||||
* Records the size of the file that is uploaded during the request.
|
||||
*
|
||||
* @param URL The URL object that is being used for uploading from the network request.
|
||||
*/
|
||||
- (void)didUploadFileWithURL:(nullable NSURL *)URL;
|
||||
|
||||
/**
|
||||
* Records the amount of data that is fetched during the request. This can be called multiple times
|
||||
* when the network delegate comes back with some data.
|
||||
*
|
||||
* @param data The data object as received from the network request.
|
||||
*/
|
||||
- (void)didReceiveData:(nullable NSData *)data;
|
||||
|
||||
/**
|
||||
* Records the size of the file that is fetched during the request. This can be called multiple
|
||||
* times when the network delegate comes back with some data.
|
||||
*
|
||||
* @param URL The URL object as received from the network request.
|
||||
*/
|
||||
- (void)didReceiveFileURL:(nullable NSURL *)URL;
|
||||
|
||||
/**
|
||||
* Records the end state of the network request. This is usually called at the end of the network
|
||||
* request with a valid response or an error.
|
||||
*
|
||||
* @param response Response of the network request.
|
||||
* @param error Error with the network request.
|
||||
*/
|
||||
- (void)didCompleteRequestWithResponse:(nullable NSURLResponse *)response
|
||||
error:(nullable NSError *)error;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* FPRNetworkTrace object contains information about an NSURLRequest. Every object contains
|
||||
* information about the URL, type of request, and details of the response.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRNetworkTrace : NSObject <FPRNetworkResponseHandler, FIRPerformanceAttributable>
|
||||
|
||||
/** @brief Start time of the trace since epoch. */
|
||||
@property(nonatomic, assign, readonly) NSTimeInterval startTimeSinceEpoch;
|
||||
|
||||
/** @brief The size of the request. The value is in bytes. */
|
||||
@property(nonatomic) int64_t requestSize;
|
||||
|
||||
/** @brief The response size for the request. The value is in bytes. */
|
||||
@property(nonatomic) int64_t responseSize;
|
||||
|
||||
/** @brief The HTTP response code for the request. */
|
||||
@property(nonatomic) int32_t responseCode;
|
||||
|
||||
/** @brief Yes if a valid response code is set, NO otherwise. */
|
||||
@property(nonatomic) BOOL hasValidResponseCode;
|
||||
|
||||
/** @brief The content type of the request as received from the server. */
|
||||
@property(nonatomic, copy, nullable) NSString *responseContentType;
|
||||
|
||||
/** @brief The checkpoint states for the request. The key to the dictionary is the value referred in
|
||||
* enum FPRNetworkTraceCheckpointState mentioned above. The value is the number of seconds since the
|
||||
* reference date.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSDictionary<NSString *, NSNumber *> *checkpointStates;
|
||||
|
||||
/** @brief The network request object. */
|
||||
@property(nonatomic, readonly, nullable) NSURLRequest *URLRequest;
|
||||
|
||||
/** @brief The URL string with all the query params cleaned. The URL string will be of the format:
|
||||
* scheme:[//[user:password@]host[:port]][/]path.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSString *trimmedURLString;
|
||||
|
||||
/** @brief Error object received with the network response. */
|
||||
@property(nonatomic, readonly, nullable) NSError *responseError;
|
||||
|
||||
/** Background state of the trace. */
|
||||
@property(nonatomic, readonly) FPRTraceState backgroundTraceState;
|
||||
|
||||
/** @brief List of sessions the trace is associated with. */
|
||||
@property(nonnull, atomic, readonly) NSArray<FPRSessionDetails *> *sessions;
|
||||
|
||||
/** @brief Serial queue to manage usage of session Ids. */
|
||||
@property(nonatomic, readonly, nonnull) dispatch_queue_t sessionIdSerialQueue;
|
||||
|
||||
/**
|
||||
* Associate a network trace to an object project. This uses ObjC runtime to associate the network
|
||||
* trace with the object provided.
|
||||
*
|
||||
* @param networkTrace Network trace object to be associated with the provided object.
|
||||
* @param object The provided object to whom the network trace object will be associated with.
|
||||
*/
|
||||
+ (void)addNetworkTrace:(nonnull FPRNetworkTrace *)networkTrace toObject:(nonnull id)object;
|
||||
|
||||
/**
|
||||
* Gets the network trace associated with the provided object. If the network trace is not
|
||||
* associated with the object, return nil. This uses ObjC runtime to fetch the object.
|
||||
*
|
||||
* @param object The provided object from which the network object would be fetched.
|
||||
* @return The network trace object associated with the provided object.
|
||||
*/
|
||||
+ (nullable FPRNetworkTrace *)networkTraceFromObject:(nonnull id)object;
|
||||
|
||||
/**
|
||||
* Remove the network trace associated with the provided object. If the network trace is not
|
||||
* associated with the object, does nothing. This uses ObjC runtime to remove the object.
|
||||
*
|
||||
* @param object The provided object from which the network object would be removed.
|
||||
*/
|
||||
+ (void)removeNetworkTraceFromObject:(nonnull id)object;
|
||||
|
||||
/**
|
||||
* Creates an instance of the FPRNetworkTrace with the provided URL and the HTTP method.
|
||||
*
|
||||
* @param URLRequest NSURLRequest object.
|
||||
* @return An instance of FPRNetworkTrace.
|
||||
*/
|
||||
- (nullable instancetype)initWithURLRequest:(nonnull NSURLRequest *)URLRequest
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (nullable instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Records the beginning of the network request. This is usually called just before initiating the
|
||||
* request.
|
||||
*/
|
||||
- (void)start;
|
||||
|
||||
/**
|
||||
* Checkpoints a particular state of the network request. Checkpoint states are listed in the enum
|
||||
* FPRNetworkTraceCheckpointState mentioned above.
|
||||
*
|
||||
* @param state A state as mentioned in enum FPRNetworkTraceCheckpointState.
|
||||
*/
|
||||
- (void)checkpointState:(FPRNetworkTraceCheckpointState)state;
|
||||
|
||||
/**
|
||||
* Provides the time difference between the provided checkpoint states in seconds. If the starting
|
||||
* checkpoint state is greater than the ending checkpoint state, the return value will be negative.
|
||||
* If either of the states does not exist, returns 0.
|
||||
*
|
||||
* @param startState The starting checkpoint state.
|
||||
* @param endState The ending checkpoint state.
|
||||
* @return Difference between the ending checkpoint state and starting checkpoint state in seconds.
|
||||
*/
|
||||
- (NSTimeInterval)timeIntervalBetweenCheckpointState:(FPRNetworkTraceCheckpointState)startState
|
||||
andState:(FPRNetworkTraceCheckpointState)endState;
|
||||
/**
|
||||
* Checks if the network trace is valid.
|
||||
*
|
||||
* @return true if the network trace is valid.
|
||||
*/
|
||||
- (BOOL)isValid;
|
||||
|
||||
@end
|
||||
465
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.m
generated
Normal file
465
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.m
generated
Normal file
@ -0,0 +1,465 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace+Private.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
|
||||
#import "FirebasePerformance/Sources/Common/FPRConstants.h"
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
|
||||
#import "FirebasePerformance/Sources/FPRClient.h"
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
#import "FirebasePerformance/Sources/FPRDataUtils.h"
|
||||
#import "FirebasePerformance/Sources/FPRURLFilter.h"
|
||||
#import "FirebasePerformance/Sources/Gauges/FPRGaugeManager.h"
|
||||
#import "FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.h"
|
||||
|
||||
NSString *const kFPRNetworkTracePropertyName = @"fpr_networkTrace";
|
||||
|
||||
@interface FPRNetworkTrace ()
|
||||
|
||||
@property(nonatomic, readwrite) NSURLRequest *URLRequest;
|
||||
|
||||
@property(nonatomic, readwrite, nullable) NSError *responseError;
|
||||
|
||||
/** State to know if the trace has started. */
|
||||
@property(nonatomic) BOOL traceStarted;
|
||||
|
||||
/** State to know if the trace has completed. */
|
||||
@property(nonatomic) BOOL traceCompleted;
|
||||
|
||||
/** Background activity tracker to know the background state of the trace. */
|
||||
@property(nonatomic) FPRTraceBackgroundActivityTracker *backgroundActivityTracker;
|
||||
|
||||
/** Custom attribute managed internally. */
|
||||
@property(nonatomic) NSMutableDictionary<NSString *, NSString *> *customAttributes;
|
||||
|
||||
/** @brief Serial queue to manage the updation of session Ids. */
|
||||
@property(nonatomic, readwrite) dispatch_queue_t sessionIdSerialQueue;
|
||||
|
||||
/**
|
||||
* Updates the current trace with the current session details.
|
||||
* @param sessionDetails Updated session details of the currently active session.
|
||||
*/
|
||||
- (void)updateTraceWithCurrentSession:(FPRSessionDetails *)sessionDetails;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRNetworkTrace {
|
||||
/**
|
||||
* @brief Object containing different states of the network request. Stores the information about
|
||||
* the state of a network request (defined in FPRNetworkTraceCheckpointState) and the time at
|
||||
* which the event happened.
|
||||
*/
|
||||
NSMutableDictionary<NSString *, NSNumber *> *_states;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithURLRequest:(NSURLRequest *)URLRequest {
|
||||
if (URLRequest.URL == nil) {
|
||||
FPRLogError(kFPRNetworkTraceInvalidInputs, @"Invalid URL. URL is nil.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Fail early instead of creating a trace here.
|
||||
// IMPORTANT: Order is important here. This check needs to be done before looking up on remote
|
||||
// config. Reference bug: b/141861005.
|
||||
if (![[FPRURLFilter sharedInstance] shouldInstrumentURL:URLRequest.URL.absoluteString]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
BOOL tracingEnabled = [FPRConfigurations sharedInstance].isDataCollectionEnabled;
|
||||
if (!tracingEnabled) {
|
||||
FPRLogInfo(kFPRTraceDisabled, @"Trace feature is disabled.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
BOOL sdkEnabled = [[FPRConfigurations sharedInstance] sdkEnabled];
|
||||
if (!sdkEnabled) {
|
||||
FPRLogInfo(kFPRTraceDisabled, @"Dropping event since Performance SDK is disabled.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *trimmedURLString = [FPRNetworkTrace stringByTrimmingURLString:URLRequest];
|
||||
if (!trimmedURLString || trimmedURLString.length <= 0) {
|
||||
FPRLogWarning(kFPRNetworkTraceURLLengthExceeds, @"URL length outside limits, returning nil.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (![URLRequest.URL.absoluteString isEqualToString:trimmedURLString]) {
|
||||
FPRLogInfo(kFPRNetworkTraceURLLengthTruncation,
|
||||
@"URL length exceeds limits, truncating recorded URL - %@.", trimmedURLString);
|
||||
}
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_URLRequest = URLRequest;
|
||||
_trimmedURLString = trimmedURLString;
|
||||
_states = [[NSMutableDictionary<NSString *, NSNumber *> alloc] init];
|
||||
_hasValidResponseCode = NO;
|
||||
_customAttributes = [[NSMutableDictionary<NSString *, NSString *> alloc] init];
|
||||
_syncQueue =
|
||||
dispatch_queue_create("com.google.perf.networkTrace.metric", DISPATCH_QUEUE_SERIAL);
|
||||
_sessionIdSerialQueue =
|
||||
dispatch_queue_create("com.google.perf.sessionIds.networkTrace", DISPATCH_QUEUE_SERIAL);
|
||||
_activeSessions = [[NSMutableArray<FPRSessionDetails *> alloc] init];
|
||||
if (![FPRNetworkTrace isCompleteAndValidTrimmedURLString:_trimmedURLString
|
||||
URLRequest:_URLRequest]) {
|
||||
return nil;
|
||||
};
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
FPRAssert(NO, @"Not a designated initializer.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// Safety net to ensure the notifications are not received anymore.
|
||||
FPRSessionManager *sessionManager = [FPRSessionManager sharedInstance];
|
||||
[sessionManager.sessionNotificationCenter removeObserver:self
|
||||
name:kFPRSessionIdUpdatedNotification
|
||||
object:sessionManager];
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"Request: %@", _URLRequest];
|
||||
}
|
||||
|
||||
- (void)sessionChanged:(NSNotification *)notification {
|
||||
if (self.traceStarted && !self.traceCompleted) {
|
||||
NSDictionary<NSString *, FPRSessionDetails *> *userInfo = notification.userInfo;
|
||||
FPRSessionDetails *sessionDetails = [userInfo valueForKey:kFPRSessionIdNotificationKey];
|
||||
if (sessionDetails) {
|
||||
[self updateTraceWithCurrentSession:sessionDetails];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateTraceWithCurrentSession:(FPRSessionDetails *)sessionDetails {
|
||||
if (sessionDetails != nil) {
|
||||
dispatch_sync(self.sessionIdSerialQueue, ^{
|
||||
[self.activeSessions addObject:sessionDetails];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray<FPRSessionDetails *> *)sessions {
|
||||
__block NSArray<FPRSessionDetails *> *sessionInfos = nil;
|
||||
dispatch_sync(self.sessionIdSerialQueue, ^{
|
||||
sessionInfos = [self.activeSessions copy];
|
||||
});
|
||||
return sessionInfos;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, NSNumber *> *)checkpointStates {
|
||||
__block NSDictionary<NSString *, NSNumber *> *copiedStates;
|
||||
dispatch_sync(self.syncQueue, ^{
|
||||
copiedStates = [_states copy];
|
||||
});
|
||||
return copiedStates;
|
||||
}
|
||||
|
||||
- (void)checkpointState:(FPRNetworkTraceCheckpointState)state {
|
||||
if (!self.traceCompleted && self.traceStarted) {
|
||||
NSString *stateKey = @(state).stringValue;
|
||||
if (stateKey) {
|
||||
dispatch_sync(self.syncQueue, ^{
|
||||
NSNumber *existingState = _states[stateKey];
|
||||
|
||||
if (existingState == nil) {
|
||||
double intervalSinceEpoch = [[NSDate date] timeIntervalSince1970];
|
||||
[_states setObject:@(intervalSinceEpoch) forKey:stateKey];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
FPRAssert(NO, @"stateKey wasn't created for checkpoint state %ld", (long)state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)start {
|
||||
if (!self.traceCompleted) {
|
||||
[[FPRSessionManager sharedInstance] collectAllGaugesOnce];
|
||||
self.traceStarted = YES;
|
||||
self.backgroundActivityTracker = [[FPRTraceBackgroundActivityTracker alloc] init];
|
||||
[self checkpointState:FPRNetworkTraceCheckpointStateInitiated];
|
||||
|
||||
if ([self.URLRequest.HTTPMethod isEqualToString:@"POST"] ||
|
||||
[self.URLRequest.HTTPMethod isEqualToString:@"PUT"]) {
|
||||
self.requestSize = self.URLRequest.HTTPBody.length;
|
||||
}
|
||||
FPRSessionManager *sessionManager = [FPRSessionManager sharedInstance];
|
||||
[self updateTraceWithCurrentSession:[sessionManager.sessionDetails copy]];
|
||||
[sessionManager.sessionNotificationCenter addObserver:self
|
||||
selector:@selector(sessionChanged:)
|
||||
name:kFPRSessionIdUpdatedNotification
|
||||
object:sessionManager];
|
||||
}
|
||||
}
|
||||
|
||||
- (FPRTraceState)backgroundTraceState {
|
||||
FPRTraceBackgroundActivityTracker *backgroundActivityTracker = self.backgroundActivityTracker;
|
||||
if (backgroundActivityTracker) {
|
||||
return backgroundActivityTracker.traceBackgroundState;
|
||||
}
|
||||
|
||||
return FPRTraceStateUnknown;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)startTimeSinceEpoch {
|
||||
NSString *stateKey =
|
||||
[NSString stringWithFormat:@"%lu", (unsigned long)FPRNetworkTraceCheckpointStateInitiated];
|
||||
__block NSTimeInterval timeSinceEpoch;
|
||||
dispatch_sync(self.syncQueue, ^{
|
||||
timeSinceEpoch = [[_states objectForKey:stateKey] doubleValue];
|
||||
});
|
||||
return timeSinceEpoch;
|
||||
}
|
||||
|
||||
#pragma mark - Overrides
|
||||
|
||||
- (void)setResponseCode:(int32_t)responseCode {
|
||||
_responseCode = responseCode;
|
||||
if (responseCode != 0) {
|
||||
_hasValidResponseCode = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FPRNetworkResponseHandler methods
|
||||
|
||||
- (void)didCompleteRequestWithResponse:(NSURLResponse *)response error:(NSError *)error {
|
||||
if (!self.traceCompleted && self.traceStarted) {
|
||||
// Extract needed fields for the trace object.
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response;
|
||||
self.responseCode = (int32_t)HTTPResponse.statusCode;
|
||||
}
|
||||
self.responseError = error;
|
||||
self.responseContentType = response.MIMEType;
|
||||
[self checkpointState:FPRNetworkTraceCheckpointStateResponseCompleted];
|
||||
|
||||
// Send the network trace for logging.
|
||||
[[FPRSessionManager sharedInstance] collectAllGaugesOnce];
|
||||
[[FPRClient sharedInstance] logNetworkTrace:self];
|
||||
|
||||
self.traceCompleted = YES;
|
||||
}
|
||||
|
||||
FPRSessionManager *sessionManager = [FPRSessionManager sharedInstance];
|
||||
[sessionManager.sessionNotificationCenter removeObserver:self
|
||||
name:kFPRSessionIdUpdatedNotification
|
||||
object:sessionManager];
|
||||
}
|
||||
|
||||
- (void)didUploadFileWithURL:(NSURL *)URL {
|
||||
NSNumber *value = nil;
|
||||
NSError *error = nil;
|
||||
|
||||
if ([URL getResourceValue:&value forKey:NSURLFileSizeKey error:&error]) {
|
||||
if (error) {
|
||||
FPRLogNotice(kFPRNetworkTraceFileError, @"Unable to determine the size of file.");
|
||||
} else {
|
||||
self.requestSize = value.unsignedIntegerValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveData:(NSData *)data {
|
||||
self.responseSize = data.length;
|
||||
}
|
||||
|
||||
- (void)didReceiveFileURL:(NSURL *)URL {
|
||||
NSNumber *value = nil;
|
||||
NSError *error = nil;
|
||||
|
||||
if ([URL getResourceValue:&value forKey:NSURLFileSizeKey error:&error]) {
|
||||
if (error) {
|
||||
FPRLogNotice(kFPRNetworkTraceFileError, @"Unable to determine the size of file.");
|
||||
} else {
|
||||
self.responseSize = value.unsignedIntegerValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTimeInterval)timeIntervalBetweenCheckpointState:(FPRNetworkTraceCheckpointState)startState
|
||||
andState:(FPRNetworkTraceCheckpointState)endState {
|
||||
__block NSNumber *startStateTime;
|
||||
__block NSNumber *endStateTime;
|
||||
dispatch_sync(self.syncQueue, ^{
|
||||
startStateTime = [_states objectForKey:[@(startState) stringValue]];
|
||||
endStateTime = [_states objectForKey:[@(endState) stringValue]];
|
||||
});
|
||||
// Fail fast. If any of the times do not exist, return 0.
|
||||
if (startStateTime == nil || endStateTime == nil) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSTimeInterval timeDiff = (endStateTime.doubleValue - startStateTime.doubleValue);
|
||||
return timeDiff;
|
||||
}
|
||||
|
||||
/** Trims and validates the URL string of a given NSURLRequest.
|
||||
*
|
||||
* @param URLRequest The NSURLRequest containing the URL string to trim.
|
||||
* @return The trimmed string.
|
||||
*/
|
||||
+ (NSString *)stringByTrimmingURLString:(NSURLRequest *)URLRequest {
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:URLRequest.URL
|
||||
resolvingAgainstBaseURL:NO];
|
||||
components.query = nil;
|
||||
components.fragment = nil;
|
||||
components.user = nil;
|
||||
components.password = nil;
|
||||
NSURL *trimmedURL = [components URL];
|
||||
NSString *truncatedURLString = FPRTruncatedURLString(trimmedURL.absoluteString);
|
||||
|
||||
NSURL *truncatedURL = [NSURL URLWithString:truncatedURLString];
|
||||
if (!truncatedURL || truncatedURL.host == nil) {
|
||||
return nil;
|
||||
}
|
||||
return truncatedURLString;
|
||||
}
|
||||
|
||||
/** Validates the trace object by checking that it's http or https, and not a denied URL.
|
||||
*
|
||||
* @param trimmedURLString A trimmed URL string from the URLRequest.
|
||||
* @param URLRequest The NSURLRequest that this trace will operate on.
|
||||
* @return YES if the trace object is valid, NO otherwise.
|
||||
*/
|
||||
+ (BOOL)isCompleteAndValidTrimmedURLString:(NSString *)trimmedURLString
|
||||
URLRequest:(NSURLRequest *)URLRequest {
|
||||
if (![[FPRURLFilter sharedInstance] shouldInstrumentURL:trimmedURLString]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Check the URL begins with http or https.
|
||||
NSURLComponents *components = [NSURLComponents componentsWithURL:URLRequest.URL
|
||||
resolvingAgainstBaseURL:NO];
|
||||
NSString *scheme = components.scheme;
|
||||
if (!scheme || !([scheme caseInsensitiveCompare:@"HTTP"] == NSOrderedSame ||
|
||||
[scheme caseInsensitiveCompare:@"HTTPS"] == NSOrderedSame)) {
|
||||
FPRLogError(kFPRNetworkTraceInvalidInputs, @"Invalid URL - %@, returning nil.", URLRequest.URL);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Custom attributes related methods
|
||||
|
||||
- (NSDictionary<NSString *, NSString *> *)attributes {
|
||||
return [self.customAttributes copy];
|
||||
}
|
||||
|
||||
- (void)setValue:(NSString *)value forAttribute:(nonnull NSString *)attribute {
|
||||
BOOL canAddAttribute = YES;
|
||||
if (self.traceCompleted) {
|
||||
FPRLogError(kFPRTraceAlreadyStopped,
|
||||
@"Failed to set attribute %@ because network request %@ has already stopped.",
|
||||
attribute, self.URLRequest.URL);
|
||||
canAddAttribute = NO;
|
||||
}
|
||||
|
||||
NSString *validatedName = FPRReservableAttributeName(attribute);
|
||||
NSString *validatedValue = FPRValidatedAttributeValue(value);
|
||||
|
||||
if (validatedName == nil) {
|
||||
FPRLogError(kFPRAttributeNoName,
|
||||
@"Failed to initialize because of a nil or zero length attribute name.");
|
||||
canAddAttribute = NO;
|
||||
}
|
||||
|
||||
if (validatedValue == nil) {
|
||||
FPRLogError(kFPRAttributeNoValue,
|
||||
@"Failed to initialize because of a nil or zero length attribute value.");
|
||||
canAddAttribute = NO;
|
||||
}
|
||||
|
||||
if (self.customAttributes.allKeys.count >= kFPRMaxGlobalCustomAttributesCount) {
|
||||
FPRLogError(kFPRMaxAttributesReached,
|
||||
@"Only %d attributes allowed. Already reached maximum attribute count.",
|
||||
kFPRMaxGlobalCustomAttributesCount);
|
||||
canAddAttribute = NO;
|
||||
}
|
||||
|
||||
if (canAddAttribute) {
|
||||
// Ensure concurrency during update of attributes.
|
||||
dispatch_sync(self.syncQueue, ^{
|
||||
self.customAttributes[validatedName] = validatedValue;
|
||||
FPRLogDebug(kFPRClientMetricLogged, @"Setting attribute %@ to %@ on network request %@",
|
||||
validatedName, validatedValue, self.URLRequest.URL);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)valueForAttribute:(NSString *)attribute {
|
||||
// TODO(b/175053654): Should this be happening on the serial queue for thread safety?
|
||||
return self.customAttributes[attribute];
|
||||
}
|
||||
|
||||
- (void)removeAttribute:(NSString *)attribute {
|
||||
if (self.traceCompleted) {
|
||||
FPRLogError(kFPRTraceAlreadyStopped,
|
||||
@"Failed to remove attribute %@ because network request %@ has already stopped.",
|
||||
attribute, self.URLRequest.URL);
|
||||
return;
|
||||
}
|
||||
|
||||
[self.customAttributes removeObjectForKey:attribute];
|
||||
}
|
||||
|
||||
#pragma mark - Class methods related to object association.
|
||||
|
||||
+ (void)addNetworkTrace:(FPRNetworkTrace *)networkTrace toObject:(id)object {
|
||||
if (object != nil && networkTrace != nil) {
|
||||
[FPRObjectSwizzler
|
||||
setAssociatedObject:object
|
||||
key:(__bridge const void *_Nonnull)kFPRNetworkTracePropertyName
|
||||
value:networkTrace
|
||||
association:GUL_ASSOCIATION_RETAIN_NONATOMIC];
|
||||
}
|
||||
}
|
||||
|
||||
+ (FPRNetworkTrace *)networkTraceFromObject:(id)object {
|
||||
FPRNetworkTrace *networkTrace = nil;
|
||||
if (object != nil) {
|
||||
id traceObject = [FPRObjectSwizzler
|
||||
getAssociatedObject:object
|
||||
key:(__bridge const void *_Nonnull)kFPRNetworkTracePropertyName];
|
||||
if ([traceObject isKindOfClass:[FPRNetworkTrace class]]) {
|
||||
networkTrace = (FPRNetworkTrace *)traceObject;
|
||||
}
|
||||
}
|
||||
|
||||
return networkTrace;
|
||||
}
|
||||
|
||||
+ (void)removeNetworkTraceFromObject:(id)object {
|
||||
if (object != nil) {
|
||||
[FPRObjectSwizzler
|
||||
setAssociatedObject:object
|
||||
key:(__bridge const void *_Nonnull)kFPRNetworkTracePropertyName
|
||||
value:nil
|
||||
association:GUL_ASSOCIATION_RETAIN_NONATOMIC];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isValid {
|
||||
return _hasValidResponseCode;
|
||||
}
|
||||
|
||||
@end
|
||||
75
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.h
generated
Normal file
75
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.h
generated
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRInstrument.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/ISASwizzler/FPRSwizzledObject.h"
|
||||
|
||||
@class FPRSelectorInstrumentor;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** Defines the interface that an instrumentor should implement if they are going to instrument
|
||||
* objects.
|
||||
*/
|
||||
@protocol FPRObjectInstrumentorProtocol <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
/** Registers an instance of the delegate class to be instrumented.
|
||||
*
|
||||
* @param object The instance to instrument.
|
||||
*/
|
||||
- (void)registerObject:(id)object;
|
||||
|
||||
@end
|
||||
|
||||
/** This class allows the instrumentation of specific objects by isa swizzling specific instances
|
||||
* with a dynamically generated subclass of the object's original class and installing methods
|
||||
* onto this new class.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRObjectInstrumentor : FPRInstrument
|
||||
|
||||
/** The instrumented object. */
|
||||
@property(nonatomic, weak) id instrumentedObject;
|
||||
|
||||
/** YES if there is reason to swizzle, NO if swizzling is not needed. */
|
||||
@property(nonatomic) BOOL hasModifications;
|
||||
|
||||
/** Please use the designated initializer. */
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Instantiates an instance of this class. The designated initializer.
|
||||
*
|
||||
* @param object The object to be instrumented.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (instancetype)initWithObject:(id)object NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Attempts to copy a selector from a donor class onto the dynamically generated subclass that the
|
||||
* object will adopt when -swizzle is called.
|
||||
*
|
||||
* @param selector The selector to use.
|
||||
* @param aClass The class to copy the selector from.
|
||||
* @param isClassSelector YES if the selector is a class selector, NO otherwise.
|
||||
*/
|
||||
- (void)copySelector:(SEL)selector fromClass:(Class)aClass isClassSelector:(BOOL)isClassSelector;
|
||||
|
||||
/** Swizzles the isa of the object and sets its class to the dynamically created subclass. */
|
||||
- (void)swizzle;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
59
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.m
generated
Normal file
59
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.m
generated
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
#import "FirebasePerformance/Sources/ISASwizzler/FPRObjectSwizzler.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRInstrument_Private.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.h"
|
||||
|
||||
@interface FPRObjectInstrumentor () {
|
||||
// The object swizzler instance this instrumentor will use.
|
||||
FPRObjectSwizzler *_objectSwizzler;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FPRObjectInstrumentor
|
||||
|
||||
- (instancetype)init {
|
||||
FPRAssert(NO, @"%@: Please use the designated initializer.", NSStringFromClass([self class]));
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithObject:(id)object {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_objectSwizzler = [[FPRObjectSwizzler alloc] initWithObject:object];
|
||||
_instrumentedObject = object;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)copySelector:(SEL)selector fromClass:(Class)aClass isClassSelector:(BOOL)isClassSelector {
|
||||
__strong id instrumentedObject = _instrumentedObject;
|
||||
if (instrumentedObject && ![instrumentedObject respondsToSelector:selector]) {
|
||||
_hasModifications = YES;
|
||||
[_objectSwizzler copySelector:selector fromClass:aClass isClassSelector:isClassSelector];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)swizzle {
|
||||
if (_hasModifications) {
|
||||
[_objectSwizzler swizzle];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
34
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRProxyObjectHelper.h
generated
Normal file
34
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRProxyObjectHelper.h
generated
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/** This class helps the instrumentation deal with objects that have been wrapped with NSProxy
|
||||
* objects after being swizzled by other SDKs. In particular, Crittercism swizzles NSURLSessions
|
||||
* and makes every NSURLSession initialization method return an NSProxy subclass.
|
||||
*/
|
||||
@interface FPRProxyObjectHelper : NSObject
|
||||
|
||||
/** Registers a proxy object for a given class and runs the onSuccess block whenever an ivar of the
|
||||
* given class is discovered on the proxy object.
|
||||
*
|
||||
* @param proxy The proxy object whose ivars will be iterated.
|
||||
* @param superclass The superclass all ivars will be compared against. See varFoundHandler.
|
||||
* @param varFoundHandler The block to run when an ivar isKindOfClass:aClass.
|
||||
*/
|
||||
+ (void)registerProxyObject:(id)proxy
|
||||
forSuperclass:(Class)superclass
|
||||
varFoundHandler:(void (^)(id ivar))varFoundHandler;
|
||||
|
||||
@end
|
||||
32
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRProxyObjectHelper.m
generated
Normal file
32
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRProxyObjectHelper.m
generated
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRProxyObjectHelper.h"
|
||||
|
||||
#import <GoogleUtilities/GULSwizzler.h>
|
||||
|
||||
@implementation FPRProxyObjectHelper
|
||||
|
||||
+ (void)registerProxyObject:(id)proxy
|
||||
forSuperclass:(Class)superclass
|
||||
varFoundHandler:(void (^)(id ivar))varFoundHandler {
|
||||
NSArray<id> *ivars = [GULSwizzler ivarObjectsForObject:proxy];
|
||||
for (id ivar in ivars) {
|
||||
if ([ivar isKindOfClass:superclass]) {
|
||||
varFoundHandler(ivar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
65
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.h
generated
Normal file
65
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.h
generated
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class is used to manage the swizzling of selectors on classes. An instance of this class
|
||||
* should be created for every selector that is being swizzled.
|
||||
*/
|
||||
@interface FPRSelectorInstrumentor : NSObject
|
||||
|
||||
/** The swizzled selector. */
|
||||
@property(nonatomic, readonly) SEL selector;
|
||||
|
||||
/** Please use designated initializer. */
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Initializes an instance of this class. The designated initializer.
|
||||
*
|
||||
* @note Capture the current IMP outside the replacing block which will be the originalIMP once we
|
||||
* swizzle.
|
||||
*
|
||||
* @param selector The selector pointer.
|
||||
* @param aClass The class to operate on.
|
||||
* @param isClassSelector YES specifies that the selector is a class selector.
|
||||
* @return An instance of this class.
|
||||
*/
|
||||
- (instancetype)initWithSelector:(SEL)selector
|
||||
class:(Class)aClass
|
||||
isClassSelector:(BOOL)isClassSelector NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** Sets the instrumentor's replacing block. To be used in conjunction with initWithSelector:.
|
||||
*
|
||||
* @param block The block to replace the original implementation with. Make sure to call
|
||||
* originalImp in your replacing block.
|
||||
*/
|
||||
- (void)setReplacingBlock:(id)block;
|
||||
|
||||
/** The current IMP of the swizzled selector.
|
||||
*
|
||||
* @return The current IMP for the class, SEL of the FPRSelectorInstrumentor.
|
||||
*/
|
||||
- (IMP)currentIMP;
|
||||
|
||||
/** Swizzles the selector. */
|
||||
- (void)swizzle;
|
||||
|
||||
/** Causes the original implementation to be run. */
|
||||
- (void)unswizzle;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
107
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.m
generated
Normal file
107
Pods/FirebasePerformance/FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.m
generated
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Common/FPRDiagnostics.h"
|
||||
|
||||
#import <GoogleUtilities/GULSwizzler.h>
|
||||
#ifdef UNSWIZZLE_AVAILABLE
|
||||
#import <GoogleUtilities/GULSwizzler+Unswizzle.h>
|
||||
#endif
|
||||
|
||||
@implementation FPRSelectorInstrumentor {
|
||||
// The class this instrumentor operates on.
|
||||
Class _class;
|
||||
|
||||
// The selector this instrumentor operates on.
|
||||
SEL _selector;
|
||||
|
||||
// YES indicates the selector swizzled is a class selector, as opposed to an instance selector.
|
||||
BOOL _isClassSelector;
|
||||
|
||||
// YES indicates that this selector instrumentor has been swizzled.
|
||||
BOOL _swizzled;
|
||||
|
||||
// A block to replace the original implementation. Can't be used with before/after blocks.
|
||||
id _replacingBlock;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
FPRAssert(NO, @"%@: Please use the designated initializer", NSStringFromClass([self class]));
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithSelector:(SEL)selector
|
||||
class:(Class)aClass
|
||||
isClassSelector:(BOOL)isClassSelector {
|
||||
if (![GULSwizzler selector:selector existsInClass:aClass isClassSelector:isClassSelector]) {
|
||||
return nil;
|
||||
}
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_selector = selector;
|
||||
_class = aClass;
|
||||
_isClassSelector = isClassSelector;
|
||||
FPRAssert(_selector, @"A selector to swizzle must be provided.");
|
||||
FPRAssert(_class, @"You can't swizzle a class that doesn't exist");
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setReplacingBlock:(id)block {
|
||||
_replacingBlock = [block copy];
|
||||
}
|
||||
|
||||
- (void)swizzle {
|
||||
_swizzled = YES;
|
||||
FPRAssert(_replacingBlock, @"A replacingBlock needs to be set.");
|
||||
|
||||
[GULSwizzler swizzleClass:_class
|
||||
selector:_selector
|
||||
isClassSelector:_isClassSelector
|
||||
withBlock:_replacingBlock];
|
||||
}
|
||||
|
||||
- (void)unswizzle {
|
||||
_swizzled = NO;
|
||||
#ifdef UNSWIZZLE_AVAILABLE
|
||||
[GULSwizzler unswizzleClass:_class selector:_selector isClassSelector:_isClassSelector];
|
||||
#else
|
||||
NSAssert(NO, @"Unswizzling is disabled.");
|
||||
#endif
|
||||
}
|
||||
|
||||
- (IMP)currentIMP {
|
||||
return [GULSwizzler currentImplementationForClass:_class
|
||||
selector:_selector
|
||||
isClassSelector:_isClassSelector];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if ([object isKindOfClass:[FPRSelectorInstrumentor class]]) {
|
||||
FPRSelectorInstrumentor *otherObject = object;
|
||||
return otherObject->_class == _class && otherObject->_selector == _selector &&
|
||||
otherObject->_isClassSelector == _isClassSelector && otherObject->_swizzled == _swizzled;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [[NSString stringWithFormat:@"%@%@%d%d", NSStringFromClass(_class),
|
||||
NSStringFromSelector(_selector), _isClassSelector, _swizzled]
|
||||
hash];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,25 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRNSURLConnectionDelegate : NSObject <NSURLConnectionDelegate,
|
||||
NSURLConnectionDataDelegate,
|
||||
NSURLConnectionDownloadDelegate>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,82 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/Network/Delegates/FPRNSURLConnectionDelegate.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
|
||||
@implementation FPRNSURLConnectionDelegate
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace didCompleteRequestWithResponse:nil error:error];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:connection];
|
||||
}
|
||||
|
||||
- (NSURLRequest *)connection:(NSURLConnection *)connection
|
||||
willSendRequest:(nonnull NSURLRequest *)request
|
||||
redirectResponse:(nullable NSURLResponse *)response {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
return request;
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
trace.responseCode = (int32_t)((NSHTTPURLResponse *)response).statusCode;
|
||||
}
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
trace.responseSize += data.length;
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection
|
||||
didSendBodyData:(NSInteger)bytesWritten
|
||||
totalBytesWritten:(NSInteger)totalBytesWritten
|
||||
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
trace.requestSize = totalBytesWritten;
|
||||
if (totalBytesWritten >= totalBytesExpectedToWrite) {
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateRequestCompleted];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace didCompleteRequestWithResponse:nil error:nil];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:connection];
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection
|
||||
didWriteData:(long long)bytesWritten
|
||||
totalBytesWritten:(long long)totalBytesWritten
|
||||
expectedTotalBytes:(long long)expectedTotalBytes {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
trace.requestSize = totalBytesWritten;
|
||||
}
|
||||
|
||||
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection
|
||||
destinationURL:(NSURL *)destinationURL {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace didReceiveFileURL:destinationURL];
|
||||
[trace didCompleteRequestWithResponse:nil error:nil];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:connection];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,36 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRInstrument.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class instruments the delegate methods needed to start/stop trace correctly. This class is
|
||||
* not intended to be used standalone--it should only be used by FPRNSURLConnectionInstrument.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRNSURLConnectionDelegateInstrument : FPRInstrument <FPRObjectInstrumentorProtocol>
|
||||
|
||||
/** Registers an instrument for a delegate class if it hasn't yet been instrumented.
|
||||
*
|
||||
* @note This method is thread-safe.
|
||||
* @param aClass The class to instrument.
|
||||
*/
|
||||
- (void)registerClass:(Class)aClass;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,307 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/Network/Delegates/FPRNSURLConnectionDelegateInstrument.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRClassInstrumentor.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRInstrument_Private.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRSelectorInstrumentor.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/Network/Delegates/FPRNSURLConnectionDelegate.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/Network/FPRNetworkInstrumentHelpers.h"
|
||||
|
||||
#pragma mark - NSURLConnectionDelegate methods
|
||||
|
||||
/** Returns the dispatch queue for all instrumentation to occur on. */
|
||||
static dispatch_queue_t GetInstrumentationQueue(void) {
|
||||
static dispatch_queue_t queue;
|
||||
static dispatch_once_t token;
|
||||
dispatch_once(&token, ^{
|
||||
queue = dispatch_queue_create("com.google.FPRNSURLConnectionDelegateInstrument",
|
||||
DISPATCH_QUEUE_SERIAL);
|
||||
});
|
||||
return queue;
|
||||
}
|
||||
|
||||
/** Instruments connection:didFailWithError:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionDidFailWithError(FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connection:didFailWithError:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor
|
||||
setReplacingBlock:^(id object, NSURLConnection *connection, NSError *error) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace didCompleteRequestWithResponse:nil error:error];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:connection];
|
||||
typedef void (*OriginalImp)(id, SEL, NSURLConnection *, NSError *);
|
||||
((OriginalImp)currentIMP)(object, selector, connection, error);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSURLConnectionDataDelegate methods
|
||||
|
||||
/** Instruments connection:willSendRequest:redirectResponse:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionWillSendRequestRedirectResponse(FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connection:willSendRequest:redirectResponse:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor setReplacingBlock:^(id object, NSURLConnection *connection,
|
||||
NSURLRequest *request, NSURLResponse *response) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
typedef NSURLRequest *(*OriginalImp)(id, SEL, NSURLConnection *, NSURLRequest *,
|
||||
NSURLResponse *);
|
||||
return ((OriginalImp)currentIMP)(object, selector, connection, request, response);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruments connection:didReceiveResponse:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionDidReceiveResponse(FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connection:didReceiveResponse:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor
|
||||
setReplacingBlock:^(id object, NSURLConnection *connection, NSURLResponse *response) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
trace.responseCode = (int32_t)((NSHTTPURLResponse *)response).statusCode;
|
||||
}
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
typedef void (*OriginalImp)(id, SEL, NSURLConnection *, NSURLResponse *);
|
||||
((OriginalImp)currentIMP)(object, selector, connection, response);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruments connection:didReceiveData:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionDidReceiveData(FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connection:didReceiveData:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor
|
||||
setReplacingBlock:^(id object, NSURLConnection *connection, NSData *data) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
trace.responseSize += data.length;
|
||||
typedef void (*OriginalImp)(id, SEL, NSURLConnection *, NSData *);
|
||||
((OriginalImp)currentIMP)(object, selector, connection, data);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruments connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionAllTheTotals(FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor
|
||||
setReplacingBlock:^(id object, NSURLConnection *connection, NSInteger bytesWritten,
|
||||
NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
trace.requestSize = totalBytesWritten;
|
||||
if (totalBytesWritten >= totalBytesExpectedToWrite) {
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateRequestCompleted];
|
||||
}
|
||||
typedef void (*OriginalImp)(id, SEL, NSURLConnection *, NSInteger, NSInteger, NSInteger);
|
||||
((OriginalImp)currentIMP)(object, selector, connection, bytesWritten, totalBytesWritten,
|
||||
totalBytesExpectedToWrite);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruments connectionDidFinishLoading:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionDidFinishLoading(FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connectionDidFinishLoading:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor setReplacingBlock:^(id object, NSURLConnection *connection) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace didCompleteRequestWithResponse:nil error:nil];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:connection];
|
||||
typedef void (*OriginalImp)(id, SEL, NSURLConnection *);
|
||||
((OriginalImp)currentIMP)(object, selector, connection);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruments connection:didWriteData:totalBytesWritten:expectedTotalBytes:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionDidWriteDataTotalBytesWrittenExpectedTotalBytes(
|
||||
FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connection:didWriteData:totalBytesWritten:expectedTotalBytes:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor
|
||||
setReplacingBlock:^(id object, NSURLConnection *connection, long long bytesWritten,
|
||||
long long totalBytesWritten, long long expectedTotalBytes) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
trace.requestSize = totalBytesWritten;
|
||||
typedef void (*OriginalImp)(id, SEL, NSURLConnection *, long long, long long, long long);
|
||||
((OriginalImp)currentIMP)(object, selector, connection, bytesWritten, totalBytesWritten,
|
||||
expectedTotalBytes);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruments connectionDidFinishDownloading:destinationURL:.
|
||||
*
|
||||
* @param instrumentor The FPRClassInstrumentor to add the selector instrumentor to.
|
||||
*/
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void InstrumentConnectionDidFinishDownloadingDestinationURL(FPRClassInstrumentor *instrumentor) {
|
||||
SEL selector = @selector(connectionDidFinishDownloading:destinationURL:);
|
||||
FPRSelectorInstrumentor *selectorInstrumentor =
|
||||
[instrumentor instrumentorForInstanceSelector:selector];
|
||||
if (selectorInstrumentor) {
|
||||
IMP currentIMP = selectorInstrumentor.currentIMP;
|
||||
[selectorInstrumentor
|
||||
setReplacingBlock:^(id object, NSURLConnection *connection, NSURL *destinationURL) {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:connection];
|
||||
[trace didReceiveFileURL:destinationURL];
|
||||
[trace didCompleteRequestWithResponse:nil error:nil];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:connection];
|
||||
typedef void (*OriginalImp)(id, SEL, NSURLConnection *, NSURL *);
|
||||
((OriginalImp)currentIMP)(object, selector, connection, destinationURL);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Helper functions
|
||||
FOUNDATION_STATIC_INLINE
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
void CopySelector(SEL selector, FPRObjectInstrumentor *instrumentor) {
|
||||
static Class fromClass = Nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
fromClass = [FPRNSURLConnectionDelegate class];
|
||||
});
|
||||
if (![instrumentor.instrumentedObject respondsToSelector:selector]) {
|
||||
[instrumentor copySelector:selector fromClass:fromClass isClassSelector:NO];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FPRNSURLConnectionDelegateInstrument
|
||||
|
||||
@implementation FPRNSURLConnectionDelegateInstrument
|
||||
|
||||
- (void)registerInstrumentors {
|
||||
// Do nothing by default. classes will be instrumented on-demand upon discovery.
|
||||
}
|
||||
|
||||
- (void)registerClass:(Class)aClass {
|
||||
dispatch_sync(GetInstrumentationQueue(), ^{
|
||||
// If this class has already been instrumented, just return.
|
||||
FPRClassInstrumentor *instrumentor = [[FPRClassInstrumentor alloc] initWithClass:aClass];
|
||||
if (![self registerClassInstrumentor:instrumentor]) {
|
||||
return;
|
||||
}
|
||||
|
||||
InstrumentConnectionDidFailWithError(instrumentor);
|
||||
InstrumentConnectionWillSendRequestRedirectResponse(instrumentor);
|
||||
InstrumentConnectionDidReceiveResponse(instrumentor);
|
||||
InstrumentConnectionDidReceiveData(instrumentor);
|
||||
InstrumentConnectionAllTheTotals(instrumentor);
|
||||
InstrumentConnectionDidFinishLoading(instrumentor);
|
||||
InstrumentConnectionDidWriteDataTotalBytesWrittenExpectedTotalBytes(instrumentor);
|
||||
InstrumentConnectionDidFinishDownloadingDestinationURL(instrumentor);
|
||||
|
||||
[instrumentor swizzle];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)registerObject:(id)object {
|
||||
dispatch_sync(GetInstrumentationQueue(), ^{
|
||||
if ([object respondsToSelector:@selector(gul_class)]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (![self isObjectInstrumentable:object]) {
|
||||
return;
|
||||
}
|
||||
|
||||
FPRObjectInstrumentor *instrumentor = [[FPRObjectInstrumentor alloc] initWithObject:object];
|
||||
|
||||
// Register the non-swizzled versions of these methods.
|
||||
CopySelector(@selector(connection:didFailWithError:), instrumentor);
|
||||
CopySelector(@selector(connection:willSendRequest:redirectResponse:), instrumentor);
|
||||
CopySelector(@selector(connection:didReceiveResponse:), instrumentor);
|
||||
CopySelector(@selector(connection:didReceiveData:), instrumentor);
|
||||
CopySelector(@selector(connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:),
|
||||
instrumentor);
|
||||
if (![object respondsToSelector:@selector(connectionDidFinishDownloading:destinationURL:)]) {
|
||||
CopySelector(@selector(connectionDidFinishLoading:), instrumentor);
|
||||
}
|
||||
|
||||
CopySelector(@selector(connection:didWriteData:totalBytesWritten:expectedTotalBytes:),
|
||||
instrumentor);
|
||||
if (![object respondsToSelector:@selector(connectionDidFinishLoading:)]) {
|
||||
CopySelector(@selector(connectionDidFinishDownloading:destinationURL:), instrumentor);
|
||||
}
|
||||
|
||||
[instrumentor swizzle];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,27 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 <Foundation/Foundation.h>
|
||||
|
||||
/** This class exists as a supplier of implementations for delegates that do not implement all
|
||||
* methods. While swizzling a delegate, if their class doesn't implement the below methods, these
|
||||
* implementations will be copied onto the delegate class.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRNSURLSessionDelegate : NSObject <NSURLSessionDelegate,
|
||||
NSURLSessionDataDelegate,
|
||||
NSURLSessionTaskDelegate,
|
||||
NSURLSessionDownloadDelegate>
|
||||
|
||||
@end
|
||||
@ -0,0 +1,84 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/Network/Delegates/FPRNSURLSessionDelegate.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/FPRConsoleLogger.h"
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
|
||||
|
||||
@implementation FPRNSURLSessionDelegate
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
task:(NSURLSessionTask *)task
|
||||
didCompleteWithError:(NSError *)error {
|
||||
@try {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:task];
|
||||
[trace didCompleteRequestWithResponse:task.response error:error];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:task];
|
||||
} @catch (NSException *exception) {
|
||||
FPRLogWarning(kFPRNetworkTraceNotTrackable, @"Unable to track network request.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
task:(NSURLSessionTask *)task
|
||||
didSendBodyData:(int64_t)bytesSent
|
||||
totalBytesSent:(int64_t)totalBytesSent
|
||||
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
|
||||
@try {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:task];
|
||||
trace.requestSize = totalBytesSent;
|
||||
if (totalBytesSent >= totalBytesExpectedToSend) {
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateRequestCompleted];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
FPRLogWarning(kFPRNetworkTraceNotTrackable, @"Unable to track network request.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
dataTask:(NSURLSessionDataTask *)dataTask
|
||||
didReceiveData:(NSData *)data {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:dataTask];
|
||||
[trace didReceiveData:data];
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
downloadTask:(NSURLSessionDownloadTask *)downloadTask
|
||||
didFinishDownloadingToURL:(NSURL *)location {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:downloadTask];
|
||||
[trace didReceiveFileURL:location];
|
||||
[trace didCompleteRequestWithResponse:downloadTask.response error:downloadTask.error];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:downloadTask];
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session
|
||||
downloadTask:(NSURLSessionDownloadTask *)downloadTask
|
||||
didWriteData:(int64_t)bytesWritten
|
||||
totalBytesWritten:(int64_t)totalBytesWritten
|
||||
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
|
||||
FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:downloadTask];
|
||||
[trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
|
||||
trace.responseSize = totalBytesWritten;
|
||||
if (totalBytesWritten >= totalBytesExpectedToWrite) {
|
||||
if ([downloadTask.response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)downloadTask.response;
|
||||
[trace didCompleteRequestWithResponse:response error:downloadTask.error];
|
||||
[FPRNetworkTrace removeNetworkTraceFromObject:downloadTask];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,36 @@
|
||||
// Copyright 2020 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
|
||||
//
|
||||
// http://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 "FirebasePerformance/Sources/Instrumentation/FPRInstrument.h"
|
||||
|
||||
#import "FirebasePerformance/Sources/Instrumentation/FPRObjectInstrumentor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** This class instruments the delegate methods needed to start/stop traces correctly. This class is
|
||||
* not intended to be used standalone--it should only be used by FPRNSURLSessionInstrument.
|
||||
*/
|
||||
NS_EXTENSION_UNAVAILABLE("Firebase Performance is not supported for extensions.")
|
||||
@interface FPRNSURLSessionDelegateInstrument : FPRInstrument <FPRObjectInstrumentorProtocol>
|
||||
|
||||
/** Registers an instrumentor for a delegate class if it hasn't yet been instrumented.
|
||||
*
|
||||
* @note This method is thread-safe.
|
||||
* @param aClass The class to instrument.
|
||||
*/
|
||||
- (void)registerClass:(Class)aClass;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user