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
12 changes: 6 additions & 6 deletions .github/workflows/BuildAndTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ on: [push, pull_request, workflow_dispatch]

jobs:
macOS:
runs-on: macOS-13
runs-on: macOS-latest
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 15.1
xcode-version: latest-stable
- name: Build and Test for macOS
run: swift test --enable-code-coverage
- name: Upload Code coverage
Expand All @@ -19,25 +19,25 @@ jobs:
xcrun llvm-cov export -ignore-filename-regex="pb\.swift|grpc\.swift" -format="lcov" .build/debug/middleware-iosPackageTests.xctest/Contents/MacOS/middleware-iosPackageTests -instr-profile .build/debug/codecov/default.profdata > .build/debug/codecov/coverage_report.lcov
./codecov -f .build/debug/codecov/coverage_report.lcov
iOS:
runs-on: macOS-13
runs-on: macOS-latest
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 15.1
xcode-version: latest-stable
- name: Install Homebrew kegs
run: make setup-brew
- name: Build for iOS
run: make build-for-testing-ios
- name: Test for iOS
run: make test-without-building-ios
tvOS:
runs-on: macOS-13
runs-on: macOS-latest
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 15.1
xcode-version:
- name: Install Homebrew kegs
run: make setup-brew
- name: Build for tvOS
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/Release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ on:

jobs:
release:
runs-on: macOS-13
runs-on: macOS-latest
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 15.1
xcode-version: latest-stable
- name: Install Homebrew kegs
run: make setup-brew
- name: Build for iOS
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PROJECT_NAME = "middleware-ios"

XCODEBUILD_OPTIONS_IOS = \
-configuration Debug \
-destination platform='iOS Simulator,name=iPhone 14,OS=latest' \
-destination platform='iOS Simulator,name=iPhone 16,OS=latest' \
-scheme $(PROJECT_NAME) \
-workspace .

Expand All @@ -14,7 +14,7 @@ XCODEBUILD_OPTIONS_TVOS = \

XCODEBUILD_OPTIONS_WATCHOS = \
-configuration Debug \
-destination platform='watchOS Simulator,name=Apple Watch Series 8 (45mm),OS=latest' \
-destination platform='watchOS Simulator,name=Apple Watch Series 10 (46mm),OS=latest' \
-scheme $(PROJECT_NAME) \
-workspace .

Expand All @@ -32,7 +32,7 @@ build-tvos:

.PHONY: build-watchos
build-watchos:
set -o pipefail && xcodebuild $(XCODEBUILD_OPTIONS_IOS) build | xcbeautify
set -o pipefail && xcodebuild $(XCODEBUILD_OPTIONS_WATCHOS) build | xcbeautify

.PHONY: build-for-testing-ios
build-for-testing-ios:
Expand Down
2 changes: 1 addition & 1 deletion MiddlewareRum.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pod::Spec.new do |spec|
#

spec.name = "MiddlewareRum"
spec.version = "1.0.5"
spec.version = "1.0.6"
spec.swift_version = "5.9"
spec.summary = "Middleware iOS / MacOS / tvOS real user monitoring SDK"

Expand Down
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ let package = Package(
targets: ["MiddlewareRum"]),
],
dependencies: [
.package(url:"https://github.com/microsoft/plcrashreporter", from: "1.8.0"),
.package(url: "https://github.com/microsoft/plcrashreporter", from: "1.8.0"),
.package(url: "https://github.com/devicekit/DeviceKit.git", from: "5.1.0"),
.package(url: "https://github.com/tsolomko/SWCompression.git", .upToNextMajor(from: "4.8.5")),
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.27.0")
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.27.0"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
Expand All @@ -39,7 +39,7 @@ let package = Package(
name: "MiddlewareRumTests",
dependencies: [
"MiddlewareRum",
.product(name: "CrashReporter", package: "PLCrashReporter"),
.product(name: "CrashReporter", package: "PLCrashReporter")
]),
]
)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
### Add the following line in `Package.swift` in `dependencies`

```swift
.package(url: "https://github.com/middleware-labs/middleware-ios", from: "1.0.5"),
.package(url: "https://github.com/middleware-labs/middleware-ios", from: "1.0.6"),
```

## Using Cocoapods

```ruby
pod "MiddlewareRum", "~> 1.0.5"
pod "MiddlewareRum", "~> 1.0.6"
```

## Initialization of Middleware iOS sdk
Expand Down
33 changes: 19 additions & 14 deletions Sources/MiddlewareRum/CrashReportingInstrumentation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,44 +90,49 @@ class CrashReportingInstrumentation {
}

