Skip to content

Commit

Permalink
Merge pull request #497 from wakmusic/496-add-logging-manager
Browse files Browse the repository at this point in the history
🔀 :: (#496) Analytics를 위한 로깅 매니저 추가
  • Loading branch information
baekteun authored Apr 23, 2024
2 parents 2dc5912 + 33a3236 commit 6090fea
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public extension ModulePaths {

public extension ModulePaths {
enum Module: String, MicroTargetPathConvertable {
case LogManager
case ErrorModule
case FeatureThirdPartyLib
case KeychainModule
Expand Down
41 changes: 40 additions & 1 deletion Projects/App/Sources/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import AVKit
import BaseFeature
import FirebaseAnalytics
import FirebaseCore
import FirebaseCrashlytics
import LogManager
import NaverThirdPartyLogin
import RealmSwift
import RootFeature
Expand All @@ -13,7 +15,7 @@ import Utility
// import AWSS3StoragePlugin

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
Expand All @@ -22,6 +24,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

// Use Firebase library to configure APIs
FirebaseApp.configure()
setAnalyticsDefaultParameters()
if let userID = PreferenceManager.userInfo?.ID {
LogManager.setUserID(userID: AES256.decrypt(encoded: userID))
} else {
LogManager.setUserID(userID: nil)
}

Analytics.logEvent(AnalyticsEventAppOpen, parameters: nil)

// configure NaverThirdPartyLoginConnection
Expand Down Expand Up @@ -64,3 +73,33 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didDiscardSceneSessions sceneSessions: Set<UISceneSession>
) {}
}

private extension AppDelegate {
func setAnalyticsDefaultParameters() {
let platform = "iOS"
let os = "iOS \(UIDevice.current.systemVersion)"
let device = Device().modelName
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "unknown"

let currentLocale = Locale.current
let region = if #available(iOS 16.0, *) {
currentLocale.region?.identifier ?? ""
} else {
currentLocale.regionCode ?? "unknown"
}
let language = if #available(iOS 16.0, *) {
currentLocale.language.languageCode?.identifier ?? "unknown"
} else {
currentLocale.languageCode ?? "unknown"
}

LogManager.setDefaultParameters(params: [
"platform": platform,
"os": os,
"device": device,
"version": version,
"region": region,
"language": language
])
}
}
12 changes: 12 additions & 0 deletions Projects/Modules/LogManager/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import DependencyPlugin
import ProjectDescription
import ProjectDescriptionHelpers

let project = Project.module(
name: ModulePaths.Module.LogManager.rawValue,
targets: [
.implements(module: .module(.LogManager), product: .framework, dependencies: [
.module(target: .ThirdPartyLib)
])
]
)
140 changes: 140 additions & 0 deletions Projects/Modules/LogManager/Sources/AnalyticsLogManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import FirebaseAnalytics
import Foundation
import OSLog
import ThirdPartyLib

fileprivate extension OSLog {
static let subSystem = Bundle.main.bundleIdentifier ?? ""
static let debug = OSLog(subsystem: subSystem, category: "DEBUG")
static let analytics = OSLog(subsystem: subSystem, category: "ANALYTICS")
static let error = OSLog(subsystem: subSystem, category: "ERROR")
}

private extension LogManager {
static func log(
_ message: Any,
level: Level,
file: String = #file,
function: String = #function,
line: Int = #line
) {
#if DEBUG
let logger = Logger(subsystem: OSLog.subSystem, category: level.category)

let fileName = file.components(separatedBy: "/").last ?? "unknown.swift"
let functionName = function.components(separatedBy: "(").first ?? "unknown"
let footerMessage = "\(fileName) | \(functionName):\(line)"

let logMessage = "[\(level.symbol) \(level.category)] > \(message)\n-> \(footerMessage)"
switch level {
case .debug:
logger.debug("\(logMessage)")
case .analytics:
logger.info("\(logMessage)")
case .error:
logger.error("\(logMessage)")
}
#endif
}
}

