Skip to content

Commit 0e7f46b

Browse files
committed
refactor: Update Sentry and rewrite integrations
1 parent 13fad82 commit 0e7f46b

4 files changed

Lines changed: 85 additions & 149 deletions

File tree

buildSrc/src/main/kotlin/dependencies.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@file:Suppress("ClassName")
22

3-
const val sentry = "io.sentry:sentry:1.7.29"
3+
const val sentry = "io.sentry:sentry:4.0.0-beta.1"
44

55
object fuel {
66
private const val group = "com.github.kittinunf.fuel"

inspector-sentry-reporter/src/main/kotlin/SentryReporter.kt

Lines changed: 37 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,93 @@
11
package ru.endlesscode.inspector.report
22

3-
import io.sentry.DefaultSentryClientFactory
4-
import io.sentry.DefaultSentryClientFactory.IN_APP_FRAMES_OPTION
5-
import io.sentry.DefaultSentryClientFactory.UNCAUGHT_HANDLER_ENABLED_OPTION
63
import io.sentry.Sentry
7-
import io.sentry.SentryClientFactory
8-
import io.sentry.connection.EventSendCallback
9-
import io.sentry.event.Event
10-
import io.sentry.event.EventBuilder
11-
import io.sentry.event.UserBuilder
12-
import io.sentry.event.interfaces.ExceptionInterface
13-
import java.util.*
4+
import io.sentry.SentryEvent
5+
import io.sentry.protocol.Message
6+
import io.sentry.protocol.User
147

158
/**
169
* Reporter that sends reports to Sentry.
1710
*/
1811
public class SentryReporter private constructor(
1912
dsn: String,
20-
factory: SentryClientFactory,
2113
override val focus: ReporterFocus,
2214
private val fields: Set<ReportField>,
2315
) : Reporter {
2416

2517
override var enabled: Boolean = true
2618

27-
private val sentry = Sentry.init(dsn, factory)
28-
2919
private val handlers = CompoundReportHandler()
30-
private val pendingExceptions = mutableMapOf<UUID, ExceptionData>()
3120

3221
init {
33-
sentry.addEventSendCallback(object : EventSendCallback {
34-
override fun onSuccess(event: Event) {
35-
val reportedException = removePendingException(event.id)
36-
if (reportedException != null) {
37-
handlers.onSuccess(event.message, reportedException)
38-
}
39-
}
22+
Sentry.init { options ->
23+
options.dsn = dsn
24+
options.release = focus.environment.appVersion
25+
options.addInAppInclude(focus.focusedPackage)
26+
options.enableUncaughtExceptionHandler = false
27+
}
4028

41-
override fun onFailure(event: Event, exception: Exception) {
42-
val isErrorReport = removePendingException(event.id) != null
43-
if (isErrorReport) {
44-
handlers.onError(exception)
45-
}
29+
Sentry.configureScope { scope ->
30+
scope.user = User().apply {
31+
id = focus.environment.reporterId
4632
}
47-
})
48-
49-
sentry.release = focus.environment.appVersion
50-
sentry.context.user = UserBuilder()
51-
.setId(focus.environment.reporterId)
52-
.build()
33+
}
5334
}
5435

5536
override fun addHandler(handler: ReportHandler) {
5637
handlers.addHandler(handler)
5738
}
5839

5940
override fun report(message: String, exception: Exception, async: Boolean) {
60-
val exceptionData = ExceptionData(exception)
61-
handlers.beforeReport(message, exceptionData)
62-
63-
val eventBuilder = EventBuilder()
64-
.withMessage(message)
65-
.withSentryInterface(ExceptionInterface(exception))
66-
.apply {
67-
fields.asSequence()
68-
.filter(ReportField::show)
69-
.forEach { withExtra(it.name, it.value) }
70-
}
41+
val sentryMessage = Message().apply {
42+
formatted = message
43+
}
7144

72-
sentry.sendEvent(eventBuilder)
73-
addPendingException(sentry.context.lastEventId, exceptionData)
74-
}
45+
val event = SentryEvent(exception).apply {
46+
setMessage(sentryMessage)
47+
fields.asSequence()
48+
.filter(ReportField::show)
49+
.forEach { setExtra(it.name, it.value) }
50+
}
51+
Sentry.captureEvent(event)
7552

76-
private fun addPendingException(id: UUID, exception: ExceptionData) {
77-
pendingExceptions[id] = exception
53+
// We can't track errors on error sending. So we just assume that report was sent successfully.
54+
val exceptionData = ExceptionData(exception)
55+
handlers.onSuccess(message, exceptionData)
7856
}
7957

80-
private fun removePendingException(id: UUID): ExceptionData? = pendingExceptions.remove(id)
81-
8258
/**
8359
* Builder that should be used to build [SentryReporter].
8460
*
8561
* You should specify DSN with one of [setDataSourceName] methods.
8662
*/
8763
public class Builder : Reporter.Builder() {
8864

89-
private var clientFactory: SentryClientFactory? = null
9065
private var dsn: String = ""
91-
private var options: Map<String, String> = emptyMap()
9266

9367
/**
94-
* Set [SentryClientFactory], that will be used to create SentryClient.
68+
* Set Sentry [dsn].
69+
* See: [Setting the DSN](https://docs.sentry.io/clients/java/config/#setting-the-dsn)
9570
*/
96-
public fun setClientFactory(clientFactory: SentryClientFactory): Builder {
97-
this.clientFactory = clientFactory
71+
public fun setDsn(dsn: String): Builder {
72+
this.dsn = dsn
9873
return this
9974
}
10075

101-
/**
102-
* Set Sentry [dsn] with one string.
103-
* See: https://docs.sentry.io/clients/java/config/#setting-the-dsn
104-
*/
76+
@Deprecated("Use setDsn", ReplaceWith("setDsn(dsn)"))
10577
public fun setDataSourceName(dsn: String): Builder {
106-
this.dsn = dsn
107-
return this
78+
return setDsn(dsn)
10879
}
10980

110-
/**
111-
* Set Sentry [dsn] built from separated parts.
112-
* See: https://docs.sentry.io/clients/java/config/#setting-the-dsn
113-
*/
11481
@JvmOverloads
82+
@Deprecated("Use setDsn")
11583
public fun setDataSourceName(
11684
publicKey: String,
11785
projectId: String,
11886
protocol: String = "https",
11987
host: String = "sentry.io",
12088
port: String = "",
121-
options: Map<String, String> = emptyMap(),
12289
): Builder {
123-
this.dsn = buildString {
90+
val dsn = buildString {
12491
append(protocol)
12592
append("://")
12693
append(publicKey)
@@ -131,31 +98,19 @@ public class SentryReporter private constructor(
13198
append(projectId)
13299
}
133100

134-
this.options = options
135-
136-
return this
101+
return setDsn(dsn)
137102
}
138103

139104
/**
140105
* Build configured [SentryReporter].
141106
*/
142107
override fun build(): Reporter {
143108
require(dsn.isNotBlank()) {
144-
"You should specify DSN with method `setDataSourceName(...)` and it shouldn't be blank."
109+
"You should specify DSN with method `setDsn(...)` and it shouldn't be blank."
145110
}
146111

147-
val options = mutableMapOf(
148-
IN_APP_FRAMES_OPTION to focus.focusedPackage,
149-
UNCAUGHT_HANDLER_ENABLED_OPTION to "false"
150-
)
151-
options.putAll(this.options)
152-
153-
val optionsString = options.asSequence()
154-
.joinToString(prefix = "?", separator = "&") { (key, value) -> "$key=$value" }
155-
156112
return SentryReporter(
157-
dsn = "$dsn$optionsString",
158-
factory = clientFactory ?: DefaultSentryClientFactory(),
113+
dsn = dsn,
159114
focus = focus,
160115
fields = fields
161116
)

sentry-bukkit/src/main/kotlin/BukkitPluginSentryClientFactory.kt

Lines changed: 0 additions & 66 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package ru.endlesscode.inspector.sentry.bukkit
2+
3+
import io.sentry.IHub
4+
import io.sentry.Integration
5+
import io.sentry.SentryOptions
6+
import org.bukkit.Server
7+
import org.bukkit.plugin.Plugin
8+
9+
/**
10+
* SentryClientFactory that handles Bukkit-specific construction, like logging
11+
* server and plugin information.
12+
*/
13+
public class SentryBukkitIntegration(private val plugin: Plugin) : Integration {
14+
15+
public companion object {
16+
private val KNOWN_SERVERS = listOf("Paper", "Spigot", "CraftBukkit", "BungeeCord", "WaterFall")
17+
}
18+
19+
private val Server.knownName: String
20+
get() = (KNOWN_SERVERS.find { it in version } ?: "Unknown").toLowerCase()
21+
private val Server.minecraftVersion: String
22+
get() = bukkitVersion.substringBefore('-')
23+
24+
override fun register(hub: IHub, options: SentryOptions) {
25+
options.sdkVersion?.addIntegration("bukkit")
26+
options.serverName = plugin.server.knownName
27+
options.setTag("minecraft", plugin.server.minecraftVersion)
28+
options.setBeforeSend { event, _ ->
29+
event.contexts.putAll(getContexts())
30+
event
31+
}
32+
}
33+
34+
private fun getContexts(): Map<String, Map<String, Any>> {
35+
val serverMap = mapOf(
36+
"Name" to plugin.server.knownName,
37+
"Version" to plugin.server.version,
38+
"Minecraft Version" to plugin.server.minecraftVersion
39+
)
40+
val pluginMap = mapOf(
41+
"Name" to plugin.description.name,
42+
"Version" to plugin.description.version,
43+
"API Version" to plugin.description.apiVersion.toString()
44+
)
45+
return mapOf("server" to serverMap, "plugin" to pluginMap)
46+
}
47+
}

0 commit comments

Comments
 (0)