let now = Date()
let span = tracer().spanBuilder(spanName: exceptionType ?? "exception").setStartTime(time: now).startSpan()

let span = tracer().spanBuilder(spanName: exceptionType!).setStartTime(time: now).startSpan()
span.setAttribute(key: MiddlewareConstants.Attributes.COMPONENT, value: "crash")
span.setAttribute(key: MiddlewareConstants.Attributes.EVENT_TYPE, value: "error")

if(report.customData != nil ) {
let customData = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSDictionary.self, from: report.customData) as? [String: String]
if(customData != nil) {
span.setAttribute(key: "crash.rumSessionId", value: customData!["sessionId"]!)
span.setAttribute(key: "crash.batteryLevel", value: customData!["batteryLevel"]!)
span.setAttribute(key: "crash.freeDiskSpace", value: customData!["freeDiskSpace"]!)
span.setAttribute(key: "crash.freeMemory", value: customData!["freeMemory"]!)
span.setAttribute(key: MiddlewareConstants.Attributes.CRASH_SESSION_ID, value: customData!["sessionId"]!)
span.setAttribute(key: MiddlewareConstants.Attributes.CRASH_BATTERY_LEVEL, value: customData!["batteryLevel"]!)
span.setAttribute(key: MiddlewareConstants.Attributes.CRASH_FREE_DISK_SPACE, value: customData!["freeDiskSpace"]!)
span.setAttribute(key: MiddlewareConstants.Attributes.CRASH_FREE_MEMORY, value: customData!["freeMemory"]!)
} else {
span.setAttribute(key: "crash.rumSessionId", value: String(decoding: report.customData, as: UTF8.self))
span.setAttribute(key: MiddlewareConstants.Attributes.CRASH_SESSION_ID, value: String(decoding: report.customData, as: UTF8.self))
}
}
span.setAttribute(key: "crash.app.version", value: report.applicationInfo.applicationMarketingVersion)
span.setAttribute(key: "error", value: true)
span.setAttribute(key: MiddlewareConstants.Attributes.CRASH_APP_VERSION, value: report.applicationInfo.applicationMarketingVersion)
var exceptionAttributes = [String: AttributeValue]()
#if !os(macOS)
span.setAttribute(key: MiddlewareConstants.Attributes.DEVICE_MODEL_NAME, value: DeviceKit.Device.current.description)
#else
span.setAttribute(key: MiddlewareConstants.Attributes.DEVICE_MODEL_NAME, value: Device.current.model)
#endif

exceptionAttributes["exception.type"] = AttributeValue(exceptionType ?? "unknown")
span.setAttribute(key: "crash.address", value: report.signalInfo.address.description)
exceptionAttributes[MiddlewareConstants.Attributes.EXCEPTION_TYPE] = AttributeValue(exceptionType!)
span.setAttribute(key: MiddlewareConstants.Attributes.CRASH_ADDRESS, value: report.signalInfo.address.description)
for case let thread as PLCrashReportThreadInfo in report.threads where thread.crashed {
exceptionAttributes["exception.stacktrace"] = AttributeValue(crashedThreadToStack(report: report, thread: thread))
exceptionAttributes[MiddlewareConstants.Attributes.EXCEPTION_STACKTRACE] = AttributeValue(crashedThreadToStack(report: report, thread: thread))
exceptionAttributes[MiddlewareConstants.Attributes.ERROR_STACK] = exceptionAttributes[MiddlewareConstants.Attributes.EXCEPTION_STACKTRACE]
break
}
if report.hasExceptionInfo {
if(report.exceptionInfo.exceptionName != nil) {
exceptionAttributes["exception.type"] = AttributeValue(report.exceptionInfo.exceptionName as Any)
exceptionAttributes[MiddlewareConstants.Attributes.EXCEPTION_TYPE] = AttributeValue(report.exceptionInfo.exceptionName as Any)
}
if(report.exceptionInfo.exceptionReason != nil) {
exceptionAttributes["exception.message"] = AttributeValue(report.exceptionInfo.exceptionReason as Any)
exceptionAttributes[MiddlewareConstants.Attributes.EXCEPTION_MESSAGE] = AttributeValue(report.exceptionInfo.exceptionReason as Any)
exceptionAttributes[MiddlewareConstants.Attributes.ERROR_MESSAGE] = exceptionAttributes[MiddlewareConstants.Attributes.EXCEPTION_MESSAGE]
}
}
span.addEvent(name: "crash.timestamp", attributes: exceptionAttributes, timestamp: report.systemInfo.timestamp)
exceptionAttributes[MiddlewareConstants.Attributes.ERROR_TYPE] = exceptionAttributes[MiddlewareConstants.Attributes.EXCEPTION_TYPE]