public enum LogManager {
fileprivate enum Level {
case debug
case analytics
case error

fileprivate var symbol: String {
switch self {
case .debug: "🔵"
case .analytics: "🟡"
case .error: "🔴"
}
}

fileprivate var category: String {
switch self {
case .debug: "DEBUG"
case .analytics: "ANALYTICS"
case .error: "ERROR"
}
}
}
}

public extension LogManager {
static func setUserID(
userID: String?,
file: String = #file,
function: String = #function,
line: Int = #line
) {
Analytics.setUserID(userID)

LogManager.printDebug(
"Set Analytics UserID : \(String(describing: userID))",
file: file,
function: function,
line: line
)
}

static func setDefaultParameters(
params: [String: Any],
file: String = #file,
function: String = #function,
line: Int = #line
) {
Analytics.setDefaultEventParameters(params)

LogManager.printDebug(
"Set Analytics Default Parameters :\n\(params)",
file: file,
function: function,
line: line
)
}

static func printDebug(
_ message: Any,
file: String = #file,
function: String = #function,
line: Int = #line
) {
LogManager.log(
message,
level: .debug,
file: file,
function: function,
line: line
)
}

static func analytics(
_ log: any AnalyticsLogType
) {
#if RELEASE
Analytics.logEvent(log.name, parameters: log.params)
#endif
let message = """
\(log.name) logged
parameters : \(log.params)
"""
LogManager.log(message, level: .analytics)
}

static func printError(
_ message: Any,
file: String = #file,
function: String = #function,
line: Int = #line
) {
LogManager.log(
message,
level: .error,
file: file,
function: function,
line: line
)
}
}
81 changes: 81 additions & 0 deletions Projects/Modules/LogManager/Sources/AnalyticsLogType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import Foundation

public protocol AnalyticsLogType {
var name: String { get }
var params: [String: Any] { get }
}

public extension AnalyticsLogType {
var name: String {
Mirror(reflecting: self)
.children
.first?
.label?
.toSnakeCase() ?? String(describing: self).toSnakeCase()
}

var params: [String: Any] {
let enumMirror = Mirror(reflecting: self)

guard let associated = enumMirror.children.first else { return [:] }

var dict: [String: Any] = [:]

for enumParams in Mirror(reflecting: associated.value).children {
guard let label = enumParams.label?.toSnakeCase() else { continue }
dict[label] = enumParams.value
}

let currentDate = Date()
let timestamp = currentDate.timeIntervalSince1970
let dateString = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter.string(from: currentDate)
}()

dict["timestamp"] = timestamp
dict["date"] = dateString

return dict
}
}

private extension String {
func toSnakeCase() -> String {
var result = ""
var previousStringWasCapitalized = false
var previousStringWasNumber = false

for (index, string) in self.enumerated() {
var mutableString = String(string)

if !mutableString.isAlphabet {
if index != 0,
!previousStringWasNumber {
mutableString = "_" + mutableString
}
previousStringWasNumber = true
} else if mutableString == mutableString.uppercased() {
mutableString = mutableString.lowercased()

// e.g. JSON으로 오면 j_s_o_n 이런식이 아닌 json 이렇게 바뀌도록
if index != 0,
!previousStringWasCapitalized {
mutableString = "_" + mutableString
}
previousStringWasCapitalized = true
} else {
previousStringWasCapitalized = false
previousStringWasNumber = false
}
result += mutableString
}
return result
}

var isAlphabet: Bool {
let alphabetSet = CharacterSet.uppercaseLetters.union(.lowercaseLetters).union(.whitespacesAndNewlines)
return self.rangeOfCharacter(from: alphabetSet.inverted) == nil
}
}
5 changes: 5 additions & 0 deletions Projects/Modules/LogManager/Sources/CommonAnalyticsLog.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

public enum CommonAnalyticsLog: AnalyticsLogType {
case viewPage(pageName: String)
}
1 change: 1 addition & 0 deletions Projects/Modules/Utility/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ let project = Project.makeModule(
name: "Utility",
product: .staticFramework,
dependencies: [
.module(target: .LogManager),
.Project.Module.ThirdPartyLib
]
)

0 comments on commit 6090fea

Please sign in to comment.