expo-observe 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +2 -0
- package/android/src/main/java/expo/modules/observe/Event.kt +2 -0
- package/android/src/main/java/expo/modules/observe/OpenTelemetry.kt +7 -2
- package/ios/Event.swift +5 -3
- package/ios/ExpoObserve.podspec +1 -8
- package/ios/ObserveVersions.h +0 -3
- package/ios/ObserveVersions.m +0 -22
- package/ios/OpenTelemetry.swift +7 -0
- package/ios/Tests/OpenTelemetryTests.swift +33 -0
- package/package.json +2 -2
package/android/build.gradle
CHANGED
|
@@ -54,6 +54,7 @@ data class EASMetric(
|
|
|
54
54
|
val name: String,
|
|
55
55
|
val value: Double,
|
|
56
56
|
val routeName: String? = null,
|
|
57
|
+
val updateId: String? = null,
|
|
57
58
|
val customParams: JsonObject? = null
|
|
58
59
|
) {
|
|
59
60
|
companion object {
|
|
@@ -65,6 +66,7 @@ data class EASMetric(
|
|
|
65
66
|
name = metric.name,
|
|
66
67
|
value = metric.value,
|
|
67
68
|
routeName = metric.routeName,
|
|
69
|
+
updateId = metric.updateId,
|
|
68
70
|
// TODO(@lukmccall): Consider using `org.json.JSONObject` instead of kotlinx.serialization. Also, we're not handling exceptions that might be thrown here.
|
|
69
71
|
customParams = metric.params?.let { Json.decodeFromString<JsonObject>(it) }
|
|
70
72
|
)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
package expo.modules.observe
|
|
2
2
|
|
|
3
3
|
import expo.modules.appmetrics.utils.TimeUtils.timestampToDateNS
|
|
4
|
-
import java.util.UUID
|
|
5
4
|
import kotlinx.serialization.Serializable
|
|
6
5
|
import kotlinx.serialization.json.Json
|
|
7
6
|
|
|
@@ -93,6 +92,9 @@ private val metricNameMap = mapOf(
|
|
|
93
92
|
// Legacy metrics - will be removed in a future release
|
|
94
93
|
"loadTime" to "expo.app_startup.load_time",
|
|
95
94
|
"launchTime" to "expo.app_startup.launch_time",
|
|
95
|
+
|
|
96
|
+
// Updates
|
|
97
|
+
"updateDownloadTime" to "expo.updates.download_time",
|
|
96
98
|
)
|
|
97
99
|
|
|
98
100
|
fun EASMetric.toOTMetric(): OTMetric {
|
|
@@ -102,6 +104,9 @@ fun EASMetric.toOTMetric(): OTMetric {
|
|
|
102
104
|
routeName?.let {
|
|
103
105
|
attributes.add(OTAttribute.of(key = "expo.route_name", rawValue = it))
|
|
104
106
|
}
|
|
107
|
+
updateId?.let {
|
|
108
|
+
attributes.add(OTAttribute.of(key = "expo.update_id", rawValue = it))
|
|
109
|
+
}
|
|
105
110
|
customParams?.let {
|
|
106
111
|
attributes.add(OTAttribute.of(key = "expo.custom_params", rawValue = it.toString()))
|
|
107
112
|
}
|
|
@@ -179,7 +184,7 @@ fun Event.toOTEvent(easClientId: String): OTEvent {
|
|
|
179
184
|
resource = toOTMetadata(easClientId),
|
|
180
185
|
scopeMetrics = listOf(
|
|
181
186
|
OTScopeMetrics(
|
|
182
|
-
scope = OTScope(name = "expo-observe", version =
|
|
187
|
+
scope = OTScope(name = "expo-observe", version = BuildConfig.EXPO_OBSERVE_VERSION),
|
|
183
188
|
metrics = metrics.map { it.toOTMetric() }
|
|
184
189
|
)
|
|
185
190
|
)
|
package/ios/Event.swift
CHANGED
|
@@ -46,6 +46,7 @@ struct Event: Codable, Sendable {
|
|
|
46
46
|
|
|
47
47
|
// Metadata
|
|
48
48
|
let routeName: String?
|
|
49
|
+
let updateId: String?
|
|
49
50
|
let customParams: AnyCodable?
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -60,15 +61,15 @@ struct Event: Codable, Sendable {
|
|
|
60
61
|
appVersion: app.appVersion,
|
|
61
62
|
appBuildNumber: app.buildNumber,
|
|
62
63
|
appUpdateId: app.updateId,
|
|
63
|
-
appEasBuildId: app.easBuildId
|
|
64
|
+
appEasBuildId: app.easBuildId,
|
|
64
65
|
|
|
65
66
|
deviceName: device.modelName,
|
|
66
67
|
deviceModel: device.modelIdentifier,
|
|
67
68
|
deviceOs: device.systemName,
|
|
68
69
|
deviceOsVersion: device.systemVersion,
|
|
69
70
|
|
|
70
|
-
reactNativeVersion:
|
|
71
|
-
expoSdkVersion:
|
|
71
|
+
reactNativeVersion: app.reactNativeVersion,
|
|
72
|
+
expoSdkVersion: app.expoSdkVersion,
|
|
72
73
|
clientVersion: ObserveVersions.clientVersion,
|
|
73
74
|
|
|
74
75
|
languageTag: Locale.preferredLanguages.first ?? "en-US",
|
|
@@ -84,6 +85,7 @@ struct Event: Codable, Sendable {
|
|
|
84
85
|
sessionId: session.id,
|
|
85
86
|
parentSessionId: nil,
|
|
86
87
|
routeName: metric.routeName,
|
|
88
|
+
updateId: metric.updateId,
|
|
87
89
|
customParams: metric.params
|
|
88
90
|
)
|
|
89
91
|
}
|
package/ios/ExpoObserve.podspec
CHANGED
|
@@ -2,10 +2,6 @@ require 'json'
|
|
|
2
2
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
4
|
|
|
5
|
-
reactNativeVersion = begin `node --print "require('react-native/package.json').version"`.strip rescue '0.0.0' end
|
|
6
|
-
expoSdkVersion = begin `node --print "require('expo/package.json').version"`.strip rescue '0.0.0' end
|
|
7
|
-
easBuildId = ENV.has_key?('EAS_BUILD_ID') ? ENV['EAS_BUILD_ID'] : nil
|
|
8
|
-
|
|
9
5
|
Pod::Spec.new do |s|
|
|
10
6
|
s.name = 'ExpoObserve'
|
|
11
7
|
s.version = package['version']
|
|
@@ -32,10 +28,7 @@ Pod::Spec.new do |s|
|
|
|
32
28
|
'DEFINES_MODULE' => 'YES',
|
|
33
29
|
'SWIFT_COMPILATION_MODE' => 'wholemodule',
|
|
34
30
|
'GCC_PREPROCESSOR_DEFINITIONS' => [
|
|
35
|
-
"
|
|
36
|
-
"EXPO_SDK_VERSION=\"#{expoSdkVersion}\"",
|
|
37
|
-
"EXPO_OBSERVE_VERSION=\"#{package['version']}\"",
|
|
38
|
-
easBuildId ? "EXPO_OBSERVE_BUILD_ID=\"#{easBuildId}\"" : nil
|
|
31
|
+
"EXPO_OBSERVE_VERSION=\"#{package['version']}\""
|
|
39
32
|
].compact
|
|
40
33
|
}
|
|
41
34
|
|
package/ios/ObserveVersions.h
CHANGED
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
@interface ObserveVersions : NSObject
|
|
6
6
|
|
|
7
|
-
@property (class, readonly, nonnull) NSString *reactNativeVersion;
|
|
8
|
-
@property (class, readonly, nonnull) NSString *expoSdkVersion;
|
|
9
7
|
@property (class, readonly, nonnull) NSString *clientVersion;
|
|
10
|
-
@property (class, readonly, nullable) NSString *easBuildId;
|
|
11
8
|
|
|
12
9
|
@end
|
package/ios/ObserveVersions.m
CHANGED
|
@@ -5,35 +5,13 @@
|
|
|
5
5
|
#define STRINGIZE(x) #x
|
|
6
6
|
#define STRINGIZE2(x) STRINGIZE(x)
|
|
7
7
|
|
|
8
|
-
#define REACT_NATIVE_VERSION_STRING STRINGIZE2(REACT_NATIVE_VERSION)
|
|
9
|
-
#define EXPO_SDK_VERSION_STRING STRINGIZE2(EXPO_SDK_VERSION)
|
|
10
8
|
#define EXPO_OBSERVE_VERSION_STRING STRINGIZE2(EXPO_OBSERVE_VERSION)
|
|
11
|
-
#define EXPO_OBSERVE_BUILD_ID_STRING STRINGIZE2(EXPO_OBSERVE_BUILD_ID)
|
|
12
9
|
|
|
13
10
|
@implementation ObserveVersions
|
|
14
11
|
|
|
15
|
-
+ (NSString *)reactNativeVersion
|
|
16
|
-
{
|
|
17
|
-
return @REACT_NATIVE_VERSION_STRING;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
+ (NSString *)expoSdkVersion
|
|
21
|
-
{
|
|
22
|
-
return @EXPO_SDK_VERSION_STRING;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
12
|
+ (NSString *)clientVersion
|
|
26
13
|
{
|
|
27
14
|
return @EXPO_OBSERVE_VERSION_STRING;
|
|
28
15
|
}
|
|
29
16
|
|
|
30
|
-
+ (NSString *)easBuildId
|
|
31
|
-
{
|
|
32
|
-
#ifdef EXPO_OBSERVE_BUILD_ID
|
|
33
|
-
return @EXPO_OBSERVE_BUILD_ID_STRING;
|
|
34
|
-
#else
|
|
35
|
-
return nil;
|
|
36
|
-
#endif
|
|
37
|
-
}
|
|
38
|
-
|
|
39
17
|
@end
|
package/ios/OpenTelemetry.swift
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
+
import ExpoAppMetrics
|
|
2
3
|
|
|
3
4
|
// MARK: -- Open Telemetry data classes
|
|
4
5
|
|
|
@@ -65,6 +66,9 @@ let metricNameMap = [
|
|
|
65
66
|
// Legacy metrics - will be removed in a future release
|
|
66
67
|
"loadTime": "expo.app_startup.load_time",
|
|
67
68
|
"launchTime": "expo.app_startup.launch_time",
|
|
69
|
+
|
|
70
|
+
// Updates
|
|
71
|
+
"updateDownloadTime": "expo.updates.download_time"
|
|
68
72
|
]
|
|
69
73
|
|
|
70
74
|
nonisolated(unsafe) let formatter = ISO8601DateFormatter()
|
|
@@ -85,6 +89,9 @@ extension Event.Metric {
|
|
|
85
89
|
if let routeName {
|
|
86
90
|
attributes.append(OTAttribute(key: "expo.route_name", rawValue: routeName))
|
|
87
91
|
}
|
|
92
|
+
if let updateId {
|
|
93
|
+
attributes.append(OTAttribute(key: "expo.update_id", rawValue: updateId))
|
|
94
|
+
}
|
|
88
95
|
if let customParamsString = try? customParams?.toJSONString() {
|
|
89
96
|
attributes.append(OTAttribute(key: "expo.custom_params", rawValue: customParamsString))
|
|
90
97
|
}
|
|
@@ -36,6 +36,7 @@ struct OpenTelemetryTests {
|
|
|
36
36
|
sessionId: testSessionId,
|
|
37
37
|
parentSessionId: nil,
|
|
38
38
|
routeName: nil,
|
|
39
|
+
updateId: nil,
|
|
39
40
|
customParams: nil
|
|
40
41
|
)
|
|
41
42
|
}
|
|
@@ -235,6 +236,7 @@ struct OpenTelemetryTests {
|
|
|
235
236
|
sessionId: testSessionId,
|
|
236
237
|
parentSessionId: nil,
|
|
237
238
|
routeName: "/home",
|
|
239
|
+
updateId: nil,
|
|
238
240
|
customParams: nil
|
|
239
241
|
)
|
|
240
242
|
let otMetric = metric.toOTMetric()
|
|
@@ -243,6 +245,36 @@ struct OpenTelemetryTests {
|
|
|
243
245
|
#expect(attrs["expo.route_name"] == "/home")
|
|
244
246
|
}
|
|
245
247
|
|
|
248
|
+
@Test
|
|
249
|
+
func `toOTMetric includes update id attribute when present`() {
|
|
250
|
+
let metric = Event.Metric(
|
|
251
|
+
category: "updates",
|
|
252
|
+
name: "updateDownloadTime",
|
|
253
|
+
value: 2.5,
|
|
254
|
+
timestamp: "2026-01-01T00:00:00Z",
|
|
255
|
+
sessionId: testSessionId,
|
|
256
|
+
parentSessionId: nil,
|
|
257
|
+
routeName: nil,
|
|
258
|
+
updateId: "abc123-def456",
|
|
259
|
+
customParams: nil
|
|
260
|
+
)
|
|
261
|
+
let otMetric = metric.toOTMetric()
|
|
262
|
+
let attrs = Dictionary(uniqueKeysWithValues: otMetric.gauge.dataPoints[0].attributes.map { ($0.key, $0.value.stringValue) })
|
|
263
|
+
|
|
264
|
+
#expect(otMetric.name == "expo.updates.download_time")
|
|
265
|
+
#expect(attrs["expo.update_id"] == "abc123-def456")
|
|
266
|
+
#expect(attrs["session.id"] == testSessionId)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@Test
|
|
270
|
+
func `toOTMetric excludes update id attribute when nil`() {
|
|
271
|
+
let metric = makeMetric(name: "bundleLoadTime", value: 1.0, timestamp: "2026-01-01T00:00:00Z")
|
|
272
|
+
let otMetric = metric.toOTMetric()
|
|
273
|
+
let keys = otMetric.gauge.dataPoints[0].attributes.map { $0.key }
|
|
274
|
+
|
|
275
|
+
#expect(keys.contains("expo.update_id") == false)
|
|
276
|
+
}
|
|
277
|
+
|
|
246
278
|
@Test
|
|
247
279
|
func `toOTMetric excludes route name attribute when nil`() {
|
|
248
280
|
let metric = makeMetric(name: "bundleLoadTime", value: 1.0, timestamp: "2026-01-01T00:00:00Z")
|
|
@@ -262,6 +294,7 @@ struct OpenTelemetryTests {
|
|
|
262
294
|
sessionId: testSessionId,
|
|
263
295
|
parentSessionId: nil,
|
|
264
296
|
routeName: nil,
|
|
297
|
+
updateId: nil,
|
|
265
298
|
customParams: AnyCodable(["screen": "dashboard", "variant": "A"] as [String: Any])
|
|
266
299
|
)
|
|
267
300
|
let otMetric = metric.toOTMetric()
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-observe",
|
|
3
3
|
"title": "Expo Observe",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.6",
|
|
5
5
|
"description": "Expo module that dispatches collected app metrics to EAS Observe",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"author": "650 Industries, Inc.",
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"expo-app-metrics": "~0.1.
|
|
36
|
+
"expo-app-metrics": "~0.1.6",
|
|
37
37
|
"expo-eas-client": "~55.0.3"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|