span.addEvent(name: MiddlewareConstants.Attributes.CRASH_TIMESTAMP, attributes: exceptionAttributes, timestamp: report.systemInfo.timestamp)
span.end(time: now)
}

Expand Down
1 change: 1 addition & 0 deletions Sources/MiddlewareRum/GlobalAttributesProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class GlobalAttributesProcessor: SpanProcessor {
span.setAttribute(key: MiddlewareConstants.Attributes.APP_VERSION, value: appVersion!)
}
span.setAttribute(key: MiddlewareConstants.Attributes.SESSION_ID, value: getRumSessionId())
span.setAttribute(key: MiddlewareConstants.Attributes.SESSION_START_TIME, value: getSessionStartTime())
span.setAttribute(key: MiddlewareConstants.Attributes.RUM_SDK_VERSION, value: MiddlewareConstants.Global.VERSION_STRING)
span.setAttribute(key: MiddlewareConstants.Attributes.DEVICE_MODEL_NAME, value: deviceModel)
if Thread.current.isMainThread {
Expand Down
16 changes: 15 additions & 1 deletion Sources/MiddlewareRum/MiddlewareConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import Foundation

enum MiddlewareConstants {
enum Global {
static let PROJECT_NAME = "project.name"
static let ACCOUNT_KEY = "mw.account_key"
static let MW_RUM = "mw.rum"
static let INSTRUMENTATION_NAME = "middleware-ios"
static let VERSION_STRING = "1.0.1"
static let UNKNOWN_APP_NAME = "unknown-app"
Expand All @@ -16,11 +19,22 @@ enum MiddlewareConstants {
static let RUM_SDK_VERSION = "mw.rum.sdk.version"
static let DEVICE_MODEL_NAME = "device.model.name"
static let ERROR = "error"
static let ERROR_TYPE = "error.type"
static let ERROR_MESSAGE = "error.message"
static let ERROR_STACK = "error.stack"
static let CRASH_ADDRESS = "crash.address"
static let CRASH_APP_VERSION = "crash.app.version"
static let CRASH_SESSION_ID = "crash.rumSessionId"
static let CRASH_BATTERY_LEVEL = "crash.batteryLevel"
static let CRASH_FREE_DISK_SPACE = "crash.freeDiskSpace"
static let CRASH_FREE_MEMORY = "crash.freeMemory"
static let CRASH_TIMESTAMP = "crash.timestamp"
static let COUNT = "count"
static let EVENT_TYPE = "event.type"
static let OS_NAME = "os.name"
static let OS = "os"
static let OS_VERSION = "os.version"
static let SESSION_ID = "session.id"
static let SESSION_START_TIME = "session.start_time"
static let PREVIOUS_SESSION_ID = "previous.session.id"
static let EXCEPTION_MESSAGE = "exception.message"
static let EXCEPTION_TYPE = "exception.type"
Expand Down
17 changes: 9 additions & 8 deletions Sources/MiddlewareRum/MiddlewareRum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,14 @@ public enum CheckState {
class func createMiddlewareResource(builder: MiddlewareRumBuilder) -> Resource {
var defaultResource = DefaultResources().get()
defaultResource.merge(other: Resource(attributes: [
"mw.account_key" :AttributeValue(builder.rumAccessToken!),
MiddlewareConstants.Global.ACCOUNT_KEY: AttributeValue(builder.rumAccessToken!),
ResourceAttributes.serviceName.rawValue : AttributeValue(builder.serviceName!),
"browser.trace" : AttributeValue("true"),
"mw.rum" : AttributeValue("true"),
MiddlewareConstants.Global.MW_RUM : AttributeValue("true"),
MiddlewareConstants.Attributes.OS: AttributeValue("iOS"),
ResourceAttributes.deviceModelName.rawValue: AttributeValue(Device.current.model),
"project.name":AttributeValue(builder.projectName!),
"session.id": AttributeValue(getSessionId())
MiddlewareConstants.Global.PROJECT_NAME: AttributeValue(builder.projectName!),
MiddlewareConstants.Attributes.SESSION_ID: AttributeValue(getSessionId()),
MiddlewareConstants.Attributes.SESSION_START_TIME: AttributeValue(getSessionStartTime()),
]))
return defaultResource
}
Expand Down Expand Up @@ -282,7 +283,7 @@ public enum CheckState {
let now = Date()
let typeName = e.name.rawValue
let span = tracer.spanBuilder(spanName: typeName).setStartTime(time: now).startSpan()
span.setAttribute(key: MiddlewareConstants.Attributes.COMPONENT, value: "error")
span.setAttribute(key: MiddlewareConstants.Attributes.COMPONENT, value: "crash")
span.setAttribute(key: MiddlewareConstants.Attributes.EVENT_TYPE, value: "error")
span.setAttribute(key: MiddlewareConstants.Attributes.ERROR, value: true)
span.setAttribute(key: MiddlewareConstants.Attributes.EXCEPTION_TYPE, value: typeName)
Expand All @@ -308,7 +309,7 @@ public enum CheckState {
let now = Date()
let typeName = String(describing: type(of: e))
let span = tracer.spanBuilder(spanName: typeName).setStartTime(time: now).startSpan()
span.setAttribute(key: MiddlewareConstants.Attributes.COMPONENT, value: "error")
span.setAttribute(key: MiddlewareConstants.Attributes.COMPONENT, value: "crash")
span.setAttribute(key: MiddlewareConstants.Attributes.EVENT_TYPE, value: "error")
span.setAttribute(key: MiddlewareConstants.Attributes.ERROR, value: true)
span.setAttribute(key: MiddlewareConstants.Attributes.EXCEPTION_TYPE, value: typeName)
Expand All @@ -327,7 +328,7 @@ public enum CheckState {
let now = Date()
let typeName = "MiddlewareRum.addError(String)"
let span = tracer.spanBuilder(spanName: typeName).setStartTime(time: now).startSpan()
span.setAttribute(key: MiddlewareConstants.Attributes.COMPONENT, value: "error")
span.setAttribute(key: MiddlewareConstants.Attributes.COMPONENT, value: "crash")
span.setAttribute(key: MiddlewareConstants.Attributes.EVENT_TYPE, value: "error")
span.setAttribute(key: MiddlewareConstants.Attributes.ERROR, value: true)
span.setAttribute(key: MiddlewareConstants.Attributes.EXCEPTION_TYPE, value: "String")
Expand Down
12 changes: 10 additions & 2 deletions Sources/MiddlewareRum/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ private var rumSessionId = generateNewSessionId()
private var sessionIdExpiration = Date().addingTimeInterval(TimeInterval(MAX_SESSION_AGE_SECONDS))
private let sessionIdLock = NSLock()
private var sessionIdCallbacks: [(() -> Void)] = []
private var sessionStartTime = Int(Date().timeIntervalSince1970 * 1000)

func generateNewSessionId() -> String {
var i=0
Expand Down Expand Up @@ -43,6 +44,7 @@ func getRumSessionId(forceNewSessionId: Bool = false) -> String {
sessionIdExpiration = Date().addingTimeInterval(TimeInterval(MAX_SESSION_AGE_SECONDS))
oldRumSessionId = rumSessionId
rumSessionId = generateNewSessionId()
sessionStartTime = Int(Date().timeIntervalSince1970 * 1000)
isSessionIdChanged = true
callbacks = sessionIdCallbacks
}
Expand All @@ -52,17 +54,23 @@ func getRumSessionId(forceNewSessionId: Bool = false) -> String {
callback()
}
if isSessionIdChanged {
createSessionIdChangeSpan(newSessionId: rumSessionId, previousSessionId: oldRumSessionId)
createSessionIdChangeSpan(newSessionId: rumSessionId, previousSessionId: oldRumSessionId, sessionStartTime: sessionStartTime)
}
return rumSessionId
}
func createSessionIdChangeSpan(newSessionId: String, previousSessionId: String) {

func getSessionStartTime() -> Int {
return sessionStartTime
}

func createSessionIdChangeSpan(newSessionId: String, previousSessionId: String, sessionStartTime: Int) {
let now = Date()
let tracer = OpenTelemetry.instance.tracerProvider.get(
instrumentationName: MiddlewareConstants.Global.INSTRUMENTATION_NAME,
instrumentationVersion: MiddlewareConstants.Global.VERSION_STRING)
var activeResource = OpenTelemetry.instance.tracerProvider.getActiveResource()
activeResource.attributes[MiddlewareConstants.Attributes.SESSION_ID] = AttributeValue(newSessionId)
activeResource.attributes[MiddlewareConstants.Attributes.SESSION_START_TIME] = AttributeValue(sessionStartTime)
OpenTelemetry.instance.tracerProvider.updateActiveResource(activeResource)

let span = tracer.spanBuilder(spanName: MiddlewareConstants.Spans.SESSION_ID_CHANGE).setStartTime(time: now).startSpan()
Expand Down
Loading