DotNET client usage
Chronicle uses connection strings to configure the .NET client. You can pass a connection string to ChronicleOptions or provide one when constructing a ChronicleClient.
Development defaults
Section titled “Development defaults”The ChronicleConnectionString.Development constant provides a pre-configured development connection string. Default constructors also use this value:
public static class ConnectionStringsDevelopmentDefaults{ public static ChronicleClient Create() { var options = new ChronicleOptions(); return new ChronicleClient(options); }}import io.cratis.chronicle.ChronicleClientimport io.cratis.chronicle.ChronicleOptions
fun createDevelopmentClient(): ChronicleClient { val options = ChronicleOptions.development() return ChronicleClient(options)}import io.cratis.chronicle.ChronicleOptions;import io.cratis.chronicle.java.BlockingChronicleClient;
class ConnectionStringsDevelopmentDefaults { BlockingChronicleClient create() { ChronicleOptions options = ChronicleOptions.development(); return BlockingChronicleClient.connect(options); }}defmodule MyApp.ConnectionStringsDevelopmentDefaults do @moduledoc false
def connection_string do Chronicle.Connections.ConnectionString.default() endendimport { ChronicleOptions } from '@cratis/chronicle';
// ChronicleOptions.development() points at the local dev kernel on chronicle://localhost:35000// using the built-in development client credentials.function createConnectionStringsDevelopmentDefaults(): ChronicleOptions { return ChronicleOptions.development();}This is equivalent to:
using Cratis.Chronicle.Connections;
public static class ConnectionStringsDevelopmentDefaultsEquivalent{ public static ChronicleClient CreateFromOptions() { var options = ChronicleOptions.FromDevelopmentConnectionString(); return new ChronicleClient(options); }
public static ChronicleClient CreateFromConnectionString() => new(ChronicleConnectionString.Development);}import io.cratis.chronicle.ChronicleClientimport io.cratis.chronicle.ChronicleOptionsimport io.cratis.chronicle.connection.ChronicleConnectionString
fun createFromOptions(): ChronicleClient = ChronicleClient(ChronicleOptions.development())
fun createFromConnectionString(): ChronicleClient = ChronicleClient(ChronicleOptions(ChronicleConnectionString.DEVELOPMENT))import io.cratis.chronicle.ChronicleOptions;import io.cratis.chronicle.connection.ChronicleConnectionString;import io.cratis.chronicle.java.BlockingChronicleClient;
class ConnectionStringsDevelopmentDefaultsEquivalent { BlockingChronicleClient createFromOptions() { return BlockingChronicleClient.connect(ChronicleOptions.development()); }
BlockingChronicleClient createFromConnectionString() { return BlockingChronicleClient.connect(new ChronicleOptions(ChronicleConnectionString.Companion.getDEVELOPMENT())); }}defmodule MyApp.ConnectionStringsDevelopmentDefaultsEquivalent do @moduledoc false
def connection_string do Chronicle.Connections.ConnectionString.parse("chronicle://localhost:35000") endendimport { ChronicleOptions } from '@cratis/chronicle';
function createConnectionStringsDevelopmentDefaultsEquivalent(): ChronicleOptions { return ChronicleOptions.fromConnectionString( 'chronicle://chronicle-dev-client:chronicle-dev-secret@localhost:35000' );}Use explicit configuration for production environments.
From connection string
Section titled “From connection string”public static class ConnectionStringsFromConnectionString{ public static ChronicleClient Create() { var options = ChronicleOptions.FromConnectionString("chronicle://localhost:35000"); return new ChronicleClient(options); }}import io.cratis.chronicle.ChronicleClientimport io.cratis.chronicle.ChronicleOptions
fun createClientFromConnectionString(): ChronicleClient { val options = ChronicleOptions.fromConnectionString("chronicle://localhost:35000") return ChronicleClient(options)}import io.cratis.chronicle.ChronicleOptions;import io.cratis.chronicle.java.BlockingChronicleClient;
class ConnectionStringsFromConnectionString { BlockingChronicleClient create() { ChronicleOptions options = ChronicleOptions.fromConnectionString("chronicle://localhost:35000"); return BlockingChronicleClient.connect(options); }}defmodule MyApp.ConnectionStringsFromConnectionString do @moduledoc false
def start_link do children = [ {Chronicle.Client, connection_string: "chronicle://localhost:35000"} ]
Supervisor.start_link(children, strategy: :one_for_one) endendimport { ChronicleOptions } from '@cratis/chronicle';
function createConnectionStringsFromConnectionString(): ChronicleOptions { return ChronicleOptions.fromConnectionString('chronicle://myserver:35000');}Fluent builder
Section titled “Fluent builder”Use ChronicleConnectionStringBuilder to construct a connection string programmatically:
using Cratis.Chronicle.Connections;
public static class ConnectionStringsFluentBuilder{ public static ChronicleClient Create() { var connectionString = new ChronicleConnectionStringBuilder() .WithHost("server.example.com") .WithPort(35000) .WithCredentials("clientId", "clientSecret") .Build();
var options = ChronicleOptions.FromConnectionString(connectionString); return new ChronicleClient(options); }}import io.cratis.chronicle.ChronicleClientimport io.cratis.chronicle.ChronicleOptionsimport io.cratis.chronicle.connection.ChronicleConnectionStringimport io.cratis.chronicle.connection.ChronicleServerAddress
// Kotlin has no separate connection string builder type — a data class with named constructor// arguments already gives every property a name, so ChronicleConnectionString is constructed// directly rather than through a fluent builder.fun createClientWithExplicitConnectionString(): ChronicleClient { val connectionString = ChronicleConnectionString( addresses = listOf(ChronicleServerAddress("server.example.com", 35000)), username = "clientId", password = "clientSecret" ) return ChronicleClient(ChronicleOptions(connectionString))}import io.cratis.chronicle.ChronicleOptions;import io.cratis.chronicle.connection.ChronicleConnectionString;import io.cratis.chronicle.connection.ChronicleServerAddress;import io.cratis.chronicle.java.BlockingChronicleClient;
import java.util.List;
// Java has no separate connection string builder type either — ChronicleConnectionString is a// Kotlin data class, so its full constructor (with every property named) is called directly.class ConnectionStringsFluentBuilder { BlockingChronicleClient create() { ChronicleConnectionString connectionString = new ChronicleConnectionString( List.of(new ChronicleServerAddress("server.example.com", 35000)), "clientId", "clientSecret", false, true, null, io.cratis.chronicle.connection.LoadBalancer.LEAST_CONNECTIONS, null, false);
return BlockingChronicleClient.connect(new ChronicleOptions(connectionString)); }}Elixir does not support this workflow yet.TypeScript does not support this workflow yet.Logging a connection string
Section titled “Logging a connection string”A connection string carries the client secret, the API key and the certificate password, so it must never be written to a log or an error message as it stands. ChronicleConnectionString.Redacted renders it with every credential replaced by REDACTED, while keeping the parts that make a log entry useful — scheme, host, port and the non-sensitive options:
using Cratis.Chronicle.Connections;
public static class ConnectionStringsRedactingForLogs{ public static void LogConnectionTarget(ILogger logger) { var connectionString = new ChronicleConnectionString("chronicle://clientId:clientSecret@server.example.com:35000");
// Logs: chronicle://clientId:REDACTED@server.example.com:35000 logger.LogInformation("Connecting to {RedactedConnectionString}", connectionString.Redacted); }}Kotlin does not support this workflow yet.Java does not support this workflow yet.Elixir does not support this workflow yet.TypeScript does not support this workflow yet.ToString() still renders the connection string in full, credentials included. Use it to pass the value on, never to report it.
The client uses Redacted for its own log messages, so connecting no longer writes the client secret to the log.
Authentication validation
Section titled “Authentication validation”You cannot specify both client credentials and API key authentication in the same connection string. Doing so throws an AmbiguousAuthenticationMode error.