Documentation
¶
Overview ¶
Package quarkbridge publishes the SQL statements a Quark ORM client executes onto a Nucleus observability feed, so they show up in Orbit's live SQL view correlated to the originating HTTP request.
It is an opt-in Quark Middleware. Wire it into a *quark.Client and point it at the Nucleus event bus (rt.Observability(), which returns a nucleus.EventBus):
bridge := quarkbridge.New(rt.Observability())
client, err := quark.New("pgx", dsn, quark.WithMiddleware(bridge))
Every statement the client runs is then timed, mapped to a nucleus.SQLEvent, and published through the framework's public SQL ingest (EmitSQL, ADR-020) — the same feed Orbit already drains via SubscribeSQL. No change to Orbit and no change to either product core is required (QADR-0006): the bridge depends on both Quark and Nucleus and lives outside their cores.
Correlation ¶
RequestID, TraceID and UserID are read from the ctx that Quark threads through the middleware, using Nucleus's own context helpers. That is why the bridge is a Middleware (which receives ctx) rather than a QueryObserver (which does not) — without ctx the feed would lose the link to the request.
Model names ¶
Quark has no model registry the bridge could consult, and a Middleware sees only the rendered SQL, so ModelName is derived from the statement's primary table (FROM/INTO/UPDATE/DELETE FROM). That is the TABLE name, which is what the fleet's sql_models filter then matches for bridged statements; map tables to your own model names with WithModelNames when they differ. Statements without a recognisable table (DDL, CTE-first queries) carry an empty ModelName, exactly as before.
Redaction ¶
By default bind arguments are masked exactly the way Nucleus masks its own SQL feed: string and []byte values become "type(len):***" markers, while numeric, bool, time.Time and nil values are kept verbatim (so a "WHERE id = ?" key still reads as e.g. "42"). Opt into raw values with WithRedaction(IncludeArgs) for local debugging only — it applies no scrubbing.
OTel ¶
OpenTelemetry (quark/otel) is complementary, not the transport for this feed: its spans are exported in batch for durable tracing and would not be real time. This bridge is the live-feed path; run both if you want durable traces too, sharing the same tracer so Quark's spans nest under the request span.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Middleware ¶
type Middleware struct {
// contains filtered or unexported fields
}
Middleware is a quark.Middleware that publishes executed SQL to a Nucleus feed. Construct it with New and pass it to quark.WithMiddleware. It is safe for concurrent use: it holds only immutable configuration.
func New ¶
func New(sink SQLSink, opts ...Option) *Middleware
New returns a Middleware that publishes to sink. A nil sink makes every wrapped call a straight pass-through (the bridge emits nothing), so wiring the bridge without a live feed is harmless.
func (*Middleware) WrapExec ¶
func (m *Middleware) WrapExec(next quark.ExecFunc) quark.ExecFunc
WrapExec implements quark.Middleware. It times the execution and publishes the statement (with any error) after next returns.
func (*Middleware) WrapQuery ¶
func (m *Middleware) WrapQuery(next quark.QueryFunc) quark.QueryFunc
WrapQuery implements quark.Middleware for row-returning queries.
func (*Middleware) WrapQueryRow ¶
func (m *Middleware) WrapQueryRow(next quark.QueryRowFunc) quark.QueryRowFunc
WrapQueryRow implements quark.Middleware for single-row queries. The error is read from (*sql.Row).Err, which reports a failure of the underlying query before Scan is called.
type Option ¶
type Option func(*Middleware)
Option configures a Middleware.
func WithModelNames ¶
WithModelNames maps table names (as they appear in SQL, matched case-insensitively) to the model names published on events. Tables absent from the map publish their table name.
func WithNodeID ¶
WithNodeID tags published events with the framework process identifier. It matches the NodeID Nucleus's own observer stamps; leave it unset for local development (NodeID may be empty).
func WithRedaction ¶
func WithRedaction(mode RedactionMode) Option
WithRedaction sets how bind arguments are exposed. The default is RedactArgs.
type RedactionMode ¶
type RedactionMode int
RedactionMode controls whether bind arguments are exposed on published events. It mirrors the redaction principle Quark applies to its OTel spans.
const ( // RedactArgs is the default. String and []byte argument values are masked // as "type(len):***"; numeric, bool, time.Time and nil values are kept // verbatim — the same convention Nucleus uses for its own SQL feed, so // bridged statements render consistently alongside framework ones. RedactArgs RedactionMode = iota // IncludeArgs places raw argument values on the event via fmt.Sprintf("%v", // arg), with no scrubbing. Opt in only for local debugging. IncludeArgs )