Skip to content

Debugging with `ksql.InjectLogger`

Vinícius Garcia edited this page Jul 18, 2023 · 4 revisions

When debugging it is sometimes useful to be able to see the exact query that is being sent to the database, for that KSQL allows you to inject a logger into the context used by the KSQL methods. This causes KSQL to log all the queries sent to the database.

You can either decide to use one of the two built-in loggers, by using:

  • ctx = ksql.InjectLogger(ctx, ksql.Logger)
  • ctx = ksql.InjectLogger(ctx, ksql.ErrorLogger)

Or you can create your own, by passing a custom function to InjectLogger, e.g.:

ctx := ksql.InjectLogger(ctx, func(ctx context.Context, values LogValues) {
	fmt.Println("the values are:", values.Query, values.Params, values.Err)
})

The short example below illustrates how this can be done, a more complete example is available on this file.

// After we inject a logger, all subsequent queries
// will use this logger.
//
// You can also inject the ksql.ErrorLogger if you only
// care about these logs when a query error happens.
ctx = ksql.InjectLogger(ctx, ksql.Logger)

// This logs: {"query":"CREATE TABLE IF NOT EXISTS users (\n\t  id INTEGER PRIMARY KEY,\n\t\tage INTEGER,\n\t\tname TEXT\n\t)","params":null}
_, err = db.Exec(ctx, `CREATE TABLE IF NOT EXISTS users (
  id INTEGER PRIMARY KEY,
	age INTEGER,
	name TEXT
)`)
if err != nil {
	panic(err.Error())
}

// This logs: {"query":"INSERT INTO `users` (`name`, `age`) VALUES (?, ?)","params":["Alison",22]}
var alison = User{
	Name: "Alison",
	Age:  22,
}
err = db.Insert(ctx, UsersTable, &alison)
if err != nil {
	panic(err.Error())
}

// This logs: {"query":"SELECT `id`, `name`, `age` FROM users LIMIT 10","params":null}
var users []User
err = db.Query(ctx, &users, "FROM users LIMIT 10")
if err != nil {
	panic(err.Error())
}

Why Injecting in the context?

The choice of injecting this logger on the context instead of just adding it as a config argument to the KSQL client, is that it gives the user a more fine grained control over what is logged and where.

For example we often just want to see the logs of a single query when debugging and this technique allows the user to inject the logger right before the function that is failing.

Another use-case is the possibility of having different loggers for different parts of your system: for routine queries, you might just want to log if an error happens, but for more sensitive parts you might prefer to always log the query even when there are no errors.