Skip to content

Commit b5701eb

Browse files
committed
feat: dsn parsing
1 parent dbb0673 commit b5701eb

8 files changed

Lines changed: 155 additions & 20 deletions

File tree

sentry-android/src/main/java/io/sentry/android/ManifestMetadataReader.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
class ManifestMetadataReader {
1111

12-
private static final String DSN_KEY = "io.sentry.dsn";
13-
private static final String DEBUG_KEY = "io.sentry.debug";
12+
static final String DSN_KEY = "io.sentry.dsn";
13+
static final String DEBUG_KEY = "io.sentry.debug";
1414

1515
public static void applyMetadata(Context context, SentryOptions options) {
1616
try {
@@ -20,16 +20,17 @@ public static void applyMetadata(Context context, SentryOptions options) {
2020
.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
2121
Bundle metadata = app.metaData;
2222

23-
options.setDebug(metadata.getBoolean(DEBUG_KEY, options.isDebug()));
23+
if (metadata != null) {
24+
options.setDebug(metadata.getBoolean(DEBUG_KEY, options.isDebug()));
25+
String dsn = metadata.getString(DSN_KEY, null);
26+
if (dsn != null) {
27+
options.getLogger().log(SentryLevel.Debug, "DSN read: %s", dsn);
28+
options.setDsn(dsn);
29+
}
30+
}
2431
options
2532
.getLogger()
2633
.log(SentryLevel.Info, "Retrieving configuration from AndroidManifest.xml");
27-
28-
String dsn = metadata.getString(DSN_KEY, null);
29-
if (dsn != null) {
30-
options.getLogger().log(SentryLevel.Debug, "DSN read: %s", dsn);
31-
options.setDsn(dsn);
32-
}
3334
} catch (Exception e) {
3435
options
3536
.getLogger()

sentry-android/src/test/java/io/sentry/android/SentryInitProviderTest.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import androidx.test.core.app.ApplicationProvider
66
import androidx.test.ext.junit.runners.AndroidJUnit4
77
import io.sentry.Sentry
88
import org.junit.runner.RunWith
9-
import kotlin.test.BeforeTest
10-
import kotlin.test.Test
9+
import android.content.pm.PackageManager
10+
import kotlin.test.Ignore
1111
import kotlin.test.assertFalse
1212
import kotlin.test.assertTrue
13+
import kotlin.test.Test
14+
import kotlin.test.BeforeTest
1315
import kotlin.test.assertFailsWith
1416

1517
@RunWith(AndroidJUnit4::class)
@@ -33,12 +35,15 @@ class SentryInitProviderTest {
3335
}
3436

3537
@Test
36-
fun `when applicationId is defined, SDK initializes`() {
38+
@Ignore("Meta-data isn't holding the value.")
39+
fun `when applicationId is defined, dsn in meta-data, SDK initializes`() {
3740
val providerInfo = ProviderInfo()
3841

3942
assertFalse(Sentry.isEnabled())
4043
providerInfo.authority = BuildConfig.LIBRARY_PACKAGE_NAME + AUTHORITY
4144

45+
val applicationInfo = context.packageManager.getApplicationInfo(context.packageName, PackageManager.GET_META_DATA)
46+
applicationInfo.metaData.putString(ManifestMetadataReader.DSN_KEY, "https://key@sentry.io/123")
4247
sentryInitProvider.attachInfo(context, providerInfo)
4348

4449
assertTrue(Sentry.isEnabled())
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package io.sentry;
2+
3+
import java.net.URI;
4+
5+
final class Dsn {
6+
private final String projectId;
7+
private final String path;
8+
private final String secretKey;
9+
private final String publicKey;
10+
private final URI sentryUri;
11+
12+
/*
13+
/ The project ID which the authenticated user is bound to.
14+
*/
15+
public String getProjectId() {
16+
return projectId;
17+
}
18+
19+
/*
20+
/ An optional path of which Sentry is hosted
21+
*/
22+
public String getPath() {
23+
return path;
24+
}
25+
26+
/*
27+
/ The optional secret key to authenticate the SDK.
28+
*/
29+
public String getSecretKey() {
30+
return secretKey;
31+
}
32+
33+
/*
34+
/ The required public key to authenticate the SDK.
35+
*/
36+
public String getPublicKey() {
37+
return publicKey;
38+
}
39+
40+
/*
41+
/ The URI used to communicate with Sentry
42+
*/
43+
URI getSentryUri() {
44+
return sentryUri;
45+
}
46+
47+
public Dsn(String dsn) throws InvalidDsnException {
48+
try {
49+
URI uri = new URI(dsn);
50+
String userInfo = uri.getUserInfo();
51+
if (userInfo == null || userInfo.length() == 0) {
52+
throw new IllegalArgumentException("Invalid DSN: No public key provided.");
53+
}
54+
String[] keys = userInfo.split(":");
55+
publicKey = keys[0]; // TODO: test lack of delimiter returns whole value as first index
56+
if (publicKey == null || publicKey.length() == 0) {
57+
throw new IllegalArgumentException("Invalid DSN: No public key provided.");
58+
}
59+
secretKey = keys.length > 1 ? keys[1] : null;
60+
String uriPath = uri.getPath();
61+
int projectIdStart = uriPath.lastIndexOf("/") + 1;
62+
path = uriPath.substring(0, projectIdStart);
63+
projectId = uriPath.substring(projectIdStart);
64+
if (projectId == null || projectId.length() == 0) {
65+
throw new IllegalArgumentException("Invalid DSN: A Project Id is required.");
66+
}
67+
sentryUri =
68+
new URI(
69+
uri.getScheme(),
70+
null,
71+
uri.getHost(),
72+
uri.getPort(),
73+
path + "/api/" + projectId + "/store/",
74+
null,
75+
null);
76+
} catch (Exception e) {
77+
throw new InvalidDsnException(dsn, e);
78+
}
79+
}
80+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package io.sentry;
2+
3+
public final class InvalidDsnException extends RuntimeException {
4+
private static final long serialVersionUID = 412945154259913013L;
5+
private final String dsn;
6+
7+
public InvalidDsnException(String dsn) {
8+
this.dsn = dsn;
9+
}
10+
11+
public InvalidDsnException(String dsn, String message) {
12+
super(message);
13+
this.dsn = dsn;
14+
}
15+
16+
public InvalidDsnException(String dsn, String message, Throwable cause) {
17+
super(message, cause);
18+
this.dsn = dsn;
19+
}
20+
21+
public InvalidDsnException(String dsn, Throwable cause) {
22+
super(cause);
23+
this.dsn = dsn;
24+
}
25+
26+
public String getDsn() {
27+
return dsn;
28+
}
29+
}

sentry-core/src/main/java/io/sentry/Sentry.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.sentry;
22

33
import io.sentry.protocol.SentryId;
4+
import io.sentry.util.NotNull;
45

56
public final class Sentry {
67

@@ -16,13 +17,22 @@ public static void init() {
1617
init(new SentryOptions());
1718
}
1819

19-
public static void init(OptionsConfiguration optionsConfiguration) {
20+
public static void init(@NotNull OptionsConfiguration optionsConfiguration) {
2021
SentryOptions options = new SentryOptions();
21-
optionsConfiguration.configure(options);
22+
if (optionsConfiguration != null) {
23+
optionsConfiguration.configure(options);
24+
}
2225
init(options);
2326
}
2427

25-
static synchronized void init(SentryOptions options) {
28+
static synchronized void init(@NotNull SentryOptions options) {
29+
String dsn = options.getDsn();
30+
if (dsn == null || dsn.isEmpty()) {
31+
return;
32+
}
33+
34+
Dsn parsedDsn = new Dsn(dsn);
35+
2636
ILogger logger = options.getLogger();
2737
if (logger != null) {
2838
logger.log(SentryLevel.Info, "Initializing SDK with DSN: '%d'", options.getDsn());

sentry-core/src/main/java/io/sentry/SentryOptions.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.sentry;
22

3+
import io.sentry.util.NotNull;
34
import java.util.ArrayList;
45
import java.util.List;
56

@@ -10,7 +11,7 @@ public class SentryOptions {
1011

1112
private String dsn;
1213
private boolean debug;
13-
private ILogger logger = NoOpLogger.getInstance();
14+
private @NotNull ILogger logger = NoOpLogger.getInstance();
1415
private SentryLevel diagnosticLevel = DEFAULT_DIAGNOSTIC_LEVEL;
1516

1617
public void addEventProcessor(EventProcessor eventProcessor) {
@@ -37,7 +38,7 @@ public void setDebug(boolean debug) {
3738
this.debug = debug;
3839
}
3940

40-
public ILogger getLogger() {
41+
public @NotNull ILogger getLogger() {
4142
return logger;
4243
}
4344

sentry-core/src/main/java/io/sentry/protocol/SentryId.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
import java.util.UUID;
44

5-
public class SentryId {
5+
public final class SentryId {
66
private final UUID uuid;
77

8-
public static final SentryId EMPTY_ID =
9-
new SentryId(UUID.fromString("00000000-0000-0000-0000-000000000000"));
8+
public static final SentryId EMPTY_ID = new SentryId(new UUID(0, 0));
109

1110
public SentryId() {
1211
this(null);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.sentry.util;
2+
3+
import java.lang.annotation.Documented;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
7+
/** Indicates that an instance on the given position cannot be null. */
8+
@Documented
9+
@Retention(RetentionPolicy.CLASS)
10+
public @interface NotNull {}

0 commit comments

Comments
 (0)