Skip to content

Commit

Permalink
feat: finalize third-party logging system
Browse files Browse the repository at this point in the history
  • Loading branch information
OlenaPostindustria committed Jan 8, 2025
1 parent 04c1471 commit bffef8e
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 147 deletions.
8 changes: 6 additions & 2 deletions PrebidMobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
5355ACAB29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5355ACAA29C454770014F16E /* CreativeModelCollectionMakerVASTTests.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 @@ -1004,6 +1005,7 @@
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>"; };
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 @@ -1966,6 +1968,7 @@
FAEE4CE2262DC2B200AD9966 /* Log.swift */,
531CF21827E8FC1B005E5ABE /* LogLevel.swift */,
53F096C927E917D40058C94C /* Log+Extensions.h */,
535ADE112D2EA2F500DB888F /* PrebidLogger.swift */,
F9F0999C2C78CC8A007DB464 /* SDKConsoleLogger.swift */,
);
path = Logging;
Expand Down Expand Up @@ -2052,6 +2055,7 @@
5BC3764E271F1CFD00444D5E /* ExtensionsAndWrappers */ = {
isa = PBXGroup;
children = (
5BC37666271F1CFD00444D5E /* NSTimer */,
5BC37652271F1CFD00444D5E /* Exposure */,
5BC37659271F1CFD00444D5E /* NSDictionary+PBMExtensions.h */,
5BC3765F271F1CFD00444D5E /* NSDictionary+PBMExtensions.m */,
Expand All @@ -2063,18 +2067,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 @@ -4379,6 +4382,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"
}
184 changes: 55 additions & 129 deletions PrebidMobile/Logging/Log.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,78 +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 logger: PrebidLogger? = SDKConsoleLogger()
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
}

public static func setCustomLogger(customLogger: PrebidLogger?) {
logger = customLogger
}

/// 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)
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)
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)
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)
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)
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)
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)
logger?.whereAmI(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?.log(object, logLevel: logLevel, filename: filename, line: line, function: function)
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 @@ -105,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 @@ -118,103 +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)

private static var logFileURL = getURLForDoc(sdkName + ".txt")
// MARK: - Private Properties

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 var logger: PrebidLogger = SDKConsoleLogger()

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

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
}

public protocol PrebidLogger {

func error(_ object: Any, filename: String, line: Int, function: String)

func info(_ object: Any, filename: String, line: Int, function: String)

func debug(_ object: Any, filename: String, line: Int, function: String)

func verbose(_ object: Any, filename: String, line: Int, function: String)

func warn(_ object: Any, filename: String, line: Int, function: String)

func severe(_ object: Any, filename: String, line: Int, function: String)

func whereAmI(filename: String, line: Int, function: String)

func log(_ object: Any, logLevel: LogLevel, filename: String, line: Int, function: String)

private static let logFileURL = URL.temporaryURL(for: PrebidConstants.SDK_NAME + ".txt")
}
Loading

0 comments on commit bffef8e

Please sign in to comment.