sentry-java icon indicating copy to clipboard operation
sentry-java copied to clipboard

JDBC transactions not logged in queries

Open peterdk opened this issue 1 year ago • 8 comments

Integration

sentry-jdbc

Java Version

18

Version

7.10.0

Steps to Reproduce

I use Ktor for a API and am looking into a tool that can help monitor performance. I saw that Sentry supports JDBC queries, and that is something I am looking for.

I added to my build.gradle.kts:

id("io.sentry.jvm.gradle") version "4.7.1"

implementation("io.sentry:sentry-jdbc:7.10.0")
implementation("p6spy:p6spy:3.9.1")

sentry {
    includeSourceContext = false
    org = "foo"
    projectName = "bar"
    authToken = System.getenv("SENTRY_AUTH_TOKEN")
    tracingInstrumentation {
        enabled = true
    }
    autoInstallation {
        enabled = true
    }
}

My DB setup logic:

 val db = Database.connect(P6DataSource(MysqlDataSource().apply {
        setURL("jdbc:mysql://$dbHost/$dbName?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&rewriteBatchedInserts=true&rewriteBatchedStatements=true&batchSize=5000")
        user = dbUser
        password = dbPass
    }))

Sentry init:

 Sentry.init { options ->
        options.dsn = "foo"
        options.tracesSampleRate = 1.0
        options.isDebug = true
        options.enableTracing = true
        options.isEnableMetrics = true
    }

I then instrumented one of the endpoints by wrapping the logic:

 val transaction = Sentry.startTransaction(name, operation)
    try {
        action()
    } catch (e: Exception) {
        transaction.throwable = e
        transaction.status = SpanStatus.INTERNAL_ERROR
        throw e
    } finally {
        transaction.finish()
    }

Expected Result

I expect that Queries section of Sentry is now being filled, but I only see data in Traces. In the logging I don't see anything related to JDBC. In the docs I don't see anything else that I would need to setup.

I am on the developer plan, but from what I see the queries section should be available until half July or so. Or am I already required to have a business plan?

Actual Result

I only see data in Traces, not in Queries and also not in Requests.

I do see the transactions logged in spy.log, so p6spy is working.

Sentry logging after a call happens:

DEBUG: Capturing transaction: ad39f934a059455e8a72d822ae3605c3
DEBUG: Serializing object: {
	"transaction": "foo",
	"start_timestamp": 1718554044.114437,
	"timestamp": 1718554044.445066,
	"type": "transaction",
	"transaction_info": {
		"source": "custom"
	},
	"event_id": "ad39f934a059455e8a72d822ae3605c3",
	"contexts": {
		"runtime": {
			"name": "Amazon.com Inc.",
			"version": "18.0.2"
		},
		"trace": {
			"trace_id": "b3de03059f8648acbc33f36138d887b8",
			"span_id": "dd688cd36b64435e",
			"op": "request",
			"origin": "manual"
		}
	},
	"sdk": {
		"name": "sentry.java",
		"version": "7.10.0",
		"packages": [
			{
				"name": "maven:io.sentry:sentry",
				"version": "7.10.0"
			},
			{
				"name": "maven:io.sentry:sentry-jdbc",
				"version": "7.10.0"
			}
		],
		"integrations": [
			"UncaughtExceptionHandler",
			"ShutdownHook",
			"JDBC"
		]
	},
	"environment": "production",
	"platform": "java",
	"user": {
		"ip_address": "{{auto}}"
	},
	"server_name": "localhost"
}```

peterdk avatar Jun 16 '24 16:06 peterdk

Hello @peterdk, can you confirm io.sentry.jdbc.SentryJdbcEventListener is actually being invoked in your setup? If so, does it find a valid transaction/span to create a child under?

adinauer avatar Jun 17 '24 11:06 adinauer

@adinauer I can check, but how would I do that? I don't know if you can set breakpoints on library code? I'll try.

peterdk avatar Jun 17 '24 11:06 peterdk

@Override
  public void onBeforeAnyExecute(final @NotNull StatementInformation statementInformation) {
    final ISpan parent = hub.getSpan();
    if (parent != null && !parent.isNoOp()) {
      final ISpan span = parent.startChild("db.query", statementInformation.getSql());
      CURRENT_SPAN.set(span);
      span.getSpanContext().setOrigin(TRACE_ORIGIN);
    }
  }

parent seems to be null, the breakpoint on span never triggers after the parent breakpoint.

I do use Kotlin and ktor, so it's inside a coroutine. Already tried wrapping the main trace fun content with

withContext(SentryContext()) {`

and also the DB call parent functions all as suspend, but no changes.

peterdk avatar Jun 17 '24 11:06 peterdk

Also only wrapping non suspend functions part (including the DB calls) with a Transaction doesn't do anything.

peterdk avatar Jun 17 '24 11:06 peterdk

Am I doing something wrong the the trace wrapping logic? span is empty, right after transaction start

 val transaction = Sentry.startTransaction(name, operation)
        try {
            val hub = Sentry.getCurrentHub() //exists
            val span = hub.span //null
           doSomething()

I would expect that span would not be null?

peterdk avatar Jun 17 '24 11:06 peterdk

Can you please take a look at https://docs.sentry.io/platforms/java/tracing/instrumentation/custom-instrumentation/#create-transaction-bound-to-the-current-scope and see if that helps?

Sorry, I guess this isn't too intuitive.

adinauer avatar Jun 17 '24 12:06 adinauer

@adinauer I was just looking into that indeed. The span is not empty now! And indeed the JDBC breakpoint triggers and I do get query data now in Sentry! Great.

Maybe improve the docs a bit?

peterdk avatar Jun 17 '24 12:06 peterdk

We'll discuss whether it makes sense to have separate methods in the future that make this more clear. We're currently changing lots of things in the SDK for v8 and this is one of the things on the list.

adinauer avatar Jun 17 '24 12:06 adinauer

Created https://github.com/getsentry/sentry-java/issues/3760 to track docs improvements. Currently there's no plan to add separate methods but a new performance API is in the works.

adinauer avatar Oct 04 '24 08:10 adinauer