Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Isolate cached events with hashed dsn subfolder #2038

Merged
merged 12 commits into from May 19, 2022
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,10 @@
- Allow setting SDK info (name & version) in manifest ([#2016](https://github.com/getsentry/sentry-java/pull/2016))
- Allow setting native Android SDK name during build ([#2035](https://github.com/getsentry/sentry-java/pull/2035))

### Fixes

- Isolate cached events with hashed DSN subfolder ([#2038](https://github.com/getsentry/sentry-java/pull/2038))

### Changed

- Update sentry-native to 0.4.17 ([#2033](https://github.com/getsentry/sentry-java/pull/2033))
Expand Down
Expand Up @@ -299,9 +299,7 @@ private static void readDefaultOptionValues(
private static void initializeCacheDirs(
final @NotNull Context context, final @NotNull SentryAndroidOptions options) {
final File cacheDir = new File(context.getCacheDir(), "sentry");
marandaneto marked this conversation as resolved.
Show resolved Hide resolved
final File profilingTracesDir = new File(cacheDir, "profiling_traces");
options.setCacheDirPath(cacheDir.getAbsolutePath());
options.setProfilingTracesDirPath(profilingTracesDir.getAbsolutePath());
}

private static boolean isNdkAvailable(final @NotNull BuildInfoProvider buildInfoProvider) {
Expand Down
Expand Up @@ -46,7 +46,7 @@
android:exported="false" />

<!-- NOTE: Replace the test DSN below with YOUR OWN DSN to see the events from this app in your Sentry project/dashboard-->
<meta-data android:name="io.sentry.dsn" android:value="https://1053864c67cc410aa1ffc9701bd6f93d@o447951.ingest.sentry.io/5428559" />
<!-- <meta-data android:name="io.sentry.dsn" android:value="https://1053864c67cc410aa1ffc9701bd6f93d@o447951.ingest.sentry.io/5428559" />-->

<!-- how to enable Sentry's debug mode-->
<meta-data android:name="io.sentry.debug" android:value="${sentryDebug}" />
Expand All @@ -64,7 +64,7 @@
<!-- <meta-data android:name="io.sentry.anr.enable" android:value="false" />-->

<!-- how to disable the auto-init-->
<!-- <meta-data android:name="io.sentry.auto-init" android:value="false" />-->
<meta-data android:name="io.sentry.auto-init" android:value="false" />

<!-- how to disable the NDK-->
<!-- <meta-data android:name="io.sentry.ndk.enable" android:value="false" />-->
Expand Down
Expand Up @@ -2,6 +2,7 @@

import android.app.Application;
import android.os.StrictMode;
import io.sentry.android.core.SentryAndroid;

/** Apps. main Application. */
public class MyApplication extends Application {
Expand All @@ -13,17 +14,12 @@ public void onCreate() {

// Example how to initialize the SDK manually which allows access to SentryOptions callbacks.
// Make sure you disable the auto init via manifest meta-data: io.sentry.auto-init=false
// SentryAndroid.init(
// this,
// options -> {
// /*
// use options, for example, to add a beforeSend callback:
//
// options.setBeforeSend((event, hint) -> {
// process event
// });
// */
// });
SentryAndroid.init(
this,
options -> {
options.setDsn(
"https://1053864c67cc410aa1ffc9701bd6f93d@o447951.ingest.sentry.io/5428559");
});
}

private void strictMode() {
Expand Down
79 changes: 61 additions & 18 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Expand Up @@ -11,6 +11,10 @@
import io.sentry.transport.NoOpTransportGate;
import io.sentry.util.Platform;
import java.io.File;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
Expand All @@ -33,6 +37,8 @@ public class SentryOptions {
/** Default Log level if not specified Default is DEBUG */
static final SentryLevel DEFAULT_DIAGNOSTIC_LEVEL = SentryLevel.DEBUG;

private static final Charset UTF_8 = Charset.forName("UTF-8");

/**
* Are callbacks that run for every event. They can either return a new event which in most cases
* means just adding data OR return null in case the event will be dropped and not sent.
Expand All @@ -55,6 +61,9 @@ public class SentryOptions {
*/
private @Nullable String dsn;

/** dsnHash is used as a subfolder of cacheDirPath to isolate events when rotating DSNs */
private @Nullable String dsnHash;

/**
* Controls how many seconds to wait before shutting down. Sentry SDKs send events from a
* background queue and this queue is given a certain amount to drain pending events Default is
Expand Down Expand Up @@ -295,9 +304,6 @@ public class SentryOptions {
/** Control if profiling is enabled or not for transactions */
private boolean profilingEnabled = false;

/** The cache dir. path for caching profiling traces */
private @Nullable String profilingTracesDirPath;

/** Max trace file size in bytes. */
private long maxTraceFileSize = 5 * 1024 * 1024;

Expand Down Expand Up @@ -374,8 +380,46 @@ public void addIntegration(@NotNull Integration integration) {
*
* @param dsn the DSN
*/
public void setDsn(@Nullable String dsn) {
public void setDsn(final @Nullable String dsn) {
this.dsn = dsn;

dsnHash = calculateHashedDsn(this.dsn);
}

private @Nullable String calculateHashedDsn(final @Nullable String dsn) {
if (dsn == null || dsn.isEmpty()) {
return null;
}

try {
// getInstance() method is called with algorithm SHA-1
marandaneto marked this conversation as resolved.
Show resolved Hide resolved
final MessageDigest md = MessageDigest.getInstance("SHA-1");
marandaneto marked this conversation as resolved.
Show resolved Hide resolved

// digest() method is called
// to calculate message digest of the input string
// returned as array of byte
final byte[] messageDigest = md.digest(dsn.getBytes(UTF_8));

// Convert byte array into signum representation
final BigInteger no = new BigInteger(1, messageDigest);

// Convert message digest into hex value
String hashtext = no.toString(16);

// Add preceding 0s to make it 32 bit
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}

// return the HashText
return hashtext;
marandaneto marked this conversation as resolved.
Show resolved Hide resolved
}

// For specifying wrong message digest algorithms
catch (NoSuchAlgorithmException e) {
logger.log(SentryLevel.INFO, "dsn: %s could not calculate hash", e, dsn);
}
return null;
}

/**
Expand Down Expand Up @@ -597,7 +641,10 @@ public void setBeforeBreadcrumb(@Nullable BeforeBreadcrumbCallback beforeBreadcr
* @return the cache dir. path or null if not set
*/
public @Nullable String getCacheDirPath() {
return cacheDirPath;
if (cacheDirPath == null || cacheDirPath.isEmpty()) {
return null;
}
return new File(cacheDirPath, dsnHash != null ? dsnHash : "").getAbsolutePath();
}

/**
Expand All @@ -606,18 +653,19 @@ public void setBeforeBreadcrumb(@Nullable BeforeBreadcrumbCallback beforeBreadcr
* @return the outbox path or null if not set
*/
public @Nullable String getOutboxPath() {
final String cacheDirPath = getCacheDirPath();
if (cacheDirPath == null || cacheDirPath.isEmpty()) {
return null;
}
return cacheDirPath + File.separator + "outbox";
return new File(cacheDirPath, "outbox").getAbsolutePath();
}

/**
* Sets the cache dir. path
*
* @param cacheDirPath the cache dir. path
*/
public void setCacheDirPath(@Nullable String cacheDirPath) {
public void setCacheDirPath(final @Nullable String cacheDirPath) {
this.cacheDirPath = cacheDirPath;
}

Expand Down Expand Up @@ -1278,7 +1326,7 @@ public long getMaxAttachmentSize() {

/**
* Sets the max attachment size for each attachment in bytes. Default is 20 MiB. Please also check
* the maximum attachment size of Relay to make sure your attachments don't get discarded there:
* the maximum attachment size of Relay to make sure your attachments don't getdiscarded there:
* https://docs.sentry.io/product/relay/options/
*
* @param maxAttachmentSize the max attachment size in bytes.
Expand Down Expand Up @@ -1486,16 +1534,11 @@ public void setProfilingEnabled(boolean profilingEnabled) {
* @return the profiling traces dir. path or null if not set
*/
public @Nullable String getProfilingTracesDirPath() {
return profilingTracesDirPath;
}

/**
* Sets the profiling traces dir. path
*
* @param profilingTracesDirPath the profiling traces dir. path
*/
public void setProfilingTracesDirPath(@Nullable String profilingTracesDirPath) {
this.profilingTracesDirPath = profilingTracesDirPath;
final String cacheDirPath = getCacheDirPath();
marandaneto marked this conversation as resolved.
Show resolved Hide resolved
if (cacheDirPath == null || cacheDirPath.isEmpty()) {
return null;
}
return new File(cacheDirPath, "profiling_traces").getAbsolutePath();
}

/**
Expand Down