Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/background aware span export #648

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
e5321a5
add SpanFileProvider
rezastallone Sep 25, 2023
82c18dd
add StartTypeAwareSpanFileProvider
rezastallone Sep 25, 2023
f2cff95
add function to calculate dir size from /span & /span/background recu…
rezastallone Sep 25, 2023
afd9b84
change session id to UUID to loose coupling from otel session id
rezastallone Sep 26, 2023
8c1501b
provide file path for span using SpanFileProvider
rezastallone Sep 26, 2023
6a24f62
abstract backlog for MemoryBufferingExporter
rezastallone Sep 26, 2023
b03f131
implement start type aware BacklogProvider
rezastallone Sep 26, 2023
747414e
implement default SpanFileProvider
rezastallone Sep 26, 2023
1125f87
return start type aware BacklogProvider & SpanFileProvider based on i…
rezastallone Sep 26, 2023
01d3c32
add unit test for StartTypeAwareSpanFileProvider
rezastallone Sep 26, 2023
2eff353
add background worker for testing
rezastallone Sep 26, 2023
0c3d319
move constructor below fields
rezastallone Sep 29, 2023
ba649e0
move static constant above fields
rezastallone Sep 29, 2023
dd0581a
rename fillFromBacklog to drain
rezastallone Sep 29, 2023
1b05193
reduce SpanFileProvider access level to package level
rezastallone Sep 29, 2023
a086e63
rename SpanFileProvider to SpanStorage
rezastallone Sep 29, 2023
1fe70f6
invert if in provideSpanFile
rezastallone Sep 29, 2023
9b20744
pass root directory to SpanStorage constructor instead of Application
rezastallone Sep 29, 2023
a7ca5dd
remove Application dependency from StartTypeAwareSpanStorageTest.java
rezastallone Sep 29, 2023
9872cc7
reduce access level BacklogProvider to package level
rezastallone Sep 29, 2023
ad985a6
move max span in backlog checking back to MemoryBufferingExporter
rezastallone Sep 29, 2023
7129a2f
rename StartTypeAwareBacklogProvider to StartTypeAwareMemorySpanBuffer
rezastallone Sep 29, 2023
8875489
use Stream to list file recursively
rezastallone Sep 29, 2023
56224cd
reword description for StartTypeAwareSpanStorage
rezastallone Sep 29, 2023
bef29ba
remove unused semicolon
rezastallone Sep 29, 2023
b7d99b8
call forEach directly instead of collect since it's also terminal ope…
rezastallone Sep 29, 2023
40e142e
remove unused import
rezastallone Sep 29, 2023
3416a23
use debug log level instead of information
rezastallone Sep 29, 2023
bceb963
move methods close to immediate caller for readability
rezastallone Sep 29, 2023
304d994
remove DemoWorker from manifest declaration
rezastallone Sep 29, 2023
36da239
add javadoc for SpanStorage
rezastallone Sep 29, 2023
1761685
rename backgroundTaskInstrumentationEnabled
rezastallone Sep 30, 2023
8386a84
add deffer background instrumentation until foreground Rum builder pa…
rezastallone Sep 30, 2023
fa5c43d
remove max size backlog test since the logic has been moved out of th…
rezastallone Sep 30, 2023
f620e45
update unit test StartTypeAwareMemorySpanBufferTest
rezastallone Sep 30, 2023
54cc6f9
remove max size exceed test from DefaultMemorySpanBufferTest
rezastallone Sep 30, 2023
8731c33
apply spotless
rezastallone Oct 3, 2023
b62a349
apply spotless to splunk-otel-android project
rezastallone Oct 3, 2023
505c70f
downgrade io.opentelemetry.android:instrumentation to 0.1.0-alpha-SNA…
rezastallone Oct 3, 2023
1bf4265
Revert "downgrade io.opentelemetry.android:instrumentation to 0.1.0-a…
rezastallone Oct 3, 2023
01c9885
fix background span not sent because not checking visibility tracker …
rezastallone Oct 11, 2023
cc28348
clean up old background directories on new uniqueId created
rezastallone Oct 11, 2023
f4e00da
apply spotless
rezastallone Oct 11, 2023
83ec585
differentiate screen name between previous visible screen & current v…
rezastallone Oct 12, 2023
76d3fd8
reword cleanupUnsentBackgroundSpans
rezastallone Oct 12, 2023
0e6573b
clean background span directories after moving its spans to foreground
rezastallone Oct 12, 2023
cc1b94d
apply javabean convention for variable name in ConfigFlags.java
rezastallone Oct 12, 2023
c1421c3
rename isSubprocessInstrumentationDisabled to isSubprocessInstrumenta…
rezastallone Oct 12, 2023
cb7417c
create factory method for StartTypeAwareSpanStorage
rezastallone Oct 12, 2023
51facbc
reword file to dir
rezastallone Oct 12, 2023
053a28e
reword file to dir
rezastallone Oct 12, 2023
998575e
apply spotless
rezastallone Oct 12, 2023
0c676ad
fix visibility checking bug in StartTypeAwareMemorySpanBuffer
rezastallone Oct 13, 2023
0db8029
reword disableBackgroundTaskReporting to disableSubprocessInstrumenta…
rezastallone Oct 13, 2023
3ecbe76
disableSubprocessInstrumentation in sample app
rezastallone Oct 13, 2023
0b90a1d
apply spotless
rezastallone Oct 13, 2023
fc5dd8e
reword reword term backgroundTaskReporting to subprocessInstrumentation
rezastallone Oct 13, 2023
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
1 change: 1 addition & 0 deletions sample-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ dependencies {
implementation(project(":splunk-otel-android"))
implementation(project(":splunk-otel-android-volley"))
implementation("com.android.volley:volley:1.2.1")
implementation("androidx.work:work-runtime:2.8.1")
implementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api")
implementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-semconv")

Expand Down
4 changes: 4 additions & 0 deletions sample-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".SplunkBackgroundService"
android:exported="false"
android:process=":my_service_process"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright Splunk Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.splunk.android.sample;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import com.splunk.rum.SplunkRum;
import io.opentelemetry.api.common.Attributes;

public class DemoWorker extends Worker {

private Context context;
public static final String TAG = "SplunkRum";

public DemoWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
this.context = context;
}

@NonNull
@Override
public Result doWork() {
try {
SplunkRum.getInstance().addRumEvent("DemoWorker is doing work", Attributes.empty());
Log.d(TAG, "DemoWorker Starting background Service");
startBackgroundService();
return Result.success();
} catch (Exception e) {
return Result.failure();
}
}

private void startBackgroundService() {
Intent serviceIntent = new Intent(context, SplunkBackgroundService.class);
Log.d(TAG, "Starting background Service");
context.startService(serviceIntent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
});

sessionId.postValue(splunkRum.getRumSessionId());

binding.workManager.setOnClickListener(
v -> {
WorkManagerHelper.startWorkManager(this.getContext());
});
}

