create core events for actions and clientparameters tracking
This commit is contained in:
parent
dcbaa316ac
commit
068714a001
@ -39,6 +39,8 @@
|
||||
0AEBB84625FA75C000EA80EE /* ActionOpenSMSModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AEBB84525FA75C000EA80EE /* ActionOpenSMSModel.swift */; };
|
||||
0AFF597A23FC6E60005C24E8 /* ActionShareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF597923FC6E60005C24E8 /* ActionShareModel.swift */; };
|
||||
1DAD0FFE26AAB40000216E83 /* ActionRunJavaScriptModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DAD0FFD26AAB3FF00216E83 /* ActionRunJavaScriptModel.swift */; };
|
||||
2723337B28BD534D004EAEE0 /* MVMCoreEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2723337A28BD534D004EAEE0 /* MVMCoreEvent.swift */; };
|
||||
2723337D28BD53C2004EAEE0 /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2723337C28BD53C2004EAEE0 /* Date+Extension.swift */; };
|
||||
30349BF11FCCA78A00546A1E /* MVMCoreSessionTimeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 30349BEF1FCCA78A00546A1E /* MVMCoreSessionTimeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
30349BF21FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 30349BF01FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m */; };
|
||||
881D26931FCC9D180079C521 /* MVMCoreErrorObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 881D268F1FCC9D180079C521 /* MVMCoreErrorObject.m */; };
|
||||
@ -196,6 +198,8 @@
|
||||
0AEBB84525FA75C000EA80EE /* ActionOpenSMSModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionOpenSMSModel.swift; sourceTree = "<group>"; };
|
||||
0AFF597923FC6E60005C24E8 /* ActionShareModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionShareModel.swift; sourceTree = "<group>"; };
|
||||
1DAD0FFD26AAB3FF00216E83 /* ActionRunJavaScriptModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionRunJavaScriptModel.swift; sourceTree = "<group>"; };
|
||||
2723337A28BD534D004EAEE0 /* MVMCoreEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreEvent.swift; sourceTree = "<group>"; };
|
||||
2723337C28BD53C2004EAEE0 /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; };
|
||||
30349BEF1FCCA78A00546A1E /* MVMCoreSessionTimeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreSessionTimeHandler.h; sourceTree = "<group>"; };
|
||||
30349BF01FCCA78A00546A1E /* MVMCoreSessionTimeHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreSessionTimeHandler.m; sourceTree = "<group>"; };
|
||||
881D268F1FCC9D180079C521 /* MVMCoreErrorObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreErrorObject.m; sourceTree = "<group>"; };
|
||||
@ -435,6 +439,7 @@
|
||||
8876D5E51FB50AB000EB2E3D /* UIFont+MFSpacing.m */,
|
||||
8876D5E61FB50AB000EB2E3D /* UILabel+MFCustom.h */,
|
||||
8876D5E71FB50AB000EB2E3D /* UILabel+MFCustom.m */,
|
||||
2723337C28BD53C2004EAEE0 /* Date+Extension.swift */,
|
||||
);
|
||||
path = Categories;
|
||||
sourceTree = "<group>";
|
||||
@ -687,6 +692,7 @@
|
||||
AFEEE81C1FCDF3CA00B5EDD0 /* MVMCoreLoggingHandler.h */,
|
||||
AFEEE81D1FCDF3CA00B5EDD0 /* MVMCoreLoggingHandler.m */,
|
||||
D288D5F426C6EFE000A5C365 /* MVMCoreLoggingHandler+Extension.swift */,
|
||||
2723337A28BD534D004EAEE0 /* MVMCoreEvent.swift */,
|
||||
);
|
||||
path = OtherHandlers;
|
||||
sourceTree = "<group>";
|
||||
@ -912,6 +918,7 @@
|
||||
AFBB96901FBA3A9A0008D868 /* MVMCoreNavigationObject.m in Sources */,
|
||||
1DAD0FFE26AAB40000216E83 /* ActionRunJavaScriptModel.swift in Sources */,
|
||||
946EE1AB237B5C940036751F /* Decoder.swift in Sources */,
|
||||
2723337D28BD53C2004EAEE0 /* Date+Extension.swift in Sources */,
|
||||
AF70699A287DD02400077CF6 /* ActionContactHandler.swift in Sources */,
|
||||
AF69D4F3286E9DCE00BC6862 /* ActionActionsHandler.swift in Sources */,
|
||||
946EE1BC237B691A0036751F /* ActionOpenPageModel.swift in Sources */,
|
||||
@ -950,6 +957,7 @@
|
||||
01F2A05223A8325100D954D8 /* ModelMapping.swift in Sources */,
|
||||
8876D5F51FB50AB000EB2E3D /* UILabel+MFCustom.m in Sources */,
|
||||
AFBB96B31FBA3B590008D868 /* MVMCoreGetterUtility.m in Sources */,
|
||||
2723337B28BD534D004EAEE0 /* MVMCoreEvent.swift in Sources */,
|
||||
AF43A7071FC4D7A2008E9347 /* MVMCoreObject.m in Sources */,
|
||||
94C014D924212360005811A9 /* ActionSettingModel.swift in Sources */,
|
||||
D2DEDCB723C63F3B00C44CC4 /* Clamping.swift in Sources */,
|
||||
|
||||
@ -84,7 +84,7 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
|
||||
/// Handle an action with the given model.
|
||||
open func handleAction(with model: ActionModelProtocol, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) async throws {
|
||||
try Task.checkCancellation()
|
||||
var additionalData = MVMCoreActionHandler.setUUID(additionalData: additionalData)
|
||||
var (additionalData, uuid) = MVMCoreActionHandler.setUUID(additionalData: additionalData)
|
||||
MVMCoreActionHandler.log(string: "Begin Action: \(model.actionType)", additionalData: additionalData)
|
||||
defer {
|
||||
MVMCoreActionHandler.log(string: "End Action: \(model.actionType)", additionalData: additionalData)
|
||||
@ -97,17 +97,20 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
|
||||
do {
|
||||
let handlerType = try ModelRegistry.getHandler(model) as! MVMCoreActionHandlerProtocol.Type
|
||||
let handler = handlerType.init()
|
||||
MVMCoreLoggingHandler.shared()?.logCoreEvent(.actionInvoked(name: model.actionType, pageType: pageType(from: delegateObject), uuid: uuid))
|
||||
if let handler = handler as? MVMCoreJSONActionHandlerProtocol {
|
||||
// Needed until we can remove legacy delegate functions.
|
||||
try await handler.performAction(with: json, model: model, delegateObject: delegateObject, additionalData: additionalData)
|
||||
} else {
|
||||
try await handler.execute(with: model, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
MVMCoreLoggingHandler.shared()?.logCoreEvent(.actionComplete(name: model.actionType, pageType: pageType(from: delegateObject), uuid: uuid))
|
||||
} catch ModelRegistry.Error.handlerNotMapped {
|
||||
try Task.checkCancellation()
|
||||
// Allows custom handling if there no handler for the action.
|
||||
guard try await handleUnregisteredAction(with: model, json: json, additionalData: additionalData, delegateObject: delegateObject) else {
|
||||
MVMCoreActionHandler.log(string: "Failed Action Unknown", additionalData: additionalData)
|
||||
MVMCoreLoggingHandler.shared()?.logCoreEvent(.actionNotFound(name: model.actionType , pageType: pageType(from: delegateObject)))
|
||||
throw ActionError.unknownAction(type: model.actionType)
|
||||
}
|
||||
} catch {
|
||||
@ -132,9 +135,10 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
|
||||
|
||||
// MARK: - Legacy Holdovers
|
||||
|
||||
static public func setUUID(additionalData: [AnyHashable: Any]?, force: Bool = false) -> [AnyHashable: Any] {
|
||||
if !force && getUUID(additionalData: additionalData) != nil { return additionalData! }
|
||||
return additionalData.dictionaryAdding(key: "Action-UUID", value: UUID().uuidString)
|
||||
static public func setUUID(additionalData: [AnyHashable: Any]?, force: Bool = false) -> ([AnyHashable: Any], String) {
|
||||
if !force, let uuid = getUUID(additionalData: additionalData) { return (additionalData!, uuid) }
|
||||
let newUUID = UUID().uuidString
|
||||
return (additionalData.dictionaryAdding(key: "Action-UUID", value: newUUID), newUUID)
|
||||
}
|
||||
|
||||
static public func getUUID(additionalData: [AnyHashable: Any]?) -> String? {
|
||||
@ -145,6 +149,17 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
|
||||
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "ActionHandler: UUID: \(String(describing: getUUID(additionalData: additionalData))), \(string)")
|
||||
}
|
||||
|
||||
fileprivate func logActionError(_ error: Error, _ actionType: String?, _ additionalData: [AnyHashable: Any]?, _ delegateObject: DelegateObject?) {
|
||||
MVMCoreActionHandler.log(string: "Failed Action: Error \(error)", additionalData: additionalData)
|
||||
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: MVMCoreActionHandler.getErrorLocation(with: delegateObject?.actionDelegate, actionType: actionType ?? "noAction")) {
|
||||
defaultHandleActionError(errorObject, additionalData: additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func pageType(from delegateObject: DelegateObject?) -> String {
|
||||
return (delegateObject?.loadDelegate as? MVMCoreViewControllerProtocol)?.pageType ?? "unknown"
|
||||
}
|
||||
|
||||
/// Legacy handle action with json.
|
||||
@objc(handleActionWithDictionary:additionalData:delegateObject:)
|
||||
open func handleAction(with json: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
@ -159,16 +174,16 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
|
||||
} catch {
|
||||
let actionType = json?.optionalStringForKey(KeyActionType)
|
||||
switch error {
|
||||
case ModelRegistry.Error.decoderError, is DecodingError:
|
||||
MVMCoreLoggingHandler.shared()?.logCoreEvent(.actionFailedToDecode(pageType: pageType(from: delegateObject), error: error))
|
||||
case ModelRegistry.Error.decoderErrorModelNotMapped:
|
||||
// If the model is not mapped, give the legacy classes a chance to handle it.
|
||||
if try await handleUnregisteredAction(with: nil, json: json!, additionalData: additionalData, delegateObject: delegateObject) == false {
|
||||
fallthrough
|
||||
MVMCoreLoggingHandler.shared()?.logCoreEvent(.actionNotFound(name: actionType ?? "noAction", pageType: pageType(from: delegateObject)))
|
||||
logActionError(error, actionType, additionalData, delegateObject)
|
||||
}
|
||||
default:
|
||||
MVMCoreActionHandler.log(string: "Failed Action: Error \(error)", additionalData: additionalData)
|
||||
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: MVMCoreActionHandler.getErrorLocation(with: delegateObject?.actionDelegate, actionType: actionType ?? "noAction")) {
|
||||
defaultHandleActionError(errorObject, additionalData: additionalData)
|
||||
}
|
||||
logActionError(error, actionType, additionalData, delegateObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,8 +192,8 @@ public protocol MVMCoreJSONActionHandlerProtocol: MVMCoreActionHandlerProtocol {
|
||||
/// Bridges the legacy json using functions and the new model using functions.
|
||||
open func handleAction(with model: ActionModelProtocol, json: [AnyHashable: Any], additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) async throws {
|
||||
try Task.checkCancellation()
|
||||
var additionalData = additionalData.dictionaryAdding(key: jsonKey, value: json)
|
||||
additionalData = MVMCoreActionHandler.setUUID(additionalData: additionalData, force: true)
|
||||
let additionalDataWithJSON = additionalData.dictionaryAdding(key: jsonKey, value: json)
|
||||
let (additionalData, _) = MVMCoreActionHandler.setUUID(additionalData: additionalDataWithJSON, force: true)
|
||||
MVMCoreActionHandler.log(string: "JSON \(json)", additionalData: additionalData)
|
||||
if let closure = (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction {
|
||||
// Allow newer delegates to handle calls from legacy functions
|
||||
|
||||
16
MVMCore/MVMCore/Categories/Date+Extension.swift
Normal file
16
MVMCore/MVMCore/Categories/Date+Extension.swift
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// Date+Extension.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Kyle on 8/29/22.
|
||||
// Copyright © 2022 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Date {
|
||||
|
||||
static func unixMillisecondsNow() -> Int64 {
|
||||
return Int64(Self().timeIntervalSince1970 * 1000)
|
||||
}
|
||||
}
|
||||
126
MVMCore/MVMCore/OtherHandlers/MVMCoreEvent.swift
Normal file
126
MVMCore/MVMCore/OtherHandlers/MVMCoreEvent.swift
Normal file
@ -0,0 +1,126 @@
|
||||
//
|
||||
// MVMCoreEvent.swift
|
||||
// MVMCore
|
||||
//
|
||||
// https://oneconfluence.verizon.com/display/MFD/NewRelic+Client+Event+Logging
|
||||
//
|
||||
// Created by Kyle on 8/29/22.
|
||||
// Copyright © 2022 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// A list of possible events from the app.
|
||||
public enum MVMCoreEvent {
|
||||
|
||||
// ----------------------------
|
||||
// MARK: Action Events
|
||||
// ----------------------------
|
||||
|
||||
/// Failed to decode the action payload.
|
||||
case actionFailedToDecode(
|
||||
pageType: String,
|
||||
error: Error?
|
||||
)
|
||||
|
||||
/// Could not find the action specified..
|
||||
case actionNotFound(
|
||||
name: String,
|
||||
pageType: String
|
||||
)
|
||||
|
||||
/// The webview bridge action handler was invoked and is in progress.
|
||||
case actionInvoked(
|
||||
name: String,
|
||||
pageType: String,
|
||||
uuid: String
|
||||
)
|
||||
|
||||
/// The action failed..
|
||||
case actionFailed(
|
||||
name: String,
|
||||
pageType: String,
|
||||
uuid: String
|
||||
)
|
||||
|
||||
/// The action is completed.
|
||||
case actionComplete(
|
||||
name: String,
|
||||
pageType: String,
|
||||
uuid: String
|
||||
)
|
||||
|
||||
// ----------------------------
|
||||
// MARK: ClientParameter Events
|
||||
// ----------------------------
|
||||
|
||||
/// Could not find the client parameter specified.
|
||||
case clientParameterNotFound(
|
||||
name: String,
|
||||
pageType: String
|
||||
)
|
||||
|
||||
/// The client perameter handler was invoked and is in progress.
|
||||
case clientParameterFetching(
|
||||
name: String,
|
||||
pageType: String,
|
||||
uuid: String
|
||||
)
|
||||
|
||||
/// The client perameter handler timed out and is returning a default value.
|
||||
case clientParameterTimeout(
|
||||
name: String,
|
||||
pageType: String,
|
||||
uuid: String
|
||||
)
|
||||
|
||||
/// The client paramter fetch completed.
|
||||
case clientParameterComplete(
|
||||
name: String,
|
||||
pageType: String,
|
||||
uuid: String
|
||||
)
|
||||
|
||||
public enum EventType: String {
|
||||
case action
|
||||
case clientParameter
|
||||
|
||||
public var notification: Notification.Name {
|
||||
return Notification.Name(rawValue: rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var type: EventType {
|
||||
switch self {
|
||||
case .actionFailedToDecode: return .action
|
||||
case .actionNotFound: return .action
|
||||
case .actionInvoked: return .action
|
||||
case .actionFailed: return .action
|
||||
case .actionComplete: return .action
|
||||
case .clientParameterNotFound: return .clientParameter
|
||||
case .clientParameterFetching: return .clientParameter
|
||||
case .clientParameterTimeout: return .clientParameter
|
||||
case .clientParameterComplete: return .clientParameter
|
||||
}
|
||||
}
|
||||
|
||||
public var name: String {
|
||||
let name = String(describing: self)
|
||||
if let attribIndex = name.firstIndex(of: "(") {
|
||||
return String(name[..<attribIndex])
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
public var notification: Notification.Name {
|
||||
return Notification.Name(rawValue: type.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
extension MVMCoreLoggingHandler {
|
||||
|
||||
func logCoreEvent(_ event: MVMCoreEvent, at timestamp: Int64 = Date.unixMillisecondsNow()) {
|
||||
recordEvent(event.type.rawValue, attributes: ["timestamp": timestamp, "event": event])
|
||||
}
|
||||
|
||||
}
|
||||
@ -25,6 +25,7 @@
|
||||
+ (void)logWithDelegateWithObject:(nullable id)object withName:(nullable NSString *)name withExtraInfo:(nullable NSDictionary *)extra;
|
||||
+ (void)logWithDelegateLoadFinished:(nullable MVMCoreLoadObject *)loadObject loadedViewController:(nullable UIViewController <MVMCoreViewControllerProtocol> *)loadedViewController error:(nullable MVMCoreErrorObject *)error;
|
||||
+ (void)logAlertForAlertController:(nullable MVMCoreAlertController *)alertController;
|
||||
- (void)recordEvent:(nonnull NSString *)name attributes:(nullable NSDictionary<NSString *, id> *)attributes;
|
||||
|
||||
#pragma mark MVMCoreLoggingDelegateProtocol
|
||||
- (void)handleDebugMessage:(nullable NSString *)message;
|
||||
|
||||
@ -51,6 +51,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)recordEvent:(nonnull NSString *)name attributes:(nullable NSDictionary<NSString *, id> *)attributes {}
|
||||
|
||||
#pragma mark - logging delegate
|
||||
|
||||
- (void)handleDebugMessage:(nullable NSString *)message {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user