Configuration
In addition to configuring your database connections in application.conf you can also set some global options in this file or through system properties (see the Typesafe Config documentation for details). These are the available options and their default values as defined in Slick’s own reference.conf:
source# These settings are read by slick.util.SlickConfig
slick {
# Use ANSI color sequences in tree dumps (as used in log messages and
# exceptions of type SlickTreeException).
ansiDump = false
# Use Unicode box characters in tree and table dumps (as used in log
# messages). If this option is not enabled, ASCII approximations are used
# instead.
unicodeDump = false
# Dump individual "Select" and "Ref" nodes instead of combining them into a
# single "Path" element when creating a tree dump (as used in log messages
# and exceptions of type SlickTreeException).
dumpPaths = false
# Use multi-line, indented formatting for SQL statements. If not enabled,
# statements are generated without any linebreaks or indentation. This
# option applies to all generated statements (but not to the Plain SQL API).
sqlIndent = false
# Verify types after each query compiler phase. This is useful for debugging
# the query compiler but should generally not be enabled in production
# environments because it makes query compilation considerably slower.
verifyTypes = false
# Detect unnecessary rebuilding of the AST after every query compiler phase.
# This is useful for debugging the query compiler. Query compilation
# performance is negatively affected by this if phase logging is enabled.
detectRebuild = false
}
# Profile-specific settings for MySQLProfile
slick.jdbc.MySQLProfile {
# The default SQL type for strings without an explicit size limit.
# When set to null / undefined, pick "TEXT" where possible, otherwise fall back
# to "VARCHAR(254)"
defaultStringType = null
}
# Profile-specific settings for SQLServerProfile
slick.jdbc.SQLServerProfile {
# The default SQL type for strings without an explicit size limit.
# When set to null / undefined, pick "TEXT" where possible, otherwise fall back to "VARCHAR(254)"
defaultStringType = null
}
Logging
Slick uses SLF4J for logging. How to configure loggers and appenders depends on the actual logging framework that you use in your application. The following Logback configuration is used internally for testing and debugging of Slick. It contains a list of all loggers that are used by Slick for debug output:
source<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>*** \(%logger{30}\)%green(%X{debugId}) %msg%n</pattern>
</encoder>
</appender>
<root level="${log.root:-info}">
<appender-ref ref="STDOUT" />
</root>
<logger name="slick.basic.BasicBackend.action" level="${log.action:-info}" />
<logger name="slick.basic.BasicBackend.stream" level="${log.stream:-info}" />
<logger name="slick.compiler" level="${log.qcomp:-info}" />
<logger name="slick.compiler.QueryCompiler" level="${log.qcomp.phases:-inherited}" />
<logger name="slick.compiler.QueryCompilerBenchmark" level="${log.qcomp.bench:-inherited}" />
<logger name="slick.compiler.Inline" level="${log.qcomp.inline:-inherited}" />
<logger name="slick.compiler.AssignUniqueSymbols" level="${log.qcomp.assignUniqueSymbols:-inherited}" />
<logger name="slick.compiler.InferTypes" level="${log.qcomp.inferTypes:-inherited}" />
<logger name="slick.compiler.ExpandTables" level="${log.qcomp.expandTables:-inherited}" />
<logger name="slick.compiler.EmulateOuterJoins" level="${log.qcomp.emulateOuterJoins:-inherited}" />
<logger name="slick.compiler.ForceOuterBinds" level="${log.qcomp.forceOuterBinds:-inherited}" />
<logger name="slick.compiler.RemoveMappedTypes" level="${log.qcomp.removeMappedTypes:-inherited}" />
<logger name="slick.compiler.CreateResultSetMapping" level="${log.qcomp.createResultSetMapping:-inherited}" />
<logger name="slick.compiler.ExpandSums" level="${log.qcomp.expandSums:-inherited}" />
<logger name="slick.compiler.ExpandRecords" level="${log.qcomp.expandRecords:-inherited}" />
<logger name="slick.compiler.ExpandConditionals" level="${log.qcomp.expandConditionals:-inherited}" />
<logger name="slick.compiler.FlattenProjections" level="${log.qcomp.flattenProjections:-inherited}" />
<logger name="slick.compiler.CreateAggregates" level="${log.qcomp.createAggregates:-inherited}" />
<logger name="slick.compiler.RewriteJoins" level="${log.qcomp.rewriteJoins:-inherited}" />
<logger name="slick.compiler.RemoveTakeDrop" level="${log.qcomp.removeTakeDrop:-inherited}" />
<logger name="slick.compiler.ResolveZipJoins" level="${log.qcomp.resolveZipJoins:-inherited}" />
<logger name="slick.compiler.HoistClientOps" level="${log.qcomp.hoistClientOps:-inherited}" />
<logger name="slick.compiler.ReorderOperations" level="${log.qcomp.reorderOperations:-inherited}" />
<logger name="slick.compiler.MergeToComprehensions" level="${log.qcomp.mergeToComprehensions:-inherited}" />
<logger name="slick.compiler.OptimizeScalar" level="${log.qcomp.optimizeScalar:-inherited}" />
<logger name="slick.compiler.FixRowNumberOrdering" level="${log.qcomp.fixRowNumberOrdering:-inherited}" />
<logger name="slick.compiler.PruneProjections" level="${log.qcomp.pruneProjections:-inherited}" />
<logger name="slick.compiler.RewriteDistinct" level="${log.qcomp.rewriteDistinct:-inherited}" />
<logger name="slick.compiler.RewriteBooleans" level="${log.qcomp.rewriteBooleans:-inherited}" />
<logger name="slick.compiler.SpecializeParameters" level="${log.qcomp.specializeParameters:-inherited}" />
<logger name="slick.compiler.CodeGen" level="${log.qcomp.codeGen:-inherited}" />
<logger name="slick.compiler.RemoveFieldNames" level="${log.qcomp.removeFieldNames:-inherited}" />
<logger name="slick.compiler.InsertCompiler" level="${log.qcomp.insertCompiler:-inherited}" />
<logger name="slick.compiler.VerifyTypes" level="${log.qcomp.verifyTypes:-inherited}" />
<logger name="slick.jdbc.DriverDataSource" level="${log.jdbc.driver:-info}" />
<logger name="slick.jdbc.JdbcBackend.statement" level="${log.jdbc.statement:-info}" />
<logger name="slick.jdbc.JdbcBackend.parameter" level="${log.jdbc.parameter:-info}" />
<logger name="slick.jdbc.JdbcBackend.benchmark" level="${log.jdbc.bench:-info}" />
<logger name="slick.jdbc.StatementInvoker.result" level="${log.jdbc.result:-info}" />
<logger name="slick.jdbc.JdbcModelBuilder" level="${log.createModel:-info}" />
<logger name="slick.memory.HeapBackend" level="${log.heap:-inherited}" />
<logger name="slick.memory.QueryInterpreter" level="${log.interpreter:-inherited}" />
<logger name="slick.relational.ResultConverterCompiler" level="${log.resultConverter:-inherited}" />
<logger name="slick.util.AsyncExecutor" level="${log.asyncExecutor:-inherited}" />
</configuration>Messages on WARNING and ERROR levels may also be emitted by loggers that are not explicitly mentioned in this configuration.
You should generally enable logging for the root package slick at level INFO (currently unused) or WARNING. Debug logging should only be enabled selectively for individual loggers, otherwise you will get a huge amount of log output.
Logback logs everything at DEBUG level when it finds no configuration file, so put a logback.xml on the classpath of the program that uses Slick (for the code generator, on the classpath of the project that runs it).
The following loggers are particularly interesting:
-
slick.basic.BasicBackend.action: Shows the execution of every Database I/O Action. -
slick.basic.BasicBackend.timing: Shows how long each SQL action took, on one line together with its SQL, e.g.SQL action took 1.234 ms: select "NAME" from "USERS", so you can see which statement took how long even when many actions run concurrently. Failed actions are logged asfailed after. The time is measured around the whole action, so it can include waiting for a connection. Synchronous actions combined with>>,DBIO.seq,zip,asTryand similar combinators run as one fused action, which is logged on one line with its total time and all its statements, e.g.SQL action took 3.210 ms: select ...; insert .... Fordb.stream, the lineSQL stream opened after 1.234 ms: select ...covers opening the stream (running the query), not reading the rows. Nothing is measured unless this logger is enabled at debug level. This logger andslick.basic.BasicBackend.actionare written by the default action listener; if you install your own listener, combine it withActionListener.timingto keep the timing log. -
slick.compiler.QueryCompiler: Shows a dump of the AST after every phase of the query compiler when compiling a query. -
slick.jdbc.DriverDataSource: Shows information about JDBC drivers being loaded byDriverDataSource. Does not apply when using a connection pool unless you explicitly use a DriverDataSource as the source for the connection pool. -
slick.jdbc.JdbcBackend.statement: Shows all SQL statements which are executed. -
slick.jdbc.JdbcBackend.parameter: Shows bind variable contents (for supported types) of all SQL statements which are executed. -
slick.jdbc.JdbcBackend.statementAndParameter: Shows executed prepared inserts, updates and batch entries (but not queries) as rendered by the JDBC driver’sPreparedStatement.toString. For drivers that include the bound values there, this shows the SQL together with the values. -
slick.jdbc.JdbcBackend.benchmark: Shows execution times for SQL statements, without the SQL. Useslick.basic.BasicBackend.timingto see which statement took how long. -
slick.jdbc.StatementInvoker.result: Shows the first rows of the result set when a query is executed. Does not apply to streaming results.
Monitoring
Slick does not expose its own JMX bean in Slick 4. Observability is provided at two levels:
-
Connection pool (HikariCP): When a Database object has the
registerMbeansoption enabled, the HikariCP pool implementation registers JMX management beans. See the HikariCP monitoring documentation for details. -
Application runtime: Runtime-level metrics depend on the facade and runtime you use (for example, Cats Effect, ZIO, or framework-provided runtime tooling). Use your runtime’s standard observability integration (for example, Micrometer or Prometheus).
In addition to pool/runtime observability, Slick 4’s execution limits are configured directly on the database config section (for DatabaseConfig.forConfig / forProfileConfig):
maxConnections: maximum concurrent JDBC connections.maxInflightActions(default2 * maxConnections): maximum concurrently running DBIO chains.queueSize(default1000): maximum callers waiting for in-flight admission.inflightAdmissionTimeout(optional): max time waiting for an in-flight slot.connectionAcquireTimeout(optional): max time waiting for a connection slot.
For programmatic configs (forDataSource, forSource, forName, forURL) use ControlsConfig and .withControls instead of config-file keys:
DatabaseConfig.forDataSource(MyProfile, ds)
.withControls(ControlsConfig(maxConnections = 10, queueSize = 500))
When queueSize is exhausted, Slick rejects immediately with SlickException("DBIOAction queue full").
When configured timeout limits are exceeded, Slick fails with SlickException as well:
SlickException("Timed out waiting for inflight admission after ...")SlickException("Timed out waiting for connection slot after ...")
Slick exposes runtime concurrency counters through Database[F].controlStatus. The returned snapshot contains:
availableConnectionSlots: free connection slots in the connection arbiter.pendingConnectionSlots: callers currently waiting for a connection slot.availableAdmissionQueueSlots: free waiting-room slots before queue-full rejection.availableInflightSlots: free in-flight DBIO action slots.
These values are useful to distinguish pressure points: admission saturation, inflight saturation, or connection-slot contention.
The management bean names registered by HikariCP are qualified with the poolName from the database configuration, or the config path if poolName has not been set explicitly.
Example: Including the following configuration options in the database configuration
connectionPool = "HikariCP"
registerMbeans = true
poolName = "myDb"
results in these two HikariCP management beans being registered:
com.zaxxer.hikari:type=PoolConfig (myDb)com.zaxxer.hikari:type=Pool (myDb)