Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,63 @@ netstat -ulnp 2>/dev/null | grep -E '6969|6970'
netstat -tlnp 2>/dev/null | grep -E '7070|7071|1212'
```

## Running a Local HTTPS Tracker

For local TLS verification, create a temporary configuration and certificate
under `.tmp/`. The directory is git-ignored, so do not place test keys in
`share/` or commit them.

1. Copy or create a configuration based on the development configuration. Give
an HTTP tracker a port-zero binding if the final runtime binding is part of
the behavior under test:

```toml
[[http_trackers]]
bind_address = "0.0.0.0:0"

# Schema 2.0 uses the historical `tsl_config` spelling.
[http_trackers.tsl_config]
ssl_cert_path = ".tmp/localhost.crt"
ssl_key_path = ".tmp/localhost.key"
```

1. Generate a short-lived self-signed certificate for local use. Include SANs
for both `localhost` and `127.0.0.1` so a loopback client can validate it
when supplied with the certificate:

```bash
openssl req -x509 -out .tmp/localhost.crt -keyout .tmp/localhost.key \
-newkey rsa:2048 -nodes -sha256 -days 1 \
-subj '/CN=localhost' \
-addext 'subjectAltName=DNS:localhost,IP:127.0.0.1' \
-addext 'keyUsage=digitalSignature' \
-addext 'extendedKeyUsage=serverAuth'
```

1. Start the tracker with the temporary configuration:

```bash
TORRUST_TRACKER_CONFIG_TOML_PATH="$PWD/.tmp/local-tls.toml" cargo run --bin torrust-tracker
```

Read the startup log to obtain the final port assigned to a `:0` binding.
It will report an `https://` URL when TLS is enabled.

1. Probe the listener. `--insecure` is appropriate only for this temporary
self-signed local certificate:

```bash
curl --fail --silent --show-error --insecure https://127.0.0.1:<port>/health_check
```

1. Stop the tracker and remove or retain the `.tmp/` files as local-only test
artifacts. Restore any temporary configuration edits before committing.

> **Known limitation:** the aggregate health-check service currently builds
> HTTP-tracker probes with an `http://` URL even when a registered listener is
> HTTPS. A direct HTTPS probe verifies the TLS listener; do not treat that
> separate health-check defect as a TLS-startup failure.

## Database Storage

By default, development tracker uses SQLite3. The database file is stored in:
Expand Down
76 changes: 76 additions & 0 deletions .github/skills/dev/logging/structured-runtime-logging/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: structured-runtime-logging
description: "Use when adding or changing logs for runtime service identity, service startup, listener bindings, or tracing instrumentation. Prefer explicit structured tracing fields over Rust Debug-formatted metadata."
metadata:
author: torrust
version: "1.0"
---

# Structured Runtime Logging

When logging runtime service identity, emit stable tracing fields instead of
recording `RuntimeServiceMetadata`, `ConfigurationInstanceId`, or related
structs through `Debug` formatting.

Use the canonical fields:

- `service_role` — the canonical role identifier, such as `http_tracker`.
- `instance_index` — the canonical zero-based configuration instance index.
- `service_binding` — the final protocol and bound socket address, after the
listener has successfully bound.

## Correct Form

Exclude metadata from automatic `#[instrument]` capture and add canonical
fields explicitly:

```rust
#[instrument(
skip(metadata),
fields(
service_role = metadata.service_role().as_str(),
instance_index = metadata.configuration_instance_id().instance_index(),
)
)]
```

When a listener binds, log its final `service_binding` as an explicit field.

```rust
tracing::info!(
service_binding = %service_binding.url(),
"Started HTTP tracker"
);
```

The resulting event has stable, queryable fields:

```text
INFO start_job{service_role="http_tracker" instance_index=1}: Started HTTP tracker service_binding=http://0.0.0.0:7171
```

## Incorrect Form

Do not let `#[instrument]` capture the metadata parameter automatically, and
do not log the metadata with `?` or `%` formatting:

```rust
#[instrument]
async fn start(metadata: RuntimeServiceMetadata) {
tracing::info!(?metadata, "Started HTTP tracker");
}
```

This creates log output coupled to the Rust struct's `Debug` representation,
such as `metadata=RuntimeServiceMetadata { configuration_instance_id: ... }`.
It is not a stable, queryable log contract.

For example, automatic span capture and `?metadata` produce implementation
detail in the log instead of canonical fields:

```text
INFO start_job{idx=1 metadata=RuntimeServiceMetadata { configuration_instance_id: ConfigurationInstanceId { service_role: HttpTracker, instance_index: 1 } }}: Started HTTP tracker metadata=RuntimeServiceMetadata { configuration_instance_id: ConfigurationInstanceId { service_role: HttpTracker, instance_index: 1 } }
```

Do not make Rust field names, struct nesting, or a `Debug` implementation an
observability contract.
53 changes: 19 additions & 34 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ torrust-tracker-axum-server = { version = "0.1.0", path = "packages/axum-server"
torrust-tracker-rest-api-client = { version = "0.1.0", path = "packages/rest-api-client" }
torrust-tracker-rest-api-runtime-adapter = { version = "0.1.0", path = "packages/rest-api-runtime-adapter" }
torrust-tracker-rest-api-protocol = { version = "0.1.0", path = "packages/rest-api-protocol" }
torrust-server-lib = "0.1.0"
torrust-server-lib = "0.2.0"
torrust-clock = "3.0.0"
torrust-tracker-configuration = { version = "3.0.0", path = "packages/configuration" }
torrust-tracker-primitives = { version = "3.0.0", path = "packages/primitives" }
Expand Down
Loading
Loading