Skip to content

Commit

Permalink
React native exporter (#381)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhennoch authored Oct 13, 2022
1 parent f8ed61c commit ba6cc2c
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ SpanExporter buildFilteringExporter(ConnectionUtil connectionUtil) {
SpanExporter filteredExporter = builder.decorateWithSpanFilter(exporter);
initializationEvents.add(
new InitializationEvent("zipkin exporter initialized", timingClock.now()));

if (builder.reactNativeSupportEnabled) {
return builder.decorateWithReactNativeExporter(filteredExporter);
}
return filteredExporter;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import android.app.Application;
import android.util.Log;
import androidx.annotation.Nullable;
import com.splunk.rum.reactnative.ReactNativeExporter;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
Expand Down Expand Up @@ -50,6 +51,7 @@ public final class SplunkRumBuilder {
int maxUsageMegabytes = DEFAULT_MAX_STORAGE_USE_MB;
boolean sessionBasedSamplerEnabled = false;
double sessionBasedSamplerRatio = 1.0;
boolean reactNativeSupportEnabled = false;

/**
* Sets the application name that will be used to identify your application in the Splunk RUM
Expand Down Expand Up @@ -138,6 +140,11 @@ public SplunkRumBuilder enableDiskBuffering() {
return this;
}

public SplunkRumBuilder enableReactNativeSupport() {
this.reactNativeSupportEnabled = true;
return this;
}

/**
* Disables the crash reporting feature.
*
Expand Down Expand Up @@ -310,6 +317,10 @@ SpanExporter decorateWithSpanFilter(SpanExporter exporter) {
return spanFilterBuilder.build().apply(exporter);
}

public SpanExporter decorateWithReactNativeExporter(SpanExporter exporter) {
return new ReactNativeExporter(exporter);
}

Attributes buildInitialGlobalAttributes() {
Attributes attrs = globalAttributes;
if (deploymentEnvironment != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* 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.reactnative;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.internal.ImmutableSpanContext;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.sdk.trace.data.DelegatingSpanData;
import io.opentelemetry.sdk.trace.data.SpanData;

public final class RNSpanData extends DelegatingSpanData {

private final SpanContext modifiedContext;
private final Attributes modifiedAttributes;

static SpanData create(SpanData original) {
SpanContext originalSpanContext = original.getSpanContext();
Attributes attributes = original.getAttributes();
AttributeKey<String> traceIdKey = AttributeKey.stringKey("_reactnative_traceId");
AttributeKey<String> spanIdKey = AttributeKey.stringKey("_reactnative_spanId");

String traceIdFromRN = attributes.get(traceIdKey);
String spanIdFromRN = attributes.get(spanIdKey);
if (traceIdFromRN == null || spanIdFromRN == null) {
return original;
}

Attributes attributesWithoutRNIds =
attributes.toBuilder().remove(traceIdKey).remove(spanIdKey).build();

SpanContext rnContext =
ImmutableSpanContext.create(
traceIdFromRN,
spanIdFromRN,
originalSpanContext.getTraceFlags(),
originalSpanContext.getTraceState(),
originalSpanContext.isRemote(),
false);
return new RNSpanData(original, rnContext, attributesWithoutRNIds);
}

private RNSpanData(
SpanData delegate, SpanContext modifiedContext, Attributes modifiedAttributes) {
super(delegate);
this.modifiedContext = modifiedContext;
this.modifiedAttributes = modifiedAttributes;
}

@Override
public SpanContext getSpanContext() {
return this.modifiedContext;
}

@Override
public Attributes getAttributes() {
return this.modifiedAttributes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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.reactnative;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public final class ReactNativeExporter implements SpanExporter {
private final SpanExporter delegate;

public ReactNativeExporter(SpanExporter delegate) {
this.delegate = delegate;
}

@Override
public CompletableResultCode export(Collection<SpanData> spans) {
List<SpanData> modified = new ArrayList<>();
for (SpanData span : spans) {
modified.add(modify(span));
}
return delegate.export(modified);
}

private SpanData modify(SpanData span) {
Attributes attributes = span.getAttributes();
if (attributes.get(AttributeKey.stringKey("_reactnative_traceId")) == null) {
return span;
}
return RNSpanData.create(span);
}

@Override
public CompletableResultCode flush() {
return delegate.flush();
}

@Override
public CompletableResultCode shutdown() {
return delegate.shutdown();
}
}

0 comments on commit ba6cc2c

Please sign in to comment.