Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.example.androidobservability

import android.app.Application
import com.launchdarkly.observability.api.Options
import com.launchdarkly.observability.api.ObservabilityOptions
import com.launchdarkly.observability.client.TelemetryInspector
import com.launchdarkly.observability.plugin.Observability
import com.launchdarkly.observability.replay.PrivacyProfile
Expand All @@ -24,11 +24,16 @@ open class BaseApplication : Application() {
const val LAUNCHDARKLY_MOBILE_KEY = "MOBILE_KEY_GOES_HERE"
}

var pluginOptions = Options(
var observabilityOptions = ObservabilityOptions(
resourceAttributes = Attributes.of(
AttributeKey.stringKey("example"), "value"
),
debug = true,
tracesApi = ObservabilityOptions.TracesApi(includeErrors = false, includeSpans = false),
metricsApi = ObservabilityOptions.MetricsApi.disabled(),
instrumentations = ObservabilityOptions.Instrumentations(
crashReporting = true, launchTime = true, activityLifecycle = false
),
logAdapter = LDAndroidLogging.adapter(),
)

Expand All @@ -39,7 +44,7 @@ open class BaseApplication : Application() {
val observabilityPlugin = Observability(
application = this@BaseApplication,
mobileKey = LAUNCHDARKLY_MOBILE_KEY,
options = testUrl?.let { pluginOptions.copy(backendUrl = it, otlpEndpoint = it) } ?: pluginOptions
options = testUrl?.let { observabilityOptions.copy(backendUrl = it, otlpEndpoint = it) } ?: observabilityOptions
)

val sessionReplayPlugin = SessionReplay(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class ViewModel(application: Application) : AndroidViewModel(application) {
fun triggerLog() {
LDObserve.recordLog(
"Test Log",
Severity.DEBUG,
Severity.INFO,
Attributes.of(AttributeKey.stringKey("FakeAttribute"), "FakeVal")
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.app.Application
import androidx.test.core.app.ApplicationProvider
import com.example.androidobservability.TestUtils.TelemetryType
import com.example.androidobservability.TestUtils.waitForTelemetryData
import com.launchdarkly.observability.api.Options
import com.launchdarkly.observability.api.ObservabilityOptions
import com.launchdarkly.observability.interfaces.Metric
import com.launchdarkly.observability.sdk.LDObserve
import io.opentelemetry.api.common.AttributeKey
Expand All @@ -14,6 +14,7 @@ import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
Expand All @@ -27,12 +28,12 @@ class DisablingConfigOptionsE2ETest {
private val application = ApplicationProvider.getApplicationContext<Application>() as TestApplication

@Test
fun `Logs should NOT be exported when disableLogs is set to true`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableLogs = true)
fun `Logs should NOT be exported when logsApiLevel is NONE`() {
application.observabilityOptions = getOptionsAllEnabled().copy(logsApiLevel = ObservabilityOptions.LogLevel.NONE)
application.initForTest()
val logsUrl = "http://localhost:${application.mockWebServer?.port}/v1/logs"

triggerTestLog()
triggerTestLog(severity = Severity.TRACE)
LDObserve.flush()
waitForTelemetryData(telemetryInspector = application.telemetryInspector, telemetryType = TelemetryType.LOGS)
val logsExported = application.telemetryInspector?.logExporter?.finishedLogRecordItems
Expand All @@ -42,22 +43,55 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Logs should be exported when disableLogs is set to false`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableLogs = false)
fun `Logs should NOT be exported when log severity is lower than logsApiLevel`() {
application.observabilityOptions = getOptionsAllEnabled().copy(logsApiLevel = ObservabilityOptions.LogLevel.INFO)
application.initForTest()
val logsUrl = "http://localhost:${application.mockWebServer?.port}/v1/logs"

triggerTestLog()
triggerTestLog(severity = Severity.TRACE)
LDObserve.flush()
waitForTelemetryData(telemetryInspector = application.telemetryInspector, telemetryType = TelemetryType.LOGS)
val logsExported = application.telemetryInspector?.logExporter?.finishedLogRecordItems

assertTrue(logsExported?.isEmpty() == true)
assertFalse(requestsContainsUrl(logsUrl))
}

@Test
fun `Logs should be exported when log severity is higher than logsApiLevel`() {
application.observabilityOptions = getOptionsAllEnabled().copy(logsApiLevel = ObservabilityOptions.LogLevel.INFO)
application.initForTest()
val logsUrl = "http://localhost:${application.mockWebServer?.port}/v1/logs"

triggerTestLog(severity = Severity.WARN)
LDObserve.flush()
waitForTelemetryData(telemetryInspector = application.telemetryInspector, telemetryType = TelemetryType.LOGS)

assertNotNull(application.telemetryInspector?.logExporter)
assertTrue(requestsContainsUrl(logsUrl))
}


@Test
fun `Spans should NOT be exported when disableTraces is set to true`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableTraces = true)
fun `Spans should NOT be exported when TracesApi is disabled`() {
application.observabilityOptions = getOptionsAllEnabled().copy(tracesApi = ObservabilityOptions.TracesApi.disabled())
application.initForTest()
val tracesUrl = "http://localhost:${application.mockWebServer?.port}/v1/traces"

triggerTestSpan()
LDObserve.flush()

waitForTelemetryData(telemetryInspector = application.telemetryInspector, telemetryType = TelemetryType.SPANS)
val spansExported = application.telemetryInspector?.spanExporter?.finishedSpanItems

assertTrue(spansExported?.isEmpty() == true)
assertFalse(requestsContainsUrl(tracesUrl))
}

fun `Spans should NOT be exported when TracesApi does not include spans`() {
application.observabilityOptions = getOptionsAllEnabled().copy(
tracesApi = ObservabilityOptions.TracesApi(includeSpans = false)
)
application.initForTest()
val tracesUrl = "http://localhost:${application.mockWebServer?.port}/v1/traces"

Expand All @@ -72,8 +106,8 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Spans should be exported when disableTraces is set to false`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableTraces = false)
fun `Spans should be exported when TracesApi is enabled`() {
application.observabilityOptions = getOptionsAllEnabled().copy(tracesApi = ObservabilityOptions.TracesApi.enabled())
application.initForTest()
val tracesUrl = "http://localhost:${application.mockWebServer?.port}/v1/traces"

Expand All @@ -86,8 +120,9 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Metrics should NOT be exported when disableMetrics is set to true`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableMetrics = true)
fun `Metrics should NOT be exported when disabled`() {
application.observabilityOptions =
getOptionsAllEnabled().copy(metricsApi = ObservabilityOptions.MetricsApi.disabled())
application.initForTest()
val metricsUrl = "http://localhost:${application.mockWebServer?.port}/v1/metrics"

Expand All @@ -99,8 +134,9 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Metrics should be exported when disableMetrics is set to false`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableMetrics = false)
fun `Metrics should be exported when enabled`() {
application.observabilityOptions =
getOptionsAllEnabled().copy(metricsApi = ObservabilityOptions.MetricsApi.enabled())
application.initForTest()
val metricsUrl = "http://localhost:${application.mockWebServer?.port}/v1/metrics"

Expand All @@ -112,8 +148,10 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Errors should NOT be exported when disableErrorTracking is set to true`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableErrorTracking = true)
fun `Errors should NOT be exported when TracesApi does not include errors`() {
application.observabilityOptions = getOptionsAllEnabled().copy(
tracesApi = ObservabilityOptions.TracesApi(includeErrors = false)
)
application.initForTest()
val tracesUrl = "http://localhost:${application.mockWebServer?.port}/v1/traces"

Expand All @@ -128,8 +166,10 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Errors should be exported as spans when disableErrorTracking is set to false and disableTraces set to true`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableTraces = true, disableErrorTracking = false)
fun `Errors should be exported as spans when TracesApi include errors but not spans`() {
application.observabilityOptions = getOptionsAllEnabled().copy(
tracesApi = ObservabilityOptions.TracesApi(includeErrors = true, includeSpans = false)
)
application.initForTest()
val tracesUrl = "http://localhost:${application.mockWebServer?.port}/v1/traces"

Expand All @@ -148,8 +188,10 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Crashes should NOT be exported when disableErrorTracking is set to true`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableErrorTracking = true)
fun `Crashes should NOT be exported when crashReporting instrumentation is disabled`() {
application.observabilityOptions = getOptionsAllEnabled().copy(
instrumentations = ObservabilityOptions.Instrumentations(crashReporting = false)
)
application.initForTest()
val logsUrl = "http://localhost:${application.mockWebServer?.port}/v1/logs"

Expand All @@ -163,8 +205,11 @@ class DisablingConfigOptionsE2ETest {
}

@Test
fun `Crashes should be exported as logs when disableErrorTracking is set to false and disableLogs set to true`() {
application.pluginOptions = getOptionsAllEnabled().copy(disableLogs = true, disableErrorTracking = false)
fun `Crashes should be exported as logs when crashReporting instrumentation is enabled logsApiLevel is NONE`() {
application.observabilityOptions = getOptionsAllEnabled().copy(
logsApiLevel = ObservabilityOptions.LogLevel.NONE,
instrumentations = ObservabilityOptions.Instrumentations(crashReporting = true)
)
application.initForTest()
val logsUrl = "http://localhost:${application.mockWebServer?.port}/v1/logs"
val exceptionMessage = "Exception for testing"
Expand All @@ -189,10 +234,10 @@ class DisablingConfigOptionsE2ETest {
}
}

private fun triggerTestLog() {
private fun triggerTestLog(severity: Severity = Severity.INFO) {
LDObserve.recordLog(
message = "test-log",
severity = Severity.INFO,
severity = severity,
attributes = Attributes.empty()
)
}
Expand All @@ -216,13 +261,17 @@ class DisablingConfigOptionsE2ETest {
LDObserve.recordMetric(Metric("test", 50.0))
}

private fun getOptionsAllEnabled(): Options {
return Options(
private fun getOptionsAllEnabled(): ObservabilityOptions {
return ObservabilityOptions(
debug = true,
disableTraces = false,
disableLogs = false,
disableMetrics = false,
disableErrorTracking = false
logsApiLevel = ObservabilityOptions.LogLevel.TRACE,
tracesApi = ObservabilityOptions.TracesApi.enabled(),
metricsApi = ObservabilityOptions.MetricsApi.enabled(),
instrumentations = ObservabilityOptions.Instrumentations(
crashReporting = true,
activityLifecycle = true,
launchTime = true
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Application
import androidx.test.core.app.ApplicationProvider
import com.example.androidobservability.TestUtils.TelemetryType
import com.example.androidobservability.TestUtils.waitForTelemetryData
import com.launchdarkly.observability.api.ObservabilityOptions
import com.launchdarkly.observability.client.TelemetryInspector
import com.launchdarkly.observability.sdk.LDObserve
import io.opentelemetry.api.common.AttributeKey
Expand Down Expand Up @@ -49,6 +50,7 @@ class SamplingE2ETest {

@Before
fun setUp() {
application.observabilityOptions = getOptionsAllEnabled()
application.initForTest()
telemetryInspector = application.telemetryInspector
}
Expand Down Expand Up @@ -203,4 +205,18 @@ class SamplingE2ETest {
)
span7.end()
}

private fun getOptionsAllEnabled(): ObservabilityOptions {
return ObservabilityOptions(
debug = true,
logsApiLevel = ObservabilityOptions.LogLevel.TRACE,
tracesApi = ObservabilityOptions.TracesApi.enabled(),
metricsApi = ObservabilityOptions.MetricsApi.enabled(),
instrumentations = ObservabilityOptions.Instrumentations(
crashReporting = true,
activityLifecycle = true,
launchTime = true
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ dependencies {
// Testing exporters for telemetry inspection
implementation("io.opentelemetry:opentelemetry-sdk-testing:1.51.0")

// Android instrumentation
// OTEL Android
implementation("io.opentelemetry.android:core:0.11.0-alpha")
implementation("io.opentelemetry.android.instrumentation:activity:0.11.0-alpha")
implementation("io.opentelemetry.android:session:0.11.0-alpha")

// Android crash instrumentation
// OTEL Android Instrumentations
implementation("io.opentelemetry.android.instrumentation:crash:0.11.0-alpha")
implementation("io.opentelemetry.android.instrumentation:activity:0.11.0-alpha")

// TODO: O11Y-626 - move replay instrumentation and associated compose dependencies into dedicated package
// Compose dependencies for capture functionality
Expand Down
Loading
Loading