Skip to content

Commit

Permalink
Custom logger implementation on iOS (#1026)
Browse files Browse the repository at this point in the history
* Made custom logger.

* Forgot to set to nil afterwards.

* Fixing customLogger Implementation

* Fixing issues.

* Included log function in other functions.

* Trying to fix build errors.

* Does this fix it?

* More testing.

* fix: fix error in project settings

* fix: add missing file

* feat: finalize third-party logging system

---------

Co-authored-by: Olena Stepaniuk <[email protected]>
  • Loading branch information
jsligh and OlenaPostindustria authored Jan 10, 2025
1 parent 839d5b8 commit 110f6d2
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 108 deletions.
20 changes: 15 additions & 5 deletions PrebidMobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@
53514CF22D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */; };
5355ACA929C454070014F16E /* VAST_with_empty_companion.xml in Resources */ = {isa = PBXBuildFile; fileRef = 5355ACA829C454070014F16E /* VAST_with_empty_companion.xml */; };
5355ACAB29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5355ACAA29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift */; };
536469C02D2FD78200F50B6D /* PluginEventDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536469BF2D2FD78200F50B6D /* PluginEventDelegate.swift */; };
535ADE0B2D2E970200DB888F /* SDKConsoleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9F0999C2C78CC8A007DB464 /* SDKConsoleLogger.swift */; };
535ADE102D2E987E00DB888F /* PluginEventDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535ADE0F2D2E987E00DB888F /* PluginEventDelegate.swift */; };
535ADE122D2EA2F500DB888F /* PrebidLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535ADE112D2EA2F500DB888F /* PrebidLogger.swift */; };
536A39262A84C50F00B1CCEA /* StringExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536A39252A84C50F00B1CCEA /* StringExtensionsTest.swift */; };
536A427F282D11DA0069E9B2 /* PrebidServerConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536A427E282D11DA0069E9B2 /* PrebidServerConnection.swift */; };
536A4283282D12E80069E9B2 /* PrebidServerConnectionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536A4282282D12E80069E9B2 /* PrebidServerConnectionProtocol.swift */; };
Expand Down Expand Up @@ -816,6 +818,7 @@
A908694229E05EAF00B37479 /* PrebidMobilePluginRegister.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */; };
A908694429E05ED500B37479 /* PrebidMobilePluginRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */; };
A908694629E05F7900B37479 /* PrebidRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694529E05F7900B37479 /* PrebidRenderer.swift */; };
F9F0999B2C78C668007DB464 /* SDKConsoleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = F91B60A82C52A73500DA9796 /* SDKConsoleLogger.swift */; };
FA5AD5E42271FA4100C8F274 /* ConstantsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5AD5E32271FA4100C8F274 /* ConstantsTest.swift */; };
FA9D7F2722E8A83D006FCBEF /* AdViewUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA9D7F2622E8A83D006FCBEF /* AdViewUtilsTests.swift */; };
FAA29904242D1C27002ACBF2 /* TargetingObjCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FAA29903242D1C27002ACBF2 /* TargetingObjCTests.m */; };
Expand Down Expand Up @@ -1008,7 +1011,8 @@
53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialControllerInteractionDelegate.swift; sourceTree = "<group>"; };
5355ACA829C454070014F16E /* VAST_with_empty_companion.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = VAST_with_empty_companion.xml; sourceTree = "<group>"; };
5355ACAA29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreativeModelCollectionMakerVASTTests.swift; sourceTree = "<group>"; };
536469BF2D2FD78200F50B6D /* PluginEventDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginEventDelegate.swift; sourceTree = "<group>"; };
535ADE0F2D2E987E00DB888F /* PluginEventDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginEventDelegate.swift; sourceTree = "<group>"; };
535ADE112D2EA2F500DB888F /* PrebidLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidLogger.swift; sourceTree = "<group>"; };
536A39252A84C50F00B1CCEA /* StringExtensionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensionsTest.swift; sourceTree = "<group>"; };
536A427E282D11DA0069E9B2 /* PrebidServerConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerConnection.swift; sourceTree = "<group>"; };
536A4282282D12E80069E9B2 /* PrebidServerConnectionProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerConnectionProtocol.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1744,6 +1748,7 @@
A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobilePluginRegister.swift; sourceTree = "<group>"; };
A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobilePluginRenderer.swift; sourceTree = "<group>"; };
A908694529E05F7900B37479 /* PrebidRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidRenderer.swift; sourceTree = "<group>"; };
F9F0999C2C78CC8A007DB464 /* SDKConsoleLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKConsoleLogger.swift; sourceTree = "<group>"; };
FA4A88432497A99D00FDCBB6 /* Swizzling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swizzling.swift; sourceTree = "<group>"; };
FA5AD5E32271FA4100C8F274 /* ConstantsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantsTest.swift; sourceTree = "<group>"; };
FA85F9B4264946FC00B8BE72 /* TestUtils.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TestUtils.xcodeproj; path = ../tools/TestUtils/TestUtils.xcodeproj; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1970,6 +1975,8 @@
FAEE4CE2262DC2B200AD9966 /* Log.swift */,
531CF21827E8FC1B005E5ABE /* LogLevel.swift */,
53F096C927E917D40058C94C /* Log+Extensions.h */,
535ADE112D2EA2F500DB888F /* PrebidLogger.swift */,
F9F0999C2C78CC8A007DB464 /* SDKConsoleLogger.swift */,
);
path = Logging;
sourceTree = "<group>";
Expand Down Expand Up @@ -2056,6 +2063,7 @@
5BC3764E271F1CFD00444D5E /* ExtensionsAndWrappers */ = {
isa = PBXGroup;
children = (
5BC37666271F1CFD00444D5E /* NSTimer */,
5BC37652271F1CFD00444D5E /* Exposure */,
5BC37659271F1CFD00444D5E /* NSDictionary+PBMExtensions.h */,
5BC3765F271F1CFD00444D5E /* NSDictionary+PBMExtensions.m */,
Expand All @@ -2067,18 +2075,17 @@
5BC3765A271F1CFD00444D5E /* NSNumber+PBMORTBNative.m */,
5BC3764F271F1CFD00444D5E /* NSString+PBMExtensions.h */,
5BC37662271F1CFD00444D5E /* NSString+PBMExtensions.m */,
5BC37666271F1CFD00444D5E /* NSTimer */,
5BC3765B271F1CFD00444D5E /* PBMTouchDownRecognizer.h */,
5BC3766E271F1CFD00444D5E /* PBMTouchDownRecognizer.m */,
5BC37650271F1CFD00444D5E /* UIView+PBMExtensions.h */,
5BC37661271F1CFD00444D5E /* UIView+PBMExtensions.m */,
5BC3765E271F1CFD00444D5E /* UIWindow+PBMExtensions.h */,
5BC3766F271F1CFD00444D5E /* UIWindow+PBMExtensions.m */,
53C925012990FB30009E6F94 /* String+Extensions.swift */,
53D3C38B2C2BEF9B0074D99B /* NSURL+PBMExtensions.h */,
53D3C38C2C2BEF9B0074D99B /* NSURL+PBMExtensions.m */,
535145DE2CCB758800D40B19 /* NSObject+PBMExtensions.h */,
535145DF2CCB758800D40B19 /* NSObject+PBMExtensions.m */,
53C925012990FB30009E6F94 /* String+Extensions.swift */,
);
path = ExtensionsAndWrappers;
sourceTree = "<group>";
Expand Down Expand Up @@ -3300,7 +3307,7 @@
A908694029E05E8D00B37479 /* PluginRenderer */ = {
isa = PBXGroup;
children = (
536469BF2D2FD78200F50B6D /* PluginEventDelegate.swift */,
535ADE0F2D2E987E00DB888F /* PluginEventDelegate.swift */,
A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */,
A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */,
53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */,
Expand Down Expand Up @@ -4119,6 +4126,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
535ADE0B2D2E970200DB888F /* SDKConsoleLogger.swift in Sources */,
5BC37AB1271F1D0000444D5E /* DemandResponseInfo.swift in Sources */,
5BC37AAE271F1D0000444D5E /* BannerEventHandlerStandalone.swift in Sources */,
5BC378DF271F1CFF00444D5E /* PBMORTBApp.m in Sources */,
Expand Down Expand Up @@ -4155,6 +4163,7 @@
2A9DDDD42C63665A000EA4A0 /* PBMEventDelegateHelper.swift in Sources */,
5BC379AC271F1D0000444D5E /* PBMModalManager.m in Sources */,
FAEE4D1C262DC2B200AD9966 /* InstreamVideoAdUnit.swift in Sources */,
535ADE102D2E987E00DB888F /* PluginEventDelegate.swift in Sources */,
53B221D12A0E3D3D00C91CCB /* PrebidJSLibraryManager.swift in Sources */,
5BC37970271F1D0000444D5E /* PBMVastAbstractAd.m in Sources */,
53BDBF89293F5EFF004B6DE8 /* InternalUserConsentDataManager.m in Sources */,
Expand Down Expand Up @@ -4386,6 +4395,7 @@
928E5A7027F0F743000ADA1A /* ContextSubType.swift in Sources */,
5BC37A20271F1D0000444D5E /* PBMORTBMacrosHelper.m in Sources */,
92989653275FE98C00D3C174 /* PBMORTBContentData.m in Sources */,
535ADE122D2EA2F500DB888F /* PrebidLogger.swift in Sources */,
5BC378BB271F1CFF00444D5E /* NSNumber+PBMORTBNative.m in Sources */,
5BC37961271F1D0000444D5E /* PBMVastAdsBuilder.m in Sources */,
5BC37A91271F1D0000444D5E /* InterstitialEventLoadingDelegate.swift in Sources */,
Expand Down
8 changes: 4 additions & 4 deletions PrebidMobile/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ import UIKit

public let PrebidLocalCacheIdKey = "hb_cache_id_local"

@objc public class Constants: NSObject {
@objc public static let PREBID_VERSION = "2.3.1"
}

extension String {

static let EMPTY_String = ""
Expand Down Expand Up @@ -117,4 +113,8 @@ public class PrebidConstants: NSObject {
</html>
"""
}

public static let PREBID_VERSION = "2.3.1"

public static let SDK_NAME = "prebid-mobile-sdk"
}
152 changes: 55 additions & 97 deletions PrebidMobile/Logging/Log.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,66 +15,90 @@

import Foundation

/// This class serves as the central point for all logging operations within the SDK.
/// It allows for categorized logging based on severity levels (e.g., error, warning, debug) and offers options for both console and file-based logging.
/// It also provides the ability to set third-party logger.
@objc(PBMLog) @objcMembers
public class Log: NSObject {

// MARK: - Public properties

public static var dateFormat = "yyyy-MM-dd hh:mm:ssSSS"
public static var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = dateFormat
formatter.locale = Locale.current
formatter.timeZone = TimeZone.current
return formatter
}

/// The current logging level. Only messages at this level or higher will be logged.
public static var logLevel: LogLevel = .debug

/// Indicates whether logs should also be saved to a file.
public static var logToFile = false

/// Sets a custom logger to handle log messages.
public static func setCustomLogger(_ logger: PrebidLogger) {
self.logger = logger
}

public static func error(_ object: Any, filename: String = #file, line: Int = #line, function: String = #function) {
log(object, logLevel: .error, filename: filename, line: line, function: function)
logger.error(object, filename: filename, line: line, function: function)
}

public static func info(_ object: Any, filename: String = #file, line: Int = #line, function: String = #function) {
log(object, logLevel: .info, filename: filename, line: line, function: function)
logger.info(object, filename: filename, line: line, function: function)
}

public static func debug(_ object: Any, filename: String = #file, line: Int = #line, function: String = #function) {
log(object, logLevel: .debug, filename: filename, line: line, function: function)
logger.debug(object, filename: filename, line: line, function: function)
}

public static func verbose(_ object: Any, filename: String = #file, line: Int = #line, function: String = #function) {
log(object, logLevel: .verbose, filename: filename, line: line, function: function)
logger.verbose(object, filename: filename, line: line, function: function)
}

public static func warn(_ object: Any, filename: String = #file, line: Int = #line, function: String = #function) {
log(object, logLevel: .warn, filename: filename, line: line, function: function)
logger.warn(object, filename: filename, line: line, function: function)
}

public static func severe(_ object: Any, filename: String = #file, line: Int = #line, function: String = #function) {
log(object, logLevel: .severe, filename: filename, line: line, function: function)
logger.severe(object, filename: filename, line: line, function: function)
}

public static func whereAmI(filename: String = #file, line: Int = #line, function: String = #function) {
log("", logLevel: .info, filename: filename, line: line, function: function)
}

static func log(_ object: Any, logLevel: LogLevel, filename: String, line: Int, function: String) {
if isLoggingEnabled(for: logLevel) {
let finalMessage = "\(sdkName): \(Date().toString()) \(logLevel.stringValue)[\(sourceFileName(filePath: filename))]:\(line) \(function) -> \(object)"
print(finalMessage)
serialWriteToLog(finalMessage)
}
logger.whereAmI(filename: filename, line: line, function: function)
}

/// Writes a log message to the log file asynchronously.
///
/// - Parameter message: The log message to be written to the file.
public static func serialWriteToLog(_ message: String) {
loggingQueue.async {
writeToLogFile(message)
}
}

public static func writeToLogFile(_ message: String) {
/// Reads the contents of the log file as a single string.
public static func getLogFileAsString() -> String? {
loggingQueue.sync {
if let logFileURL = logFileURL {
do {
return try String(contentsOf: logFileURL, encoding: .utf8)
} catch {
Log.error("\(PrebidConstants.SDK_NAME) Error getting log file: \(error.localizedDescription)")
}
}
return nil
}
}

/// Clears the contents of the log file.
public static func clearLogFile() {
loggingQueue.sync {
do {
if let logFileURL = logFileURL {
try "".data(using: .utf8)?.write(to: logFileURL)
}
} catch {
Log.error("\(PrebidConstants.SDK_NAME) Error clearing log file: \(error.localizedDescription)")
}
}
}

static func writeToLogFile(_ message: String) {
if !Log.logToFile {
return
}
Expand All @@ -93,7 +117,7 @@ public class Log: NSObject {
try fileHandle.write(contentsOf: data)
try fileHandle.close()
} catch {
Log.error("\(sdkName) Couldn't write to log file: \(error.localizedDescription)")
Log.error("\(PrebidConstants.SDK_NAME) Couldn't write to log file: \(error.localizedDescription)")
}
} else {
fileHandle.seekToEndOfFile()
Expand All @@ -106,83 +130,17 @@ public class Log: NSObject {
do {
try data.write(to: logFileURL)
} catch {
Log.error("\(sdkName) Couldn't write to log file URL: \(error.localizedDescription)")
}
}
}
}

public static func getLogFileAsString() -> String? {
loggingQueue.sync {
if let logFileURL = logFileURL {
do {
return try String(contentsOf: logFileURL, encoding: .utf8)
} catch {
Log.error("\(sdkName) Error getting log file: \(error.localizedDescription)")
}
}
return nil
}
}

public static func clearLogFile() {
loggingQueue.sync {
do {
if let logFileURL = logFileURL {
try "".data(using: .utf8)?.write(to: logFileURL)
Log.error("\(PrebidConstants.SDK_NAME) Couldn't write to log file URL: \(error.localizedDescription)")
}
} catch {
Log.error("\(sdkName) Error clearing log file: \(error.localizedDescription)")
}
}
}

// MARK: - Internal properties and methods

private static let sdkName = "prebid-mobile-sdk"

private static let loggingQueue = DispatchQueue(label: sdkName)
// MARK: - Private Properties

private static var logFileURL = getURLForDoc(sdkName + ".txt")
private static var logger: PrebidLogger = SDKConsoleLogger()

private class func isLoggingEnabled(for currentLevel: LogLevel) -> Bool {
#if !(DEBUG)
return false
#endif

if currentLevel.rawValue < Log.logLevel.rawValue {
return false
}

return true
}
private static let loggingQueue = DispatchQueue(label: PrebidConstants.SDK_NAME)

private static func getURLForDoc(_ docName: String) -> URL? {
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
return temporaryDirectoryURL.appendingPathComponent(docName)
}

private static func sourceFileName(filePath: String) -> String {
let components = filePath.components(separatedBy: "/")
return components.isEmpty ? "" : components.last!
}
}

extension Date {
func toString() -> String {
return Log.dateFormatter.string(from: self as Date)
}
}

/// Wrapping Swift.print() within DEBUG flag
///
/// - Note: *print()* might cause [security vulnerabilities](https://codifiedsecurity.com/mobile-app-security-testing-checklist-ios/)
///
/// - Parameter object: The object which is to be logged
///
func print(_ object: Any) {
// Only allowing in DEBUG mode
#if DEBUG
Swift.print(object)
#endif
private static let logFileURL = URL.temporaryURL(for: PrebidConstants.SDK_NAME + ".txt")
}
Loading

0 comments on commit 110f6d2

Please sign in to comment.