Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ExampleApp/ExampleApp/ExampleAppApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct ExampleAppApp: App {
case .manualInstrumentation:
InstrumentationView()
case .automaticInstrumentation:
NetworkRequestView()
AutomaticInstrumentationView()
case .evaluation:
FeatureFlagView()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import SwiftUI

struct AutomaticInstrumentationView: View {
var body: some View {
VStack {
NetworkRequestView()
HelloWorldView()
}
}
}

#Preview {
AutomaticInstrumentationView()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import SwiftUI
import ObservabilitySwiftUIExtensions

struct AChildView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Child A View")
.padding()
Text(count.description)
.bold()
Button {
count = count + 1
} label: {
Text("Increment")
.bold()
}
.tint(.yellow)
.buttonStyle(.borderedProminent)
}
.padding()
.background {
Color.red
}
}
}

struct HelloWorldView: View {
@State private var count = 0
var body: some View {
VStack {
Text(count.description)
.bold()
Button {
count = count + 1
} label: {
Text("Increment")
}
AChildView()
}
.logViewName(
"HelloWorldView",
attributes: [
"view": .string("vstack")
]
)
.onAppear {
print("PRINT FROM ONAPPEAR")
}
}
}

#Preview {
HelloWorldView()
}
15 changes: 14 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ let package = Package(
products: [
.library(
name: "LaunchDarklyObservability",
targets: ["LaunchDarklyObservability"]),
targets: [
"LaunchDarklyObservability",
"ObservabilitySwiftUIExtensions"
]
),
],
dependencies: [
.package(url: "https://github.com/open-telemetry/opentelemetry-swift", exact: "2.0.0"),
Expand Down Expand Up @@ -111,6 +115,15 @@ let package = Package(
.product(name: "OpenTelemetrySdk", package: "opentelemetry-swift"),
.product(name: "OpenTelemetryApi", package: "opentelemetry-swift"),
]
),
.target(
name: "ObservabilitySwiftUIExtensions",
dependencies: [
"LaunchDarklyObservability",
.product(name: "LaunchDarkly", package: "ios-client-sdk"),
.product(name: "OpenTelemetrySdk", package: "opentelemetry-swift"),
.product(name: "OpenTelemetryApi", package: "opentelemetry-swift"),
]
)
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Foundation
import os
import SwiftUI

import OpenTelemetryApi

import LaunchDarklyObservability

public struct ViewNameViewModifier: ViewModifier {
public let viewName: String
public let attributes: [String: AttributeValue]?

public init(viewName: String, attributes: [String: AttributeValue]? = nil) {
self.viewName = viewName
self.attributes = attributes
}

public func body(content: Content) -> some View {
content
.onDisappear {
let logAttributes = self.attributes ?? [String: AttributeValue]()
LDObserve.shared.recordLog(
message: "on Disappear \(self.viewName)",
severity: .info,
attributes: [
"screen.name": .string(self.viewName),
].merging(logAttributes) { _, inbound in inbound }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Screen Name Mismatch in View Modifier

The onAppear and onDisappear blocks in ViewNameViewModifier use a merging strategy that allows user-provided attributes to override the screen.name attribute. This can lead to the logged screen name not matching the viewName parameter, potentially causing confusion.

Fix in Cursor Fix in Web

)
}
.onAppear {
let logAttributes = self.attributes ?? [String: AttributeValue]()
LDObserve.shared.recordLog(
message: "on Appear \(self.viewName)",
severity: .info,
attributes: [
"screen.name": .string(self.viewName),
].merging(logAttributes) { _, inbound in inbound }
)
}
}
}


extension View {
public func logViewName(_ viewName: String, attributes: [String: AttributeValue]? = nil) -> some View {
modifier(ViewNameViewModifier(viewName: viewName, attributes: attributes))
}
}