Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,10 +2,15 @@

## Unreleased

### Fixes

- Only send userid in Dynamic Sampling Context if sendDefaultPii is true ([#2147](https://github.com/getsentry/sentry-java/pull/2147))

### Features

- New package `sentry-android-navigation` for AndroidX Navigation support ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- New package `sentry-compose` for Jetpack Compose support (Navigation) ([#2136](https://github.com/getsentry/sentry-java/pull/2136))
- Add sample rate to baggage as well as trace in envelope header and flatten user ([#2135](https://github.com/getsentry/sentry-java/pull/2135))

## 6.1.4

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import com.nhaarman.mockitokotlin2.whenever
import io.sentry.Hint
import io.sentry.IHub
import io.sentry.SentryTracer
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP
import io.sentry.protocol.MeasurementValue
Expand All@@ -21,7 +22,7 @@ class PerformanceAndroidEventProcessorTest {
val options = SentryAndroidOptions()

val hub = mock<IHub>()
val context = TransactionContext("name", "op", true)
val context = TransactionContext("name", "op", TracesSamplingDecision(true))
val tracer = SentryTracer(context, hub)
val activityFramesTracker = mock<ActivityFramesTracker>()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@ import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TraceContext
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import io.sentry.protocol.SentryTransaction
import kotlinx.coroutines.launch
Expand DownExpand Up@@ -200,7 +201,7 @@ class SentryApolloInterceptorTest {
private fun executeQuery(sut: ApolloClient = fixture.getSut(), isSpanActive: Boolean = true) = runBlocking {
var tx: ITransaction? = null
if (isSpanActive) {
tx = SentryTracer(TransactionContext("op", "desc", true), fixture.hub)
tx = SentryTracer(TransactionContext("op", "desc", TracesSamplingDecision(true)), fixture.hub)
whenever(fixture.hub.span).thenReturn(tx)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
Expand All@@ -28,7 +29,7 @@ class SentrySpanRestTemplateCustomizerTest {
val hub = mock<IHub>()
val restTemplate = RestTemplateBuilder().build()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
internal val customizer = SentrySpanRestTemplateCustomizer(hub)
val url = mockServer.url("/test/123").toString()

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ import io.sentry.SentryOptions
import io.sentry.SentryTraceHeader
import io.sentry.SentryTracer
import io.sentry.SpanStatus
import io.sentry.TracesSamplingDecision
import io.sentry.TransactionContext
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
Expand All@@ -34,7 +35,7 @@ class SentrySpanWebClientCustomizerTest {
lateinit var sentryOptions: SentryOptions
val hub = mock<IHub>()
var mockServer = MockWebServer()
val transaction = SentryTracer(TransactionContext("aTransaction", "op", true), hub)
val transaction = SentryTracer(TransactionContext("aTransaction", "op", TracesSamplingDecision(true)), hub)
private val customizer = SentrySpanWebClientCustomizer(hub)

fun getSut(isTransactionActive: Boolean, status: HttpStatus = HttpStatus.OK, throwIOException: Boolean = false, includeMockServerInTracingOrigins: Boolean = true): WebClient {
Expand Down
56 changes: 32 additions & 24 deletions sentry/api/sentry.api
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,6 +30,7 @@ public final class io/sentry/Baggage {
public fun setEnvironment (Ljava/lang/String;)V
public fun setPublicKey (Ljava/lang/String;)V
public fun setRelease (Ljava/lang/String;)V
public fun setSampleRate (Ljava/lang/String;)V
public fun setTraceId (Ljava/lang/String;)V
public fun setTransaction (Ljava/lang/String;)V
public fun setUserId (Ljava/lang/String;)V
Expand DownExpand Up@@ -473,6 +474,7 @@ public abstract interface class io/sentry/ITransaction : io/sentry/ISpan {
public abstract fun getEventId ()Lio/sentry/protocol/SentryId;
public abstract fun getLatestActiveSpan ()Lio/sentry/Span;
public abstract fun getName ()Ljava/lang/String;
public abstract fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public abstract fun getSpans ()Ljava/util/List;
public abstract fun isSampled ()Ljava/lang/Boolean;
public abstract fun scheduleFinish ()V
Expand DownExpand Up@@ -660,6 +662,7 @@ public final class io/sentry/NoOpTransaction : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -1386,6 +1389,7 @@ public final class io/sentry/SentryTracer : io/sentry/ITransaction {
public fun getLatestActiveSpan ()Lio/sentry/Span;
public fun getName ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1488,6 +1492,7 @@ public final class io/sentry/Span : io/sentry/ISpan {
public fun getHighPrecisionTimestamp ()Ljava/lang/Double;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanContext ()Lio/sentry/SpanContext;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStartTimestamp ()Ljava/util/Date;
Expand DownExpand Up@@ -1520,14 +1525,15 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
protected field status Lio/sentry/SpanStatus;
protected field tags Ljava/util/Map;
public fun <init> (Lio/sentry/SpanContext;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Ljava/lang/Boolean;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;Lio/sentry/SpanStatus;)V
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Ljava/lang/String;Lio/sentry/SpanId;Lio/sentry/TracesSamplingDecision;)V
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public fun getDescription ()Ljava/lang/String;
public fun getOperation ()Ljava/lang/String;
public fun getParentSpanId ()Lio/sentry/SpanId;
public fun getSampled ()Ljava/lang/Boolean;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpanId ()Lio/sentry/SpanId;
public fun getStatus ()Lio/sentry/SpanStatus;
public fun getTags ()Ljava/util/Map;
Expand All@@ -1537,6 +1543,7 @@ public class io/sentry/SpanContext : io/sentry/JsonSerializable, io/sentry/JsonU
public fun setDescription (Ljava/lang/String;)V
public fun setOperation (Ljava/lang/String;)V
public fun setSampled (Ljava/lang/Boolean;)V
public fun setSamplingDecision (Lio/sentry/TracesSamplingDecision;)V
public fun setStatus (Lio/sentry/SpanStatus;)V
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
public fun setUnknown (Ljava/util/Map;)V
Expand DownExpand Up@@ -1619,10 +1626,12 @@ public final class io/sentry/TraceContext : io/sentry/JsonSerializable, io/sentr
public fun getEnvironment ()Ljava/lang/String;
public fun getPublicKey ()Ljava/lang/String;
public fun getRelease ()Ljava/lang/String;
public fun getSampleRate ()Ljava/lang/String;
public fun getTraceId ()Lio/sentry/protocol/SentryId;
public fun getTransaction ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun getUser ()Lio/sentry/TraceContext$TraceContextUser;
public fun getUserId ()Ljava/lang/String;
public fun getUserSegment ()Ljava/lang/String;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
public fun toBaggage (Lio/sentry/ILogger;)Lio/sentry/Baggage;
Expand All@@ -1638,31 +1647,20 @@ public final class io/sentry/TraceContext$JsonKeys {
public static final field ENVIRONMENT Ljava/lang/String;
public static final field PUBLIC_KEY Ljava/lang/String;
public static final field RELEASE Ljava/lang/String;
public static final field SAMPLE_RATE Ljava/lang/String;
public static final field TRACE_ID Ljava/lang/String;
public static final field TRANSACTION Ljava/lang/String;
public static final field USER Ljava/lang/String;
public static final field USER_ID Ljava/lang/String;
public static final field USER_SEGMENT Ljava/lang/String;
public fun <init> ()V
}

public final class io/sentry/TraceContext$TraceContextUser : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public fun <init> (Lio/sentry/protocol/User;)V
public fun getId ()Ljava/lang/String;
public fun getSegment ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setUnknown (Ljava/util/Map;)V
}

public final class io/sentry/TraceContext$TraceContextUser$Deserializer : io/sentry/JsonDeserializer {
public fun <init> ()V
public fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Lio/sentry/TraceContext$TraceContextUser;
public synthetic fun deserialize (Lio/sentry/JsonObjectReader;Lio/sentry/ILogger;)Ljava/lang/Object;
}

public final class io/sentry/TraceContext$TraceContextUser$JsonKeys {
public static final field ID Ljava/lang/String;
public static final field SEGMENT Ljava/lang/String;
public fun <init> ()V
public final class io/sentry/TracesSamplingDecision {
public fun <init> (Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/Boolean;Ljava/lang/Double;)V
public fun getSampleRate ()Ljava/lang/Double;
public fun getSampled ()Ljava/lang/Boolean;
}

public final class io/sentry/TracingOrigins {
Expand All@@ -1673,10 +1671,11 @@ public final class io/sentry/TracingOrigins {

public final class io/sentry/TransactionContext : io/sentry/SpanContext {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/TracesSamplingDecision;)V
public static fun fromSentryTrace (Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;)Lio/sentry/TransactionContext;
public fun getName ()Ljava/lang/String;
public fun getParentSampled ()Ljava/lang/Boolean;
public fun getParentSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun setParentSampled (Ljava/lang/Boolean;)V
}

Expand DownExpand Up@@ -2826,6 +2825,7 @@ public final class io/sentry/protocol/SentryTransaction : io/sentry/SentryBaseEv
public fun <init> (Lio/sentry/SentryTracer;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;Ljava/util/List;Ljava/util/Map;)V
public fun getMeasurements ()Ljava/util/Map;
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
public fun getSpans ()Ljava/util/List;
public fun getStartTimestamp ()Ljava/lang/Double;
public fun getStatus ()Lio/sentry/SpanStatus;
Expand DownExpand Up@@ -3035,6 +3035,14 @@ public final class io/sentry/util/Platform {
public static fun isJvm ()Z
}

public final class io/sentry/util/SampleRateUtil {
public fun <init> ()V
public static fun isValidSampleRate (Ljava/lang/Double;)Z
public static fun isValidSampleRate (Ljava/lang/Double;Z)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;)Z
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
}

public final class io/sentry/util/StringUtils {
public static fun byteCountToString (J)Ljava/lang/String;
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;
Expand Down
12 changes: 8 additions & 4 deletions sentry/src/main/java/io/sentry/Baggage.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,11 +153,11 @@ private static String decode(final @NotNull String value) throws UnsupportedEnco
}

public void setTraceId(final @Nullable String traceId) {
set("sentry-traceid", traceId);
set("sentry-trace_id", traceId);
}

public void setPublicKey(final @Nullable String publicKey) {
set("sentry-publickey", publicKey);
set("sentry-public_key", publicKey);
}

public void setEnvironment(final @Nullable String environment) {
Expand All@@ -169,17 +169,21 @@ public void setRelease(final @Nullable String release) {
}

public void setUserId(final @Nullable String userId) {
set("sentry-userid", userId);
set("sentry-user_id", userId);
}

public void setUserSegment(final @Nullable String userSegment) {
set("sentry-usersegment", userSegment);
set("sentry-user_segment", userSegment);
}

public void setTransaction(final @Nullable String transaction) {
set("sentry-transaction", transaction);
}

public void setSampleRate(final @Nullable String sampleRate) {
set("sentry-sample_rate", sampleRate);
}

public void set(final @NotNull String key, final @Nullable String value) {
this.keyValues.put(key, value);
}
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/main/java/io/sentry/Hub.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -730,8 +730,8 @@ public void flush(long timeoutMillis) {
} else {
final SamplingContext samplingContext =
new SamplingContext(transactionContext, customSamplingContext);
boolean samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSampled(samplingDecision);
@NotNull TracesSamplingDecision samplingDecision = tracesSampler.sample(samplingContext);
transactionContext.setSamplingDecision(samplingDecision);

transaction =
new SentryTracer(
Expand All@@ -745,7 +745,7 @@ public void flush(long timeoutMillis) {

// The listener is called only if the transaction exists, as the transaction is needed to
// stop it
if (samplingDecision && options.isProfilingEnabled()) {
if (samplingDecision.getSampled() && options.isProfilingEnabled()) {
final ITransactionProfiler transactionProfiler = options.getTransactionProfiler();
transactionProfiler.onTransactionStart(transaction);
}
Expand Down
3 changes: 3 additions & 0 deletions sentry/src/main/java/io/sentry/ITransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ public interface ITransaction extends ISpan {
@Nullable
Boolean isSampled();

@Nullable
TracesSamplingDecision getSamplingDecision();

/**
* Returns the latest span that is not finished.
*
Expand Down
5 changes: 5 additions & 0 deletions sentry/src/main/java/io/sentry/NoOpTransaction.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,6 +136,11 @@ public void setTag(@NotNull String key, @NotNull String value) {}
return null;
}

@Override
public @Nullable TracesSamplingDecision getSamplingDecision() {
return null;
}

@Override
public void setData(@NotNull String key, @NotNull Object value) {}

Expand Down
41 changes: 37 additions & 4 deletions sentry/src/main/java/io/sentry/OutboxSender.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@
import io.sentry.util.HintUtils;
import io.sentry.util.LogUtils;
import io.sentry.util.Objects;
import io.sentry.util.SampleRateUtil;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
Expand DownExpand Up@@ -161,12 +162,17 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
continue;
}

// if there is no trace context header we also won't send it to Sentry
final @Nullable TraceContext traceContext = envelope.getHeader().getTraceContext();
if (transaction.getContexts().getTrace() != null) {
// Hint: Set sampled in order for the transaction not to be dropped, as this is a
// transient property.
transaction.getContexts().getTrace().setSampled(true);
// Hint: Set sampling decision in order for the transaction not to be dropped, as this
// is a transient property.
transaction
.getContexts()
.getTrace()
.setSamplingDecision(extractSamplingDecision(traceContext));
}
hub.captureTransaction(transaction, envelope.getHeader().getTraceContext(), hint);
hub.captureTransaction(transaction, traceContext, hint);
logItemCaptured(currentItem);

if (!waitFlush(hint)) {
Expand DownExpand Up@@ -216,6 +222,33 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @NotN
}
}

private @NotNull TracesSamplingDecision extractSamplingDecision(
final @Nullable TraceContext traceContext) {
if (traceContext != null) {
final @Nullable String sampleRateString = traceContext.getSampleRate();
if (sampleRateString != null) {
try {
final Double sampleRate = Double.parseDouble(sampleRateString);
if (!SampleRateUtil.isValidTracesSampleRate(sampleRate, false)) {
logger.log(
SentryLevel.ERROR,
"Invalid sample rate parsed from TraceContext: %s",
sampleRateString);
} else {
return new TracesSamplingDecision(true, sampleRate);
}
} catch (Exception e) {
logger.log(
SentryLevel.ERROR,
"Unable to parse sample rate from TraceContext: %s",
sampleRateString);
}
}
}

return new TracesSamplingDecision(true);
}

private void logEnvelopeItemNull(final @NotNull SentryEnvelopeItem item, int itemIndex) {
logger.log(
SentryLevel.ERROR,
Expand Down
Loading