private void multiThreadCrashing() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import com.splunk.android.sample.databinding.ActivityMainBinding;
import com.splunk.rum.SplunkRum;
import io.opentelemetry.android.instrumentation.RumScreenName;
Expand Down Expand Up @@ -74,6 +77,18 @@ protected void onCreate(Bundle savedInstanceState) {
view -> {
new MailDialogFragment(this).show(getSupportFragmentManager(), "Mail");
});
setUpPeriodicWorker();
}

private void setUpPeriodicWorker() {
PeriodicWorkRequest workRequest =
new PeriodicWorkRequest.Builder(DemoWorker.class, 15, TimeUnit.MINUTES).build();

WorkManager.getInstance(this)
.enqueueUniquePeriodicWork(
"backgroundsplunk",
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
workRequest);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public void onCreate() {
.setRumAccessToken(getResources().getString(R.string.rum_access_token))
.enableDebug()
.enableDiskBuffering()
.disableBackgroundTaskReporting(BuildConfig.APPLICATION_ID)
.disableSubprocessInstrumentation(BuildConfig.APPLICATION_ID)
.enableBackgroundInstrumentationDeferredUntilForeground()
.setSlowRenderingDetectionPollInterval(Duration.ofMillis(1000))
.setDeploymentEnvironment("demo")
.limitDiskUsageMegabytes(1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Splunk Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.splunk.android.sample;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class SplunkBackgroundService extends Service {
public static final String TAG = "SplunkRum";

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
Log.d(TAG, "Service started on different thread");
}
stopSelf();
return START_STICKY;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Splunk Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.splunk.android.sample;

import android.content.Context;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;
import androidx.work.WorkRequest;

public class WorkManagerHelper {

public static void startWorkManager(Context context) {
WorkRequest demoWorkRequest = new OneTimeWorkRequest.Builder(DemoWorker.class).build();
WorkManager.getInstance(context).enqueue(demoWorkRequest);
}
}
7 changes: 7 additions & 0 deletions sample-app/src/main/res/layout/fragment_first.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@
android:layout_marginTop="8dp"
android:text="@string/volley_client" />

<Button
android:id="@+id/work_manager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/worker" />

<TextView
android:id="@+id/session_id"
android:layout_width="wrap_content"
Expand Down
1 change: 1 addition & 0 deletions sample-app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<string name="http_me_up">HTTP me up!</string>
<string name="http_me_bad">Http Error</string>
<string name="volley_client">Volley HTTP</string>
<string name="worker">Worker</string>
<string name="http_not_found">HTTP Not Found</string>

<string name="local_web_view">Local WebView</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class ConfigFlags {
private boolean networkMonitorEnabled = true;
private boolean anrDetectionEnabled = true;
private boolean slowRenderingDetectionEnabled = true;
private boolean backgroundTaskInstrumentationEnabled = true;
private boolean subprocessInstrumentationEnabled = true;
private boolean backgroundInstrumentationDeferredUntilForeground = false;

void enableDebug() {
debugEnabled = true;
Expand Down Expand Up @@ -56,16 +57,24 @@ void disableSlowRenderingDetection() {
slowRenderingDetectionEnabled = false;
}

public void disableBackgroundTaskDetection() {
backgroundTaskInstrumentationEnabled = false;
public void disableSubprocessInstrumentation() {
subprocessInstrumentationEnabled = false;
}

public void enableBackgroundInstrumentationDeferredUntilForeground() {
backgroundInstrumentationDeferredUntilForeground = true;
}

boolean isDebugEnabled() {
return debugEnabled;
}

boolean isBackgroundTaskInstrumentationEnabled() {
return backgroundTaskInstrumentationEnabled;
boolean isSubprocessInstrumentationEnabled() {
return subprocessInstrumentationEnabled;
}

boolean isBackgroundInstrumentationDeferredUntilForeground() {
return backgroundInstrumentationDeferredUntilForeground;
}

boolean isAnrDetectionEnabled() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright Splunk Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.splunk.rum;

import io.opentelemetry.sdk.trace.data.SpanData;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;

public class DefaultMemorySpanBuffer implements MemorySpanBuffer {

// note: no need to make this queue thread-safe since it will only ever be called from the
// BatchSpanProcessor worker thread.
private final Queue<SpanData> backlog = new ArrayDeque<>();

@Override
public void addAll(Collection<SpanData> spans) {
backlog.addAll(spans);
}

@Override
public void addFailedSpansToBacklog(SpanData spanData) {
backlog.add(spanData);
}

@Override
public List<SpanData> drain() {
List<SpanData> retries = new ArrayList<>(backlog);
backlog.clear();
return retries;
}

@Override
public boolean isEmpty() {
return backlog.isEmpty();
}

@Override
public void clear() {
backlog.clear();
}

@Override
public int size() {
return backlog.size();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright Splunk Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.splunk.rum;

import android.util.Log;
import java.io.File;
import java.util.stream.Stream;

public class DefaultSpanStorage implements SpanStorage {

private final FileUtils fileUtils;
private final File rootDir;

public DefaultSpanStorage(FileUtils fileUtils, File rootDir) {
this.fileUtils = fileUtils;
this.rootDir = rootDir;
}

@Override
public File provideSpanFile() {
File spansPath = fileUtils.getSpansDirectory(rootDir);
if (spansPath.exists() || spansPath.mkdirs()) {
return spansPath;
}

Log.e(
SplunkRum.LOG_TAG,
"Error creating path " + spansPath + " for span buffer, defaulting to parent");
return rootDir;
}

@Override
public Stream<File> getAllSpanFiles() {
return fileUtils.listSpanFiles(provideSpanFile());
}

@Override
public long getTotalFileSizeInBytes() {
return fileUtils.getTotalFileSizeInBytes(provideSpanFile());
}

@Override
public Stream<File> getPendingFiles() {
return fileUtils.listSpanFiles(provideSpanFile());
}
}
Loading