TypeDB.GRPC.Telemetry (TypeDB.GRPC v0.1.0)

Copy Markdown View Source

What this driver reports about itself.

The event names are the sibling's, on purpose

[:typedb, :operation, …], [:typedb, :transaction, …] and [:typedb, :sign_in, …] are exactly the events TypeDB.Telemetry emits, and they mean the same things. That is the same argument as the shared %TypeDB.Error{}: an application that switches transports should keep its dashboards, and telemetry is precisely the sort of thing that breaks quietly when it does not.

Both drivers put :transport in the metadata — :grpc here, :http there — so an application running both can break a metric down by it, and one running either can ignore it.

eventemitted foruse it for
[:typedb, :operation, …]one call into the public APIrequest rates and latency
[:typedb, :transaction, …]one bracketed transactionhow long work holds a transaction
[:typedb, :sign_in, …]one sign-intoken churn
[:typedb, :grpc, :stream, :batch]one batch of a streamed readback pressure, and whether it is working

What is missing, and why

There is no [:typedb, :request, …] here. Over HTTP that span is one attempt on the wire, and it exists because the driver retries: several spans per call is the interesting fact. This transport has no per-request retry — a request lives on a transaction stream whose failure destroys the transaction, so there is nothing a retry could correctly re-send — and a span per message on the stream would report the same duration as the operation that contains it. Emitting it would be noise dressed as parity.

There is no [:typedb, :retry, :exhausted] for the same reason.

[:typedb, :operation, :start | :stop | :exception]

One span per call into the public API: TypeDB.GRPC.query/4, TypeDB.GRPC.Database.list/2, TypeDB.GRPC.Transaction.commit/2 and so on.

Metadata:

  • :transport — always :grpc
  • :connection — the connection name
  • :operation — a low-cardinality atom such as :query, :commit, :databases_all. Safe as a metric tag; this is the one to tag on
  • :database — present whenever the call names one
  • :transaction_type:read, :write or :schema, where the call has one
  • :queries — how many queries a call carried, on query_many/3 and execute_many/3
  • :error — the TypeDB.Error, on :stop only, when the call failed

[:typedb, :transaction, :start | :stop | :exception]

One span per TypeDB.GRPC.Transaction.transaction/5, from opening the transaction to the commit or close that ends it.

Metadata: :transport, :connection, :database, :type, and on :stop an :outcome of :commit, :close or :commit_failed, plus :error when there was one. A block that raises produces :exception.

[:typedb, :sign_in, :start | :stop | :exception]

One span per sign-in. Metadata: :transport, :connection, and :error on failure.

[:typedb, :grpc, :stream, :batch]

Not a span, and with no counterpart on the other transport: one event per batch handed to a consumer of TypeDB.GRPC.stream/4.

Measurements: :rows in the batch, and :wait — native time units the consumer spent waiting for it. Metadata: :transport, :connection and :database.

It is here because back pressure is invisible otherwise. A :wait near zero every time means the server is ahead of the consumer and the batch size could be larger; a :wait that dominates means the consumer is waiting on TypeDB, which is the shape a healthy streamed read has.

Just show me what it is doing

TypeDB.GRPC.Telemetry.attach_default_logger(:info)

Summary

Functions

Attaches a handler that logs one line per operation, transaction and sign-in.

Removes the handler attach_default_logger/1 installed.

The event prefix for operation spans. The sibling's, deliberately.

The event prefix for sign-in spans.

The event emitted for each batch of a streamed read.

The event prefix for bracketed-transaction spans.

The value this driver puts in :transport.

Functions

attach_default_logger(level \\ :debug)

@spec attach_default_logger(Logger.level()) :: :ok | {:error, :already_exists}

Attaches a handler that logs one line per operation, transaction and sign-in.

It filters on :transport so that attaching it alongside TypeDB.Telemetry.attach_default_logger/1 does not log the sibling's spans twice — they share event names, which is the point, and this is the cost.

detach_default_logger()

@spec detach_default_logger() :: :ok | {:error, :not_found}

Removes the handler attach_default_logger/1 installed.

operation_event()

@spec operation_event() :: [atom()]

The event prefix for operation spans. The sibling's, deliberately.

sign_in_event()

@spec sign_in_event() :: [atom()]

The event prefix for sign-in spans.

stream_batch_event()

@spec stream_batch_event() :: [atom()]

The event emitted for each batch of a streamed read.

transaction_event()

@spec transaction_event() :: [atom()]

The event prefix for bracketed-transaction spans.

transport()

@spec transport() :: atom()

The value this driver puts in :transport.