The Switchgear binary runs all services as well as the CLI admin interface.
cargo install switchgear-serverThe docker image is multi-platform for:
docker pull bitshock/switchgearswgr service --config {path/to/config/file} {service enabledment list}The configuration file is in YAML format, and controls settings for all services.
The service enablement list can be any of:
lnurl - the public LNURL servicediscovery - the admin discovery serviceoffer - the offer admin serviceall - all servicesIf left empty, all services will be enabled (same as all).
To run the Docker image:
docker run bitshock/switchgearThe image is configured with a default configuration file path of /etc/swgr/config.yaml . Mount a volume on top of /etc/swgr to provide your own configuration file.
To build the Docker image:
docker buildx build --platform linux/arm64,linux/amd64 -t swgr .Set the build arg WEBPKI_ROOTS=true if you need Mozilla's web PKI roots bundle installed on the image:
docker buildx build --platform linux/arm64,linux/amd64 --build-arg WEBPKI_ROOTS=true -t swgr .Switchgear can be configured by both the REST API and the CLI.
Administration Service endpoints:
https://{host}/discovery
https://{host}/offersSee the Manage Lightning Node Backends with Discovery Service and Manage LNURLs with Offer Service sections for complete REST API.
# Manage Lightning Node Backends
swgr discovery
# Manage LNURLs
swgr offerSee the Manage Lightning Node Backends with Discovery Service and Manage LNURLs with Offer Service sections for complete CLI manual.
To run the CLI administration from Docker:
docker run bitshock/switchgear {cli-options}All service configuration is controlled by a yaml file passed to the server at startup.
See server/config directory for more configuration examples.
Each service has a root entry the configuration file:
# LNURL Service Configuration
lnurl-service:
# Discovery Service Configuration
discovery-service:
# Offer Service Configuration
offer-service:
# Persistence Settings for Discovery and Offer data
store:See the service entries below for complete configuration manual.
Shell-style env var expansion is supported anywhere in the yaml configuration file.
Example config.yaml:
lnurl-service:
address: "${MY_LNURL_SERVICE_ADDRESS:-127.0.0.1:8080}"Run with:
MY_LNURL_SERVICE_ADDRESS=192.168.1.100:8080 swgr service --config ./config.yamlThe configuration would be parsed as:
lnurl-service:
address: "192.168.1.100:8080"If the env var is unset:
swgr service --config ./config.yamlThe configuration would be parsed as:
lnurl-service:
address: "127.0.0.1:8080"Secrets are loaded from files and used to replace tokens in specific configuration fields. Each secret is stored in its own file. The file contents (with a trailing newline stripped) become the secret value.
Example secret files:
# /etc/secrets/offer-mysql-username
root# /etc/secrets/offer-mysql-password
mysqlSecrets are declared inline within the configuration section that consumes them. Each secrets: block has a ttl ( cache time-to-live in seconds) and a map of named secrets, each pointing to a file path:
secrets:
ttl: 300.0
secrets:
MYSQL_USERNAME:
path: "/etc/secrets/offer-mysql-username"
MYSQL_PASSWORD:
path: "/etc/secrets/offer-mysql-password"Once declared, secrets are referenced with the {{SECRET_NAME}} template syntax in fields that support expansion:
database-uri: "postgres://{{POSTGRES_USERNAME}}:{{POSTGRES_PASSWORD}}@localhost:5432/discovery"Unlike env var expansion, secret expansion is selective. Only specific configuration fields have access to secrets, and each secrets: block is scoped to the section that declares it. Secret file contents are cached in memory for ttl seconds and re-read on expiry, allowing rotation without a service restart.
See server/config directory for more configuration examples.
lnurl-service:
# List of partitions this service will handle
# Partitions allow you to segment different Lightning node groups
partitions: [ "default" ]
# Network address and port for the LNURL service to bind to
address: "127.0.0.1:8080"
# Frequency in seconds for health checking Lightning node backends (float)
health-check-frequency-secs: 1.0
# Whether to perform health checks in parallel across all backends
parallel-health-check: true
# Number of consecutive successful health checks needed to mark a backend as healthy
health-check-consecutive-success-to-healthy: 1
# Number of consecutive failed health checks needed to mark a backend as unhealthy
health-check-consecutive-failure-to-unhealthy: 1
# Frequency in seconds for updating backend node information (float)
backend-update-frequency-secs: 1.0
# Invoice expiry time in seconds (integer)
invoice-expiry-secs: 180
# Timeout in seconds for Lightning node client connections (float)
ln-client-timeout-secs: 2.0
# Optional trusted roots pem bundle for all LN clients
ln-trusted-roots: "/etc/ssl/certs/ln-ca.pem"
# List of allowed host headers for incoming requests
# Used for safely generating callback/invoice URLs.
allowed-hosts: [ "lnurl.example.com" ]
# Backoff configuration for retrying failed operations.
# Backoff is used when Lightning Node invoice request fails.
backoff:
# Type of backoff strategy: "stop" or "exponential"
type: "exponential"
# Optional: Initial interval in seconds for exponential backoff (float)
initial-interval-secs: 1.0
# Optional: Randomization factor (0.0 to 1.0)
randomization-factor: 0.5
# Optional: Multiplier for each retry attempt
multiplier: 2.0
# Optional: Maximum interval between retries in seconds (float)
max-interval-secs: 60.0
# Optional: Maximum total elapsed time before giving up in seconds (float)
max-elapsed-time-secs: 300.0
# Backend selection strategy for load balancing
# Options: "round-robin", "random", or "consistent"
backend-selection: "round-robin"
# For consistent hashing, specify max iterations (only used with "consistent")
# backend-selection:
# type: "consistent"
# max-iterations: 10000
# Optional: Bias factor for capacity-influenced selection
# Negative values are restrictive:
# prefer nodes with capacity higher than requested amount
# Positive values are lenient:
# refer nodes with capacity less than requested amount
selection-capacity-bias: -0.2
# Optional: Allow &comment query param in LNURL invoice request, sized in char len
# Used for Consistent backend selection
comment_allowed: 64,
# Optional: TLS configuration for HTTPS support
tls:
# Path to TLS certificate file
cert-path: "/etc/ssl/certs/lnurl-cert.pem"
# Path to TLS private key file
key-path: "/etc/ssl/certs/lnurl-key.pem"
# QR module width x height
bech32-qr-scale: 8
# QR light gray level
bech32-qr-light: 255
# QR dark gray level
bech32-qr-dark: 0
# Optional: OTLP telemetry export
otlp:
# Required. Shared transport for every signal below: a signal that declares
# its own `export` block replaces this one in full (no field-level merge),
# and signals that do not share one gRPC connection.
export:
# OTLP collector endpoint (gRPC)
endpoint: "http://127.0.0.1:4317"
# Name of the secret whose contents are sent as the bearer token
auth-token: "OTEL_AUTH_TOKEN"
# Optional: pem bundle of trusted CA certificate paths for TLS verification
trusted-roots: "/etc/ssl/certs/otlp-ca.pem"
# Optional: pinned collector address for the trusted-roots bundle
trusted-root-address: "127.0.0.1:4317"
# Optional: per-request timeout on the gRPC channel
export-timeout-secs: 5.0
# Optional: mTLS client identity, referencing secret names
client-identity:
cert-secret: "OTEL_CLIENT_CERT"
key-secret: "OTEL_CLIENT_KEY"
# Secrets consumed by this exporter (see Secrets Expansion)
secrets:
ttl: 300.0
secrets:
OTEL_AUTH_TOKEN:
path: "/etc/ssl/certs/otlp-auth.token"
OTEL_CLIENT_CERT:
path: "/etc/ssl/certs/otlp-client.pem"
OTEL_CLIENT_KEY:
path: "/etc/ssl/certs/otlp-client-key.pem"
# Present = span export is on. Omit the block to turn tracing off.
tracing:
# always-on | always-off | trace-id-ratio | parent-based-trace-id-ratio
# `parent-based-trace-id-ratio` with `ratio: 1.0` is the OTel default.
sampler:
type: parent-based-trace-id-ratio
ratio: 1.0
# Present = metric export is on. Omit the block to turn metrics off.
metrics:
# cumulative | delta | low-memory
temporality: cumulative
# trace | debug | info | warn | error | off. Optional; defaults to info.
level: infoSee server/config directory for more configuration examples.
discovery-service:
# Network address and port for the Discovery service to bind to
address: "127.0.0.1:8081"
# Path to the authentication authority certificate/key file
# This file contains the public key used to verify API access
auth-authority: "/etc/ssl/certs/discovery-auth-authority.pem"
# Optional: TLS configuration for HTTPS support
tls:
# Path to TLS certificate file
cert-path: "/etc/ssl/certs/discovery-cert.pem"
# Path to TLS private key file
key-path: "/etc/ssl/certs/discovery-key.pem"
# Optional: OTLP telemetry export
otlp:
# Required. Shared transport for every signal below: a signal that declares
# its own `export` block replaces this one in full (no field-level merge),
# and signals that do not share one gRPC connection.
export:
# OTLP collector endpoint (gRPC)
endpoint: "http://127.0.0.1:4317"
# Name of the secret whose contents are sent as the bearer token
auth-token: "OTEL_AUTH_TOKEN"
# Optional: pem bundle of trusted CA certificate paths for TLS verification
trusted-roots: "/etc/ssl/certs/otlp-ca.pem"
# Optional: pinned collector address for the trusted-roots bundle
trusted-root-address: "127.0.0.1:4317"
# Optional: per-request timeout on the gRPC channel
export-timeout-secs: 5.0
# Optional: mTLS client identity, referencing secret names
client-identity:
cert-secret: "OTEL_CLIENT_CERT"
key-secret: "OTEL_CLIENT_KEY"
# Secrets consumed by this exporter (see Secrets Expansion)
secrets:
ttl: 300.0
secrets:
OTEL_AUTH_TOKEN:
path: "/etc/ssl/certs/otlp-auth.token"
OTEL_CLIENT_CERT:
path: "/etc/ssl/certs/otlp-client.pem"
OTEL_CLIENT_KEY:
path: "/etc/ssl/certs/otlp-client-key.pem"
# Present = span export is on. Omit the block to turn tracing off.
tracing:
# always-on | always-off | trace-id-ratio | parent-based-trace-id-ratio
# `parent-based-trace-id-ratio` with `ratio: 1.0` is the OTel default.
sampler:
type: parent-based-trace-id-ratio
ratio: 1.0
# Present = metric export is on. Omit the block to turn metrics off.
metrics:
# cumulative | delta | low-memory
temporality: cumulative
# trace | debug | info | warn | error | off. Optional; defaults to info.
level: infoGenerate key pairs and tokens for Discovery service authentication:
# Generate a new key pair for token signing
swgr discovery token key --public discovery-public.pem --private discovery-private.pem
# The public key (discovery-public.pem) should be used as the auth-authority in the configuration
# The private key (discovery-private.pem) is used to mint authentication tokens
# Create a token (default 3600 seconds)
swgr discovery token mint --key discovery-private.pem --output discovery.tokenSee server/config directory for more configuration examples.
offer-service:
# Network address and port for the Offers service to bind to
address: "127.0.0.1:8082"
# Path to the authentication authority certificate/key file
# This file contains the public key used to verify API access
auth-authority: "/etc/ssl/certs/offer-auth-authority.pem"
# Optional: TLS configuration for HTTPS support
tls:
# Path to TLS certificate file
cert-path: "/etc/ssl/certs/offer-cert.pem"
# Path to TLS private key file
key-path: "/etc/ssl/certs/offer-key.pem"
# max page size for get all queries
max-page-size: 100
# Optional: OTLP telemetry export
otlp:
# Required. Shared transport for every signal below: a signal that declares
# its own `export` block replaces this one in full (no field-level merge),
# and signals that do not share one gRPC connection.
export:
# OTLP collector endpoint (gRPC)
endpoint: "http://127.0.0.1:4317"
# Name of the secret whose contents are sent as the bearer token
auth-token: "OTEL_AUTH_TOKEN"
# Optional: pem bundle of trusted CA certificate paths for TLS verification
trusted-roots: "/etc/ssl/certs/otlp-ca.pem"
# Optional: pinned collector address for the trusted-roots bundle
trusted-root-address: "127.0.0.1:4317"
# Optional: per-request timeout on the gRPC channel
export-timeout-secs: 5.0
# Optional: mTLS client identity, referencing secret names
client-identity:
cert-secret: "OTEL_CLIENT_CERT"
key-secret: "OTEL_CLIENT_KEY"
# Secrets consumed by this exporter (see Secrets Expansion)
secrets:
ttl: 300.0
secrets:
OTEL_AUTH_TOKEN:
path: "/etc/ssl/certs/otlp-auth.token"
OTEL_CLIENT_CERT:
path: "/etc/ssl/certs/otlp-client.pem"
OTEL_CLIENT_KEY:
path: "/etc/ssl/certs/otlp-client-key.pem"
# Present = span export is on. Omit the block to turn tracing off.
tracing:
# always-on | always-off | trace-id-ratio | parent-based-trace-id-ratio
# `parent-based-trace-id-ratio` with `ratio: 1.0` is the OTel default.
sampler:
type: parent-based-trace-id-ratio
ratio: 1.0
# Present = metric export is on. Omit the block to turn metrics off.
metrics:
# cumulative | delta | low-memory
temporality: cumulative
# trace | debug | info | warn | error | off. Optional; defaults to info.
level: infoGenerate key pairs and tokens for Offer service authentication:
# Generate a new key pair for token signing
swgr offer token key --public offer-public.pem --private offer-private.pem
# The public key (offer-public.pem) should be used as the auth-authority in the configuration
# The private key (offer-private.pem) is used to mint authentication tokens
# Create a token (default 3600 seconds)
swgr offer token mint --key offer-private.pem --output offer.tokenBoth Discovery and Offer services support multiple storage backends. Configure persistence in the store section of your configuration file.
Both Discovery and Offer stores support these storage backends:
store:
discover: # or 'offer'
type: "database"
# Database connection URI (SQLite/MySQL/PostgreSQL)
# Supports secrets expansion
database-uri: "connection-url"
# Maximum number of concurrent database connections
max-connections: 5
# Timeout in seconds for establishing a new database connection
connect-timeout-secs: 5.0
# Timeout in seconds for acquiring a connection from the pool
acquire-timeout-secs: 10.0
# Optional: inline secrets consumed by database-uri (see Secrets Expansion)
secrets:
ttl: 300.0
secrets:
POSTGRES_USERNAME:
path: "/etc/secrets/discovery-postgres-username"
POSTGRES_PASSWORD:
path: "/etc/secrets/discovery-postgres-password"For database-uri formats, see Database Connection URLs.
Both Discovery and Offer can use a remote http store, making custom integrations straightforward. The store clients connect to the same REST API used for remote administration, making it possible for Switchgear to run headless as well, serving only as a database for other Switchgear instances.
store:
discover: # or 'offer'
type: "http"
# Base URL of the remote service
base-url: "https://service.example.com"
# Timeout in seconds for establishing connection
connect-timeout-secs: 2.0
# Total timeout in seconds for complete request/response
total-timeout-secs: 5.0
# Optional pem bundle of trusted CA certificate paths for TLS verification
trusted-roots: "/etc/ssl/certs/ca.pem"
# Name of the secret whose contents are sent as the bearer token
authorization: "DISCOVERY_STORE_HTTP_BEARER"
# Inline secrets consumed by authorization (see Secrets Expansion)
secrets:
ttl: 300.0
secrets:
DISCOVERY_STORE_HTTP_BEARER:
path: "/etc/ssl/certs/discovery-authorization.token"Volatile storage, data is lost on restart:
store:
discover: # or 'offer'
type: "memory"store:
# Discovery backend storage
discover:
type: "database"
database-uri: "postgres://{{POSTGRES_USERNAME}}:{{POSTGRES_PASSWORD}}@localhost:5432/switchgear"
max-connections: 5
connect-timeout-secs: 5.0
acquire-timeout-secs: 10.0
secrets:
ttl: 300.0
secrets:
POSTGRES_USERNAME:
path: "/etc/secrets/postgres-username"
POSTGRES_PASSWORD:
path: "/etc/secrets/postgres-password"
# Offer storage (sharing same database)
offer:
type: "database"
database-uri: "postgres://{{POSTGRES_USERNAME}}:{{POSTGRES_PASSWORD}}@localhost:5432/switchgear"
max-connections: 10
connect-timeout-secs: 5.0
acquire-timeout-secs: 10.0
secrets:
ttl: 300.0
secrets:
POSTGRES_USERNAME:
path: "/etc/secrets/postgres-username"
POSTGRES_PASSWORD:
path: "/etc/secrets/postgres-password"store:
# Memory storage for Discovery
discover:
type: "memory"
# Database storage for Offers
offer:
type: "database"
database-uri: "sqlite:///var/lib/switchgear/offers.db?mode=rwc"
max-connections: 5
connect-timeout-secs: 5.0
acquire-timeout-secs: 10.0store:
# Connect to remote Discovery service
discover:
type: "http"
base-url: "https://discovery.internal:8081"
connect-timeout-secs: 2.0
total-timeout-secs: 5.0
trusted-roots: "/etc/ssl/certs/internal-ca.pem"
authorization: "DISCOVERY_STORE_HTTP_BEARER"
secrets:
ttl: 300.0
secrets:
DISCOVERY_STORE_HTTP_BEARER:
path: "/etc/ssl/certs/discovery.token"
# Local database for Offers
offer:
type: "database"
database-uri: "sqlite:///data/offers.db?mode=rwc"
max-connections: 10
connect-timeout-secs: 5.0
acquire-timeout-secs: 10.0Both Discovery and Offer data stores have a database-uri field to configure the database.
sqlite:///path/to/file.db?{options}See https://www.sqlite.org/uri.html for all connection URL options.
mysql://[host][/database][?properties]Properties:
| Parameter | Default | Description |
|---|---|---|
ssl-mode | PREFERRED | Determines whether or with what priority a secure SSL TCP/IP connection will be negotiated. See [MySqlSslMode]. |
ssl-ca | None | Sets the name of a file containing a list of trusted SSL Certificate Authorities. |
statement-cache-capacity | 100 | The maximum number of prepared statements stored in the cache. Set to 0 to disable. |
socket | None | Path to the unix domain socket, which will be used instead of TCP if set. |
postgresql://[user[:password]@][host][:port][/dbname][?param1=value1&...]See https://www.postgresql.org/docs/current/libpq-connect.html for all connection URL options.
Switchgear service processes emit structured logs to stderr in ECS logging format. Logging output is newline-delimited JSON (ND-JSON) that conforms to the Elastic Common Schema. Every record can be ingested directly by Elasticsearch, Filebeat, Vector, Fluent Bit, or any pipeline that understands ECS.
Each line begins with the four MVP keys defined by the ecs-logging specification, in this order:
@timestamp: ISO-8601 UTC timestamplog.level: TRACE, DEBUG, INFO, WARN, or ERRORmessage: human-readable textecs.version: ECS schema version the record conforms toExample access-log line:
{
"@timestamp": "2026-08-24T21:07:11.482Z",
"log.level": "INFO",
"message": "handled request",
"ecs.version": "8.11.0",
"service.name": "swgr.lnurl",
"service.version": "0.5.0",
"http.request.method": "GET",
"http.response.status_code": 200,
"http.version": "1.1",
"url.path": "/offers/default/6a38ebdd-83ef-4b94-b843-3b18cd90a833/invoice",
"url.query": "amount=100000",
"client.ip": "10.0.0.42",
"event.dataset": "swgr.lnurl.access",
"event.duration": 18342119,
"trace.id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span.id": "00f067aa0ba902b7",
"log.origin.file.name": "request_logger.rs",
"log.origin.file.line": 73
}Example error record:
{
"@timestamp": "2026-08-24T21:07:12.104Z",
"log.level": "ERROR",
"message": "upstream offer store returned 502",
"ecs.version": "8.11.0",
"service.name": "swgr.lnurl",
"service.version": "0.5.0",
"error.type": "switchgear_service::axum::crud::error::CrudError",
"error.message": "connect error",
"error.stack_trace": "...",
"event.kind": "event",
"event.category": [
"web"
],
"event.type": [
"error"
],
"event.outcome": "failure",
"http.response.status_code": 502,
"trace.id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span.id": "00f067aa0ba902b7"
}Each enabled service emits records under its own service.name:
| Service | service.name |
|---|---|
| LNURL | swgr.lnurl |
| Discovery | swgr.discovery |
| Offer | swgr.offer |
| CLI / bootstrap | swgr |
service.version carries the running Switchgear build version.
Every completed HTTP request produces an INFO record with ECS HTTP and ECS URL fields:
http.request.method, http.response.status_code, http.versionurl.path, url.queryclient.ipevent.duration (nanoseconds), event.dataset, event.modulelog.origin.file.name, log.origin.file.lineWARN (4xx) and ERROR (5xx) records add ECS error and ECS event fields:
error.type: fully-qualified Rust error typeerror.message: the error's Display stringerror.stack_trace: full cause chainevent.kind (event), event.category (e.g. ["web"]), event.type (e.g. ["error"]), event.outcome ( failure)When OTLP tracing is enabled and a request is executing inside a span, log records carry ECS tracing fields trace.id and span.id. These correlate to the OTLP spans exported to the collector, so you can pivot from a log line in Kibana/Elastic APM directly to its distributed trace.
See OTLP Tracing below for exporter configuration.
swgr service reads its log level from the standard RUST_LOG environment variable and defaults to info. It accepts the full tracing-subscriber env-filter grammar:
RUST_LOG=info,switchgear_service=debug swgr service --config ./config.yamlThe -l / --log-level global flag is ignored for swgr service. Use RUST_LOG instead.
CLI subcommands (swgr discovery ..., swgr offer ...) output human-readable text on stderr intended for interactive use; their level is controlled by the -l / --log-level global flag (defaults to info):
swgr --log-level debug discovery lsEach service can export OpenTelemetry spans to an OTLP-compatible collector (Jaeger, Tempo, Elastic APM, Grafana Cloud, etc.). Presence of the otlp.tracing block turns span export on; the transport comes from otlp.export unless otlp.tracing.export overrides it. See the LNURL, Discovery, and Offer service configuration samples above.
Each service can also export OpenTelemetry metrics over the same OTLP pipeline. Presence of the otlp.metrics block turns metric export on; the transport comes from otlp.export unless otlp.metrics.export overrides it.
otlp:
export:
endpoint: "http://127.0.0.1:4317"
auth-token: "OTEL_AUTH_TOKEN"
# ... shared transport, as in the samples above
metrics:
temporality: cumulativeMetric export is on when the service's otlp.metrics block is present. Setting the OTel-standard OTEL_METRICS_EXPORTER environment variable to none forces it off regardless of configuration:
OTEL_METRICS_EXPORTER=none swgr service --config ./config.yamlnone is the only value that changes anything: any other setting, and an unset variable, leave metrics on. Log records and spans are unaffected either way.
otlp.metrics.level sets how much metric detail is recorded:
otlp:
metrics:
temporality: cumulative
level: debug| Value | Recorded |
|---|---|
off, error, warn | Nothing |
info | The standard metric set. This is the default when the field is omitted |
debug | The standard set, plus finer-grained per-operation detail |
trace | Everything |
Values are case-insensitive.
Leave the level at info for normal running. Raise it to debug when you are investigating something and need per-operation detail; expect more datapoints and higher tag cardinality at your metrics sink, so lower it again afterward.
Setting off stops metrics being recorded but leaves the exporter connected. To shut the pipeline down entirely, omit the otlp.metrics block or set OTEL_METRICS_EXPORTER=none (see Enabling And Disabling above).
RUST_LOG has no effect on metrics — it governs log records only. otlp.metrics.level is the only setting that changes metric verbosity.
otlp.metrics.temporality selects how cumulative state is reported:
| Value | Behaviour |
|---|---|
cumulative | Each export carries the running total since process start |
delta | Each export carries only what changed since the previous one |
low-memory | Delta for counters and histograms, cumulative for up-down counters and gauges |
| Metric | Emitted when |
|---|---|
db.client.operation.duration | A discovery or offer store is backed by a database |
http.client.request.duration | A discovery or offer store is backed by a remote service, see Persistence |
rpc.client.call.duration | The LNURL service calls a CLN or LND node |
Metric and attribute names follow the OpenTelemetry semantic conventions, so a collector, dashboard or alert built against those conventions understands them without mapping. Three things hold across all three:
info, so they are exported at the default metric level.db.client.operation.durationHow long a database call took.
Source: Database client metrics — histogram, stable.
| Attribute | Present | Value |
|---|---|---|
db.system.name | Always | sqlite, mysql or postgresql |
db.namespace | db.collection.name | Always | The database and the table. For SQLite the database is the file name without its extension, or :memory: |
server.address | server.port | Except SQLite | Host and port of the database server. Never any credential from the connection URL |
error.type | On failure only | unique_constraint, foreign_key_constraint, constraint, connection_acquire, connection, statement, conversion, or _OTHER. The same set whichever database you run |
db.response.status_code | On failure only | The database's own error code, which differs between SQLite, MySQL and Postgres |
swgr.operation | Always | The store operation, see below |
swgr.operation is finer-grained than the table alone. The pairings are fixed:
db.collection.name | swgr.operation |
|---|---|
offer_record | get_offer, get_offers, post_offer, put_offer_upsert, put_offer_fetch, delete_offer |
offer_metadata | get_metadata, get_all_metadata, post_metadata, put_metadata_upsert, put_metadata_fetch, delete_metadata |
discovery_backend | get, get_all_backends, post, put, patch, delete |
discovery_backend_etag | get_all_etag |
http.client.request.durationHow long a request to a remote discovery or offer service took.
Source: HTTP client metrics — histogram, stable.
| Attribute | Present | Value |
|---|---|---|
http.request.method | url.template | Always | The method, and the route pattern rather than the requested path, so no identifier reaches your metrics sink |
server.address | server.port | Always | Host and port of the remote store |
http.response.status_code | When a response arrived | The status, including a 4xx or 5xx |
error.type | On failure only | The status, when one was returned, otherwise timeout, connect, decode or request |
The route patterns are fixed:
| Store | url.template | http.request.method |
|---|---|---|
| Offer | /offers, /offers/{partition}, /offers/{partition}/{id} | GET, POST, PUT, DELETE |
| Offer | /metadata, /metadata/{partition}, /metadata/{partition}/{id} | GET, POST, PUT, DELETE |
| Discovery | /discovery, /discovery/{public_key} | GET, POST, PUT, PATCH, DELETE |
rpc.client.call.durationHow long a gRPC call to a Lightning node took.
Source: RPC client metrics — histogram, release candidate. Older tooling may know this metric by its previous name, rpc.client.duration.
| Attribute | Present | Value |
|---|---|---|
rpc.system.name | Always | grpc |
rpc.method | Always | The node call, see below |
server.address | server.port | Always | Host and port of the node |
rpc.response.status_code | Always | The gRPC status, including OK on success |
error.type | On failure only | The gRPC status, set only when the call did not return OK |
The methods are fixed:
| Node | rpc.method |
|---|---|
| CLN | cln.Node/Invoice, cln.Node/ListPeerChannels |
| LND | lnrpc.Lightning/AddInvoice, lnrpc.Lightning/ChannelBalance |