diff --git a/OktaLogger.podspec b/OktaLogger.podspec index 0cbf8ca..1601e38 100644 --- a/OktaLogger.podspec +++ b/OktaLogger.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "OktaLogger" - s.version = "1.2.3" + s.version = "1.3.0" s.summary = "Logging proxy for standardized logging interface across products" s.description = "Standard interface for all logging in Okta apps + SDK. Supports file, console, firebase logging destinations." s.homepage = "https://github.com/okta/okta-logger-swift" @@ -19,6 +19,7 @@ Pod::Spec.new do |s| s.subspec "Complete" do |complete| complete.dependency 'OktaLogger/FileLogger' complete.dependency 'OktaLogger/FirebaseCrashlytics' + complete.dependency 'OktaLogger/InstabugLogger' end s.subspec "MacOS" do |macos| @@ -52,13 +53,22 @@ Pod::Spec.new do |s| appCenterLogger.dependency 'OktaLogger/Core' end + s.subspec 'InstabugLogger' do |instabugLogger| + instabugLogger.ios.source_files = [ + 'OktaLogger/InstabugLogger/*' + ] + instabugLogger.ios.dependency 'Instabug', '~>10.7.5' + instabugLogger.ios.dependency 'OktaLogger/Core' + end + s.subspec "Core" do |core| core.source_files = 'OktaLogger/*.{h,m,swift}' core.exclude_files = [ 'OktaLogger/Info.plist', 'OktaLogger/FileLoggers', 'OktaLogger/FirebaseCrashlyticsLogger', - 'OktaLogger/AppCenterLogger' + 'OktaLogger/AppCenterLogger', + 'OktaLogger/InstabugLogger' ] end diff --git a/OktaLogger.xcodeproj/project.pbxproj b/OktaLogger.xcodeproj/project.pbxproj index 191d95f..1c0b188 100644 --- a/OktaLogger.xcodeproj/project.pbxproj +++ b/OktaLogger.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -32,8 +32,10 @@ DE2FFE21260B89650028CAD6 /* OktaLoggerFileLoggerMultithreadingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2FFE20260B89650028CAD6 /* OktaLoggerFileLoggerMultithreadingTests.swift */; }; DE504DC425BEE84A00B27BDD /* OktaLoggerFileLogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE504DC325BEE84A00B27BDD /* OktaLoggerFileLogFormatter.swift */; }; DE6A163725F1120100B0FBA0 /* LogsBrowseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE6A163625F1120100B0FBA0 /* LogsBrowseViewController.swift */; }; + DE9B02FF26BD6A090072A501 /* OktaLoggerInstabugLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9B02FE26BD6A090072A501 /* OktaLoggerInstabugLogger.swift */; }; DEABAFC9260C7C0100DB7008 /* FileTestsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEABAFC8260C7C0100DB7008 /* FileTestsHelper.swift */; }; DEC5276624DBF9630022B698 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DEC5276524DBF9630022B698 /* GoogleService-Info.plist */; }; + DEE498C726C1139A00487014 /* OktaLoggerInstabugLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEE498C626C1139A00487014 /* OktaLoggerInstabugLoggerTests.swift */; }; DEF2CC23260A341300F8B644 /* OktaLoggerMultithreadingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEF2CC22260A341300F8B644 /* OktaLoggerMultithreadingTests.swift */; }; DEFB59E124EAC76400A1744F /* OktaLoggerFirebaseCrashlyticsLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEFB59E024EAC76300A1744F /* OktaLoggerFirebaseCrashlyticsLogger.swift */; }; E251E7FE248AD1B400EF466D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E251E7FD248AD1B400EF466D /* AppDelegate.swift */; }; @@ -126,8 +128,10 @@ DE2FFE20260B89650028CAD6 /* OktaLoggerFileLoggerMultithreadingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OktaLoggerFileLoggerMultithreadingTests.swift; sourceTree = ""; }; DE504DC325BEE84A00B27BDD /* OktaLoggerFileLogFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OktaLoggerFileLogFormatter.swift; sourceTree = ""; }; DE6A163625F1120100B0FBA0 /* LogsBrowseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogsBrowseViewController.swift; sourceTree = ""; }; + DE9B02FE26BD6A090072A501 /* OktaLoggerInstabugLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OktaLoggerInstabugLogger.swift; sourceTree = ""; }; DEABAFC8260C7C0100DB7008 /* FileTestsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTestsHelper.swift; sourceTree = ""; }; DEC5276524DBF9630022B698 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + DEE498C626C1139A00487014 /* OktaLoggerInstabugLoggerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OktaLoggerInstabugLoggerTests.swift; sourceTree = ""; }; DEF2CC22260A341300F8B644 /* OktaLoggerMultithreadingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OktaLoggerMultithreadingTests.swift; sourceTree = ""; }; DEFB59E024EAC76300A1744F /* OktaLoggerFirebaseCrashlyticsLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OktaLoggerFirebaseCrashlyticsLogger.swift; sourceTree = ""; }; DF75E3D21D2B9A971A2CAEC7 /* libPods-OktaLoggerDemoApp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OktaLoggerDemoApp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -229,6 +233,7 @@ D5C824D62469DBF1005CF747 /* OktaLogger */ = { isa = PBXGroup; children = ( + DE9B02FD26BD697B0072A501 /* InstabugLogger */, 8DCF5F662644B23F008698CD /* AppCenterLogger */, 8004832F24C1F0F0008BFF3A /* FileLoggers */, DEFB59DF24EAC76300A1744F /* FirebaseCrashlyticsLogger */, @@ -252,6 +257,7 @@ 804F18F624C0174800894A52 /* OktaLoggerFileLoggerTests.swift */, DE2FFE20260B89650028CAD6 /* OktaLoggerFileLoggerMultithreadingTests.swift */, D5D0978D246DE00800C1362F /* OktaLoggerConsoleLoggerTests.swift */, + DEE498C626C1139A00487014 /* OktaLoggerInstabugLoggerTests.swift */, D5D0978A246CB52900C1362F /* Helpers */, D5C824E42469DBF1005CF747 /* Info.plist */, D5B22D07246C8E39007ECC2F /* OktaLoggerTests-Bridging-Header.h */, @@ -270,6 +276,14 @@ path = Helpers; sourceTree = ""; }; + DE9B02FD26BD697B0072A501 /* InstabugLogger */ = { + isa = PBXGroup; + children = ( + DE9B02FE26BD6A090072A501 /* OktaLoggerInstabugLogger.swift */, + ); + path = InstabugLogger; + sourceTree = ""; + }; DEC9C9CB24E57AC800AAFAE0 /* Recovered References */ = { isa = PBXGroup; children = ( @@ -368,6 +382,7 @@ D5C824D92469DBF1005CF747 /* Sources */, D5C824DA2469DBF1005CF747 /* Frameworks */, D5C824DB2469DBF1005CF747 /* Resources */, + 9ECAD1E0171C5273C443BE35 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -389,6 +404,7 @@ E251E7F9248AD1B400EF466D /* Resources */, 80DDE77E24B961B400D0E2F3 /* Embed Frameworks */, DEC5276724DBFE6C0022B698 /* ShellScript */, + 20382702DB652A5C8D9E415D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -494,6 +510,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 20382702DB652A5C8D9E415D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-OktaLoggerDemoApp/Pods-OktaLoggerDemoApp-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-OktaLoggerDemoApp/Pods-OktaLoggerDemoApp-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-OktaLoggerDemoApp/Pods-OktaLoggerDemoApp-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3EDE391A122E4EE902619005 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -538,6 +571,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 9ECAD1E0171C5273C443BE35 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-OktaLoggerTests/Pods-OktaLoggerTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-OktaLoggerTests/Pods-OktaLoggerTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-OktaLoggerTests/Pods-OktaLoggerTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; DEC5276724DBFE6C0022B698 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -571,6 +621,7 @@ D54461CB246B55A600C755F1 /* OktaLoggerDestination.swift in Sources */, 8004832E24C1EFDF008BFF3A /* OktaLoggerFileLoggerConfig.swift in Sources */, 8DCF5F682644B25D008698CD /* AppCenterLogger.swift in Sources */, + DE9B02FF26BD6A090072A501 /* OktaLoggerInstabugLogger.swift in Sources */, 806FF25E24B95A3300994D4D /* OktaLoggerFileLogger.swift in Sources */, D52C2AD12474A4F5003CCF4D /* ReadWriteLock.swift in Sources */, 6582A2024047A1BC55BC98D3 /* LumberjackLoggerDelegate.swift in Sources */, @@ -583,6 +634,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DEE498C726C1139A00487014 /* OktaLoggerInstabugLoggerTests.swift in Sources */, 804F18F724C0174800894A52 /* OktaLoggerFileLoggerTests.swift in Sources */, D5D0978E246DE00800C1362F /* OktaLoggerConsoleLoggerTests.swift in Sources */, DEABAFC9260C7C0100DB7008 /* FileTestsHelper.swift in Sources */, diff --git a/OktaLogger/InstabugLogger/OktaLoggerInstabugLogger.swift b/OktaLogger/InstabugLogger/OktaLoggerInstabugLogger.swift new file mode 100644 index 0000000..018a0dc --- /dev/null +++ b/OktaLogger/InstabugLogger/OktaLoggerInstabugLogger.swift @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (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 Instabug + +/** + Concrete logging class for Instabug. + */ +open class OktaLoggerInstabugLogger: OktaLoggerDestinationBase { + + override open func log(level: OktaLoggerLogLevel, eventName: String, message: String?, properties: [AnyHashable: Any]?, file: String, line: NSNumber, funcName: String) { + guard Instabug.enabled else { + return + } + let logString = self.stringValue( + level: level, + eventName: eventName, + message: message, + file: file, + line: line, + funcName: funcName + ) + switch level { + case .all: + IBGLog.logVerbose(logString) + case .debug: + IBGLog.logDebug(logString) + case .info, .uiEvent: + IBGLog.logInfo(logString) + case .warning: + IBGLog.logWarn(logString) + case .error: + IBGLog.logError(logString) + case .off: + return + default: + return + } + } + + open override func stringValue(level: OktaLoggerLogLevel, eventName: String, message: String?, file: String, line: NSNumber, funcName: String) -> String { + let fileLogString = file.split(separator: "/").last ?? "" + let messageLogString: String = { + guard let message = message else { + return "" + } + return ". \(message)" + }() + return "\(eventName)\(messageLogString) | \(fileLogString):\(funcName):\(line)" + } +} diff --git a/OktaLoggerTests/OktaLoggerInstabugLoggerTests.swift b/OktaLoggerTests/OktaLoggerInstabugLoggerTests.swift new file mode 100644 index 0000000..42ad091 --- /dev/null +++ b/OktaLoggerTests/OktaLoggerInstabugLoggerTests.swift @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (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 XCTest +@testable import OktaLogger + +class OktaLoggerInstabugLoggerTests: XCTestCase { + + var instabugLogger: OktaLoggerInstabugLogger! + + override func setUp() { + super.setUp() + instabugLogger = OktaLoggerInstabugLogger( + identifier: "instabug-logger", + level: .all, + defaultProperties: nil + ) + } + + func testStringValueMessageNotNil() { + let actualLog = instabugLogger.stringValue( + level: .info, + eventName: "Test event", + message: "Test message", + file: "OktaLoggerInstabugLoggerTests.swift", + line: 29, + funcName: "testStringValueMessageNotNil()" + ) + XCTAssertEqual(actualLog, "Test event. Test message | OktaLoggerInstabugLoggerTests.swift:testStringValueMessageNotNil():29") + } + + func testStringValueMessageNil() { + let actualLog = instabugLogger.stringValue( + level: .info, + eventName: "Test event", + message: nil, + file: "OktaLoggerInstabugLoggerTests.swift", + line: 29, + funcName: "testStringValueMessageNotNil()" + ) + XCTAssertEqual(actualLog, "Test event | OktaLoggerInstabugLoggerTests.swift:testStringValueMessageNotNil():29") + } + + func testStringValueNoFileName() { + let actualLog = instabugLogger.stringValue( + level: .info, + eventName: "Test event", + message: "Test message", + file: "", + line: 29, + funcName: "testStringValueMessageNotNil()" + ) + XCTAssertEqual(actualLog, "Test event. Test message | :testStringValueMessageNotNil():29") + } +} diff --git a/Podfile b/Podfile index d209888..8b5f4c4 100644 --- a/Podfile +++ b/Podfile @@ -5,6 +5,7 @@ target 'OktaLogger' do pod 'AppCenter', '~>4.1.1' pod 'Firebase/Crashlytics', '~>7.4.0' pod 'CocoaLumberjack/Swift', '~>3.6.0' + pod 'Instabug', '~>10.7.5' end target 'OktaLoggerDemoApp' do diff --git a/Podfile.lock b/Podfile.lock index 3ec4678..272fa5a 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -43,28 +43,34 @@ PODS: - GoogleUtilities/Environment - GoogleUtilities/UserDefaults (7.2.2): - GoogleUtilities/Logger + - Instabug (10.7.5) - nanopb (2.30907.0): - nanopb/decode (= 2.30907.0) - nanopb/encode (= 2.30907.0) - nanopb/decode (2.30907.0) - nanopb/encode (2.30907.0) - - OktaLogger (1.2.2): - - OktaLogger/Complete (= 1.2.2) + - OktaLogger (1.3.0): + - OktaLogger/Complete (= 1.3.0) - SwiftLint - - OktaLogger/Complete (1.2.2): + - OktaLogger/Complete (1.3.0): - OktaLogger/FileLogger - OktaLogger/FirebaseCrashlytics + - OktaLogger/InstabugLogger - SwiftLint - - OktaLogger/Core (1.2.2): + - OktaLogger/Core (1.3.0): - SwiftLint - - OktaLogger/FileLogger (1.2.2): + - OktaLogger/FileLogger (1.3.0): - CocoaLumberjack/Swift (~> 3.6.0) - OktaLogger/Core - SwiftLint - - OktaLogger/FirebaseCrashlytics (1.2.2): + - OktaLogger/FirebaseCrashlytics (1.3.0): - Firebase/Crashlytics (~> 7.4.0) - OktaLogger/Core - SwiftLint + - OktaLogger/InstabugLogger (1.3.0): + - Instabug (~> 10.7.5) + - OktaLogger/Core + - SwiftLint - PromisesObjC (1.2.12) - SwiftLint (0.39.2) @@ -72,6 +78,7 @@ DEPENDENCIES: - AppCenter (~> 4.1.1) - CocoaLumberjack/Swift (~> 3.6.0) - Firebase/Crashlytics (~> 7.4.0) + - Instabug (~> 10.7.5) - OktaLogger (from `.`) SPEC REPOS: @@ -85,6 +92,7 @@ SPEC REPOS: - FirebaseInstallations - GoogleDataTransport - GoogleUtilities + - Instabug - nanopb - PromisesObjC - SwiftLint @@ -103,11 +111,12 @@ SPEC CHECKSUMS: FirebaseInstallations: a46ae59915f0931e18814164849cd0354bea24ed GoogleDataTransport: 1024b1a4dfbd7a0e92cb20d7e0a6f1fb66b449a4 GoogleUtilities: 31c5b01f978a70c6cff2afc6272b3f1921614b43 + Instabug: ec36344097cf86024029f5cf9dde858e6f9ab0ee nanopb: 59221d7f958fb711001e6a449489542d92ae113e - OktaLogger: 43fd81691a7cdb69ef29997d7f2f218a1415d63b + OktaLogger: 93607a34f00c947c5ccce88e25140bb6a6e03256 PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97 SwiftLint: 22ccbbe3b8008684be5955693bab135e0ed6a447 -PODFILE CHECKSUM: 0d62d957d380013c75e13aeb32bd0c568a713007 +PODFILE CHECKSUM: e599c7c788b36ecd9f8879e14a2c65fd02ff26b0 COCOAPODS: 1.10.1 diff --git a/README.md b/README.md index 150ad40..5d4c588 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ OktaLogger is a proxy-based logging SDK for allowing an app to log to many desti - [Console](#console-destination) - [File](#file-destination) - [Firebase Crashlytics](#firebase-crashlytics-destination) + - [App Center](#app-center-destination) + - [Instabug](#instabug-destination) - [Custom destinations](#custom-destinations) - [Log levels](#log-levels) - [Diagrams](#diagrams) @@ -133,8 +135,7 @@ This destination is using [Firebase Crashlytics SDK](https://github.com/firebase ### App Center destination Related class - -[AppCenterLogger] -(OktaLogger/AppCenterLogger/AppCenterLogger.swift). +[AppCenterLogger](OktaLogger/AppCenterLogger/AppCenterLogger.swift). This destination uses the AppCenter SDK to send events, so they can be accessed from the App Center console. The only functionality supported by this destination is sending events to the App Center dashboard. There are a few important features and restrictions in this destination: @@ -144,6 +145,28 @@ There are a few important features and restrictions in this destination: This destination is using [App Center SDK](https://github.com/microsoft/appcenter-sdk-apple) for logging implementation +### Instabug destination + +Related class - +[OktaLoggerInstabugLogger](OktaLogger/InstabugLogger/OktaLoggerInstabugLogger.swift). +This destination uses the Instabug SDK to send events, so they can be accessed from the Instabug console in bug report or improvement suggestion. +There are a few important features and restrictions in this destination: + +- Logger will not send events unless Instabug is configured [setup Instabug in iOS app](https://docs.instabug.com/docs/ios-integration). +- You can review only 1000 log records for one report. See [Instabug docs](https://docs.instabug.com/docs/ios-integration) for more details. +- For each log level OktaLogger will call appropriate Instabug log method. See the full list in the table below. + +| OktaLogger log level | Instabug log method | +| -------------------- | --------------------- | +| `all` | `IBGLog.logVerbose()` | +| `debug` | `IBGLog.logDebug()` | +| `info` | `IBGLog.logInfo()` | +| `uiEvent` | `IBGLog.logInfo()` | +| `warning` | `IBGLog.logWarn()` | +| `error` | `IBGLog.logError()` | + +This destination is using [Instabug iOS SDK](https://github.com/Instabug/Instabug-iOS) for logging implementation. + ### Custom destinations If you want to create your custom destination it is recommended to inherit it from `OktaLoggerDestinationBase` class, as this class implements some basic functionality. Hovewer, the only requirement for destinations is to conform to `OktaLoggerDestinationProtocol`.