Latu.Telemetry (latu v0.1.1)

Copy Markdown View Source

The :telemetry events Latu emits, and the only place their names are written down.

:telemetry.execute/3 is a plain function call, so this fits an architecture that holds no processes: a handler runs in whichever process is talking to Spark, which is the caller's. A slow handler slows the query, exactly as a :progress function does.

EventMeasurementsWhen
[:latu, :rpc, :start]system_timeevery unary RPC, before the call
[:latu, :rpc, :stop]durationthe same call, after it
[:latu, :rpc, :exception]durationthe call raised rather than returning
[:latu, :execute, :start]system_timea result stream is first enumerated
[:latu, :execute, :stop]durationthat stream ended, however it ended
[:latu, :retry, :attempt]backoff, attempta transient error the transport retries
[:latu, :reattach, :attempt]backoff, attemptan ordinary mid-stream reattach
[:latu, :result, :batch]rows, byteseach Arrow batch
[:latu, :result, :progress]percenteach progress message from the server

Metadata is rpc, outcome and error_class on the RPC events, and session_id plus operation_id on everything that belongs to an execution. The RPC events carry no operation_id; [:latu, :execute, :stop] carries an outcome of :ok, :error or :abandoned. Durations are in native time units, as :telemetry.span/3's are.

[:latu, :rpc, :*] covers every gRPC call, including ExecutePlan — but for that one and ReattachExecute it measures opening the stream, not draining it, because a Latu result is a lazy stream and there is no function whose return is the end of the query. So a dashboard built on the rpc duration would show a 30-second query as two milliseconds. That is what [:latu, :execute, :*] is for: it opens when the stream is first enumerated and closes when it ends, whether that is a finish, a failure, or a consumer that stopped reading — the :abandoned outcome, worth alerting on, since an abandoned reattachable execution goes on running on the server (see Latu.interrupt/2).

Names follow SparkEx's, with :latu for its :spark_ex, so a metrics reporter written for one needs nothing but a prefix for the other.

What is never in metadata

The session's :token and its :headers. Every event is built from named fields — session_id, operation_id — and never from the %Latu.Session{} itself, so a handler that logs its metadata cannot leak a credential. test/integration/telemetry_test.exs asserts it against a session that has a token.

Nor is the plan, the schema or any row. A measurement is a number and metadata is an id.

Attaching

:telemetry.attach_many(
  "latu-log",
  [[:latu, :rpc, :stop], [:latu, :retry, :attempt]],
  fn event, measurements, metadata, _config ->
    Logger.info("#{inspect(event)} #{inspect(measurements)} #{inspect(metadata)}")
  end,
  nil
)