Skip to content

Commit

Permalink
Merge pull request #47 from instana/162932_expose_api_for_im
Browse files Browse the repository at this point in the history
162932 expose api for im
  • Loading branch information
jobykorahgeorgeibm authored and GitHub Enterprise committed May 22, 2024
2 parents 09a6402 + 7cf72f4 commit 4feb9c9
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 6 deletions.
3 changes: 3 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 1.8.1
- added functionality to accept internal metadata from cross-platform agents

## 1.8.0
- add to mobile feature list if `autoCaptureScreenNames` is enabled
- add Privacy Manifest File PrivacyInfo.xcprivacy to iOSAgent
Expand Down
2 changes: 1 addition & 1 deletion InstanaAgent.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pod::Spec.new do |s|
#

s.name = "InstanaAgent"
s.version = "1.8.0"
s.version = "1.8.1"
s.summary = "Instana iOS agent."

# This description is used to generate tags and improve search results.
Expand Down
9 changes: 8 additions & 1 deletion Sources/InstanaAgent/Beacons/Beacons Types/ViewChange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ class ViewChange: Beacon {
var navigationItemTitle: String?
var className: String?

// Internal Meta only to be consumed by Flutter/React agents
var viewInternalCPMetaMap: [String: String]

init(timestamp: Instana.Types.Milliseconds = Date().millisecondsSince1970,
viewName: String? = nil, accessibilityLabel: String? = nil,
navigationItemTitle: String? = nil,
className: String? = nil, isSwiftUI: Bool = false) {
className: String? = nil, isSwiftUI: Bool = false, viewInternalCPMetaMap: [String: String] = [:]) {
self.viewInternalCPMetaMap = [:]
var canonicalName: String? = viewName
var prefix = ""
if accessibilityLabel != nil, !accessibilityLabel!.isEmpty {
Expand All @@ -32,6 +36,9 @@ class ViewChange: Beacon {
canonicalName = prefix.isEmpty ? "@\(self.className!)" : prefix
}
}
for (key, value) in viewInternalCPMetaMap {
self.viewInternalCPMetaMap[key] = ViewChange.validate(viewName: value)
}
super.init(timestamp: timestamp, viewName: canonicalName)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ extension CoreBeacon {
if beacon.className != nil {
im![internalMetaDataKeyView_className] = beacon.className!
}
if !beacon.viewInternalCPMetaMap.isEmpty {
for (key, value) in beacon.viewInternalCPMetaMap {
im![key] = value
}
}
if im!.isEmpty {
im = nil
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/InstanaAgent/Configuration/Defines.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ let internalMetaDataKeyView_accbltyLabel = "view.accLabel" // accessibilityLabel
let internalMetaDataKeyView_navItemTitle = "view.navItemTitle" // navigationItemTitle
let internalMetaDataKeyView_className = "view.clsName" // className

let internalMetaFlutterKeys = ["settings.route.name", "widget.name", "child.widget.name", "child.widget.title", "go.router.path"] // keys given from flutter agent

///
/// Mobile Features
///
Expand Down
2 changes: 1 addition & 1 deletion Sources/InstanaAgent/Configuration/VersionConfig.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
struct VersionConfig {
static let agentVersion = "1.8.0"
static let agentVersion = "1.8.1"
}
29 changes: 27 additions & 2 deletions Sources/InstanaAgent/Instana.swift
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,35 @@ import Foundation
Instana.current?.setViewInternal(name: name)
}

/// Set the screen name and its meta details from crossplatfrom services (Flutter & React Native agents)
///
/// ONLY TO BE USED BY FLUTTER/REACT NATIVE AGENTS!
///
/// This is exposed for internal use, for the communication between the instana agents, not to be consumed by developers
/// Call this method from instana cross platform agents when need to provide auto capture of screen names and its meta details
/// - Parameters:
/// - name: The screen name identified from cross platform agents
/// - viewInternalCPMetaMap: Dictionary of keys and values of meta details from CROSS PLATFORM agents
@objc
public static func setViewMetaCPInternal(name: String, viewInternalCPMetaMap: [String: String] = [:]) {
var isAllKeysValid = true
for key in viewInternalCPMetaMap.keys {
if !internalMetaFlutterKeys.contains(key) {
isAllKeysValid = false
break
}
}
if isAllKeysValid {
Instana.current?.setViewInternal(name: name, viewInternalCPMetaMap: viewInternalCPMetaMap)
}
}

public func setViewInternal(name: String?,
accessibilityLabel: String? = nil,
navigationItemTitle: String? = nil,
className: String? = nil,
isSwiftUI: Bool = false) {
isSwiftUI: Bool = false,
viewInternalCPMetaMap: [String: String] = [:]) {
guard let propertyHandler = Instana.current?.session.propertyHandler else { return }
let isIdentical = propertyHandler.properties.view?.isSame(name: name,
accessibilityLabel: accessibilityLabel,
Expand All @@ -427,7 +451,8 @@ import Foundation
accessibilityLabel: accessibilityLabel,
navigationItemTitle: navigationItemTitle,
className: className,
isSwiftUI: isSwiftUI)
isSwiftUI: isSwiftUI,
viewInternalCPMetaMap: viewInternalCPMetaMap)
propertyHandler.properties.view = view

guard view.viewName != nil else { return }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ViewChangeBeaconTests: InstanaTestCase {
let testViewName = "test view name 0"
let testAcsbLabel = "test accessibilityLabel 1"
let testNavItemTitle = "test navigationItemTitle 2"
let testViewInternalMetaMap = ["key1": "value1", "key2": "value2"]

override func setUp() {
super.setUp()
Expand Down Expand Up @@ -113,4 +114,18 @@ class ViewChangeBeaconTests: InstanaTestCase {
vcAfterSwizzle.viewDidAppear(false)
Thread.sleep(forTimeInterval: 1)
}

func test_init_viewInternalMetaMap() {
let vcBeacon = ViewChange(timestamp: testTimestamp, viewName: testViewName,
accessibilityLabel: nil, navigationItemTitle: nil, className: nil,viewInternalCPMetaMap: testViewInternalMetaMap)
XCTAssertEqual(vcBeacon.viewInternalCPMetaMap,testViewInternalMetaMap)
}

func test_init_viewInternalMetaMap_empty() {
let vcBeacon = ViewChange(timestamp: testTimestamp, viewName: testViewName,
accessibilityLabel: nil, navigationItemTitle: nil, className: nil)
XCTAssertEqual(vcBeacon.viewInternalCPMetaMap,[:])
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class InstanaSystemUtilsTests: InstanaTestCase {

func test_AgentVersion() {
// Then
AssertTrue(InstanaSystemUtils.agentVersion == "1.8.0")
AssertTrue(InstanaSystemUtils.agentVersion == "1.8.1")
}

func test_systemVersion() {
Expand Down
87 changes: 87 additions & 0 deletions Tests/InstanaAgentTests/InstanaTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -827,4 +827,91 @@ class InstanaTests: InstanaTestCase {
Instana.current = nil
AssertFalse(Instana.collectionEnabled)
}

func test_setViewMetaCPInternal_called_negative(){
// Given
let session = InstanaSession.mock(configuration: .mock())

var viewChangeBeaconCount = 0
var capturedViewInternalMetaMap: [String: String]? = nil
let reporter = MockReporter {
if let viewChange = $0 as? ViewChange {
capturedViewInternalMetaMap = viewChange.viewInternalCPMetaMap
viewChangeBeaconCount += 1
}
}
Instana.current = Instana(session: session, monitors: Monitors(session, reporter: reporter))

let testViewInternalMetaMap = ["key1": "value1", "key2": "value2"]
// When
Instana.setViewMetaCPInternal(name: "ScreenName", viewInternalCPMetaMap:testViewInternalMetaMap)

Instana.current?.setViewInternal(name: nil) // nil view name should not trigger ViewChange beacon
Thread.sleep(forTimeInterval: 1)

// Then
AssertEqualAndNotNil(viewChangeBeaconCount, 0)
AssertEqualAndNotNil(capturedViewInternalMetaMap, nil)
}

func test_setViewMetaCPInternal_called_positive(){
// Given
let session = InstanaSession.mock(configuration: .mock())

var viewChangeBeaconCount = 0
var capturedViewInternalMetaMap: [String: String]? = nil
let reporter = MockReporter {
if let viewChange = $0 as? ViewChange {
capturedViewInternalMetaMap = viewChange.viewInternalCPMetaMap
viewChangeBeaconCount += 1
}
}
Instana.current = Instana(session: session, monitors: Monitors(session, reporter: reporter))

let testViewInternalMetaMap = ["settings.route.name": "value1", "widget.name": "value2"]


// When
Instana.setViewMetaCPInternal(name: "ScreenName", viewInternalCPMetaMap:testViewInternalMetaMap)

Instana.current?.setViewInternal(name: nil) // nil view name should not trigger ViewChange beacon
Thread.sleep(forTimeInterval: 1)

// Then
AssertEqualAndNotNil(viewChangeBeaconCount, 1)
AssertEqualAndNotNil(capturedViewInternalMetaMap, testViewInternalMetaMap)
}

func test_setViewMetaCPInternal_called_with_max_value_length(){
// Given
let session = InstanaSession.mock(configuration: .mock())

var viewChangeBeaconCount = 0
var capturedViewInternalMetaMap: [String: String]? = nil
let reporter = MockReporter {
if let viewChange = $0 as? ViewChange {
capturedViewInternalMetaMap = viewChange.viewInternalCPMetaMap
viewChangeBeaconCount += 1
}
}
Instana.current = Instana(session: session, monitors: Monitors(session, reporter: reporter))
var randomString = ""
for _ in 0..<InstanaProperties.viewMaxLength+3 {
let randomCharacter = Character(UnicodeScalar(UInt32.random(in: 65...90)) ?? "A") // A-Z
randomString.append(randomCharacter)
}

let testViewInternalMetaMap = ["settings.route.name": randomString, "widget.name": "value2"]


// When
Instana.setViewMetaCPInternal(name: "ScreenName", viewInternalCPMetaMap:testViewInternalMetaMap)

Instana.current?.setViewInternal(name: nil) // nil view name should not trigger ViewChange beacon
Thread.sleep(forTimeInterval: 1)

// Then
AssertEqualAndNotNil(viewChangeBeaconCount, 1)
AssertEqualAndNotNil(capturedViewInternalMetaMap?["settings.route.name"]?.count, InstanaProperties.viewMaxLength)
}
}

0 comments on commit 4feb9c9

Please sign in to comment.