Skip to content

Commit 4feb9c9

Browse files
jobykorahgeorgeibmGitHub Enterprise
authored andcommitted
Merge pull request #47 from instana/162932_expose_api_for_im
162932 expose api for im
2 parents 09a6402 + 7cf72f4 commit 4feb9c9

File tree

10 files changed

+150
-6
lines changed

10 files changed

+150
-6
lines changed

Changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## 1.8.1
4+
- added functionality to accept internal metadata from cross-platform agents
5+
36
## 1.8.0
47
- add to mobile feature list if `autoCaptureScreenNames` is enabled
58
- add Privacy Manifest File PrivacyInfo.xcprivacy to iOSAgent

InstanaAgent.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
1616
#
1717

1818
s.name = "InstanaAgent"
19-
s.version = "1.8.0"
19+
s.version = "1.8.1"
2020
s.summary = "Instana iOS agent."
2121

2222
# This description is used to generate tags and improve search results.

Sources/InstanaAgent/Beacons/Beacons Types/ViewChange.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ class ViewChange: Beacon {
99
var navigationItemTitle: String?
1010
var className: String?
1111

12+
// Internal Meta only to be consumed by Flutter/React agents
13+
var viewInternalCPMetaMap: [String: String]
14+
1215
init(timestamp: Instana.Types.Milliseconds = Date().millisecondsSince1970,
1316
viewName: String? = nil, accessibilityLabel: String? = nil,
1417
navigationItemTitle: String? = nil,
15-
className: String? = nil, isSwiftUI: Bool = false) {
18+
className: String? = nil, isSwiftUI: Bool = false, viewInternalCPMetaMap: [String: String] = [:]) {
19+
self.viewInternalCPMetaMap = [:]
1620
var canonicalName: String? = viewName
1721
var prefix = ""
1822
if accessibilityLabel != nil, !accessibilityLabel!.isEmpty {
@@ -32,6 +36,9 @@ class ViewChange: Beacon {
3236
canonicalName = prefix.isEmpty ? "@\(self.className!)" : prefix
3337
}
3438
}
39+
for (key, value) in viewInternalCPMetaMap {
40+
self.viewInternalCPMetaMap[key] = ViewChange.validate(viewName: value)
41+
}
3542
super.init(timestamp: timestamp, viewName: canonicalName)
3643
}
3744

Sources/InstanaAgent/Beacons/CoreBeacon/CoreBeaconFactory.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ extension CoreBeacon {
109109
if beacon.className != nil {
110110
im![internalMetaDataKeyView_className] = beacon.className!
111111
}
112+
if !beacon.viewInternalCPMetaMap.isEmpty {
113+
for (key, value) in beacon.viewInternalCPMetaMap {
114+
im![key] = value
115+
}
116+
}
112117
if im!.isEmpty {
113118
im = nil
114119
}

Sources/InstanaAgent/Configuration/Defines.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ let internalMetaDataKeyView_accbltyLabel = "view.accLabel" // accessibilityLabel
5656
let internalMetaDataKeyView_navItemTitle = "view.navItemTitle" // navigationItemTitle
5757
let internalMetaDataKeyView_className = "view.clsName" // className
5858

59+
let internalMetaFlutterKeys = ["settings.route.name", "widget.name", "child.widget.name", "child.widget.title", "go.router.path"] // keys given from flutter agent
60+
5961
///
6062
/// Mobile Features
6163
///
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
struct VersionConfig {
2-
static let agentVersion = "1.8.0"
2+
static let agentVersion = "1.8.1"
33
}

Sources/InstanaAgent/Instana.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,11 +412,35 @@ import Foundation
412412
Instana.current?.setViewInternal(name: name)
413413
}
414414

415+
/// Set the screen name and its meta details from crossplatfrom services (Flutter & React Native agents)
416+
///
417+
/// ONLY TO BE USED BY FLUTTER/REACT NATIVE AGENTS!
418+
///
419+
/// This is exposed for internal use, for the communication between the instana agents, not to be consumed by developers
420+
/// Call this method from instana cross platform agents when need to provide auto capture of screen names and its meta details
421+
/// - Parameters:
422+
/// - name: The screen name identified from cross platform agents
423+
/// - viewInternalCPMetaMap: Dictionary of keys and values of meta details from CROSS PLATFORM agents
424+
@objc
425+
public static func setViewMetaCPInternal(name: String, viewInternalCPMetaMap: [String: String] = [:]) {
426+
var isAllKeysValid = true
427+
for key in viewInternalCPMetaMap.keys {
428+
if !internalMetaFlutterKeys.contains(key) {
429+
isAllKeysValid = false
430+
break
431+
}
432+
}
433+
if isAllKeysValid {
434+
Instana.current?.setViewInternal(name: name, viewInternalCPMetaMap: viewInternalCPMetaMap)
435+
}
436+
}
437+
415438
public func setViewInternal(name: String?,
416439
accessibilityLabel: String? = nil,
417440
navigationItemTitle: String? = nil,
418441
className: String? = nil,
419-
isSwiftUI: Bool = false) {
442+
isSwiftUI: Bool = false,
443+
viewInternalCPMetaMap: [String: String] = [:]) {
420444
guard let propertyHandler = Instana.current?.session.propertyHandler else { return }
421445
let isIdentical = propertyHandler.properties.view?.isSame(name: name,
422446
accessibilityLabel: accessibilityLabel,
@@ -427,7 +451,8 @@ import Foundation
427451
accessibilityLabel: accessibilityLabel,
428452
navigationItemTitle: navigationItemTitle,
429453
className: className,
430-
isSwiftUI: isSwiftUI)
454+
isSwiftUI: isSwiftUI,
455+
viewInternalCPMetaMap: viewInternalCPMetaMap)
431456
propertyHandler.properties.view = view
432457

433458
guard view.viewName != nil else { return }

Tests/InstanaAgentTests/Beacons/Beacon Types/ViewChangeBeaconTests.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class ViewChangeBeaconTests: InstanaTestCase {
1313
let testViewName = "test view name 0"
1414
let testAcsbLabel = "test accessibilityLabel 1"
1515
let testNavItemTitle = "test navigationItemTitle 2"
16+
let testViewInternalMetaMap = ["key1": "value1", "key2": "value2"]
1617

1718
override func setUp() {
1819
super.setUp()
@@ -113,4 +114,18 @@ class ViewChangeBeaconTests: InstanaTestCase {
113114
vcAfterSwizzle.viewDidAppear(false)
114115
Thread.sleep(forTimeInterval: 1)
115116
}
117+
118+
func test_init_viewInternalMetaMap() {
119+
let vcBeacon = ViewChange(timestamp: testTimestamp, viewName: testViewName,
120+
accessibilityLabel: nil, navigationItemTitle: nil, className: nil,viewInternalCPMetaMap: testViewInternalMetaMap)
121+
XCTAssertEqual(vcBeacon.viewInternalCPMetaMap,testViewInternalMetaMap)
122+
}
123+
124+
func test_init_viewInternalMetaMap_empty() {
125+
let vcBeacon = ViewChange(timestamp: testTimestamp, viewName: testViewName,
126+
accessibilityLabel: nil, navigationItemTitle: nil, className: nil)
127+
XCTAssertEqual(vcBeacon.viewInternalCPMetaMap,[:])
128+
}
129+
130+
116131
}

Tests/InstanaAgentTests/Configuration/InstanaSystemUtilsTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class InstanaSystemUtilsTests: InstanaTestCase {
55

66
func test_AgentVersion() {
77
// Then
8-
AssertTrue(InstanaSystemUtils.agentVersion == "1.8.0")
8+
AssertTrue(InstanaSystemUtils.agentVersion == "1.8.1")
99
}
1010

1111
func test_systemVersion() {

Tests/InstanaAgentTests/InstanaTests.swift

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,4 +827,91 @@ class InstanaTests: InstanaTestCase {
827827
Instana.current = nil
828828
AssertFalse(Instana.collectionEnabled)
829829
}
830+
831+
func test_setViewMetaCPInternal_called_negative(){
832+
// Given
833+
let session = InstanaSession.mock(configuration: .mock())
834+
835+
var viewChangeBeaconCount = 0
836+
var capturedViewInternalMetaMap: [String: String]? = nil
837+
let reporter = MockReporter {
838+
if let viewChange = $0 as? ViewChange {
839+
capturedViewInternalMetaMap = viewChange.viewInternalCPMetaMap
840+
viewChangeBeaconCount += 1
841+
}
842+
}
843+
Instana.current = Instana(session: session, monitors: Monitors(session, reporter: reporter))
844+
845+
let testViewInternalMetaMap = ["key1": "value1", "key2": "value2"]
846+
// When
847+
Instana.setViewMetaCPInternal(name: "ScreenName", viewInternalCPMetaMap:testViewInternalMetaMap)
848+
849+
Instana.current?.setViewInternal(name: nil) // nil view name should not trigger ViewChange beacon
850+
Thread.sleep(forTimeInterval: 1)
851+
852+
// Then
853+
AssertEqualAndNotNil(viewChangeBeaconCount, 0)
854+
AssertEqualAndNotNil(capturedViewInternalMetaMap, nil)
855+
}
856+
857+
func test_setViewMetaCPInternal_called_positive(){
858+
// Given
859+
let session = InstanaSession.mock(configuration: .mock())
860+
861+
var viewChangeBeaconCount = 0
862+
var capturedViewInternalMetaMap: [String: String]? = nil
863+
let reporter = MockReporter {
864+
if let viewChange = $0 as? ViewChange {
865+
capturedViewInternalMetaMap = viewChange.viewInternalCPMetaMap
866+
viewChangeBeaconCount += 1
867+
}
868+
}
869+
Instana.current = Instana(session: session, monitors: Monitors(session, reporter: reporter))
870+
871+
let testViewInternalMetaMap = ["settings.route.name": "value1", "widget.name": "value2"]
872+
873+
874+
// When
875+
Instana.setViewMetaCPInternal(name: "ScreenName", viewInternalCPMetaMap:testViewInternalMetaMap)
876+
877+
Instana.current?.setViewInternal(name: nil) // nil view name should not trigger ViewChange beacon
878+
Thread.sleep(forTimeInterval: 1)
879+
880+
// Then
881+
AssertEqualAndNotNil(viewChangeBeaconCount, 1)
882+
AssertEqualAndNotNil(capturedViewInternalMetaMap, testViewInternalMetaMap)
883+
}
884+
885+
func test_setViewMetaCPInternal_called_with_max_value_length(){
886+
// Given
887+
let session = InstanaSession.mock(configuration: .mock())
888+
889+
var viewChangeBeaconCount = 0
890+
var capturedViewInternalMetaMap: [String: String]? = nil
891+
let reporter = MockReporter {
892+
if let viewChange = $0 as? ViewChange {
893+
capturedViewInternalMetaMap = viewChange.viewInternalCPMetaMap
894+
viewChangeBeaconCount += 1
895+
}
896+
}
897+
Instana.current = Instana(session: session, monitors: Monitors(session, reporter: reporter))
898+
var randomString = ""
899+
for _ in 0..<InstanaProperties.viewMaxLength+3 {
900+
let randomCharacter = Character(UnicodeScalar(UInt32.random(in: 65...90)) ?? "A") // A-Z
901+
randomString.append(randomCharacter)
902+
}
903+
904+
let testViewInternalMetaMap = ["settings.route.name": randomString, "widget.name": "value2"]
905+
906+
907+
// When
908+
Instana.setViewMetaCPInternal(name: "ScreenName", viewInternalCPMetaMap:testViewInternalMetaMap)
909+
910+
Instana.current?.setViewInternal(name: nil) // nil view name should not trigger ViewChange beacon
911+
Thread.sleep(forTimeInterval: 1)
912+
913+
// Then
914+
AssertEqualAndNotNil(viewChangeBeaconCount, 1)
915+
AssertEqualAndNotNil(capturedViewInternalMetaMap?["settings.route.name"]?.count, InstanaProperties.viewMaxLength)
916+
}
830917
}

0 commit comments

Comments
 (0)