chronos-ruby 1.1.3 → 1.2.0.pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -26
- data/README.md +14 -13
- data/docs/adr/ADR-010-opentelemetry-interoperability.md +3 -3
- data/docs/compatibility.md +10 -16
- data/docs/configuration.md +7 -3
- data/docs/modules/context.md +1 -1
- data/docs/modules/external-http.md +3 -2
- data/docs/modules/rails-legacy.md +2 -2
- data/docs/modules/sidekiq-legacy.md +3 -3
- data/docs/troubleshooting.md +1 -1
- data/lib/chronos/adapters/fiber_local_context_store.rb +57 -0
- data/lib/chronos/agent.rb +7 -1
- data/lib/chronos/configuration/apm_validation.rb +2 -0
- data/lib/chronos/configuration/snapshot.rb +2 -2
- data/lib/chronos/configuration/validation.rb +2 -2
- data/lib/chronos/configuration.rb +5 -3
- data/lib/chronos/core/trace_context.rb +38 -0
- data/lib/chronos/integrations/active_job.rb +2 -2
- data/lib/chronos/integrations/faraday.rb +76 -0
- data/lib/chronos/integrations/net_http.rb +5 -1
- data/lib/chronos/integrations/opentelemetry.rb +44 -0
- data/lib/chronos/integrations/rack/middleware.rb +8 -2
- data/lib/chronos/integrations/sidekiq.rb +1 -1
- data/lib/chronos/rails/error_reporter_subscriber.rb +39 -0
- data/lib/chronos/rails/installer.rb +8 -14
- data/lib/chronos/rails/notifications_subscriber.rb +12 -0
- data/lib/chronos/rails.rb +2 -13
- data/lib/chronos/version.rb +2 -2
- data/lib/chronos.rb +4 -0
- data/lib/generators/chronos/install/templates/chronos.rb +10 -52
- metadata +42 -44
- data/docs/release-1.1.2-readiness.md +0 -21
- data/docs/release-1.1.3-readiness.md +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c13c2858edcb41d4b2a0bfc83049349ee13a5a9ecee873798750b4bf9f1da48c
|
|
4
|
+
data.tar.gz: a21babcc28ce763e7d867f35064735d661214724c1ed9d256e8d174a1a04c5dc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 81ab0672785236e1ffaeecf0fbb5ae3187f319be349a06f724eee50dd0d20963afb74a84485267e8ea5e3a7dd37dacef15ab456783fee622bef901110b98344a
|
|
7
|
+
data.tar.gz: 835ee551ddcec646a44376dcdfc09748e12c0fa360fee62365455e6776503a0597baed504a33276059853e652f5a90458ad7ae43bb582f7647303af9940a5d1f
|
data/CHANGELOG.md
CHANGED
|
@@ -4,40 +4,23 @@ All notable changes are documented here. The project follows Semantic Versioning
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
-
## [1.1
|
|
7
|
+
## [1.2.0.pre.1] - 2026-08-11
|
|
8
8
|
|
|
9
|
-
###
|
|
10
|
-
|
|
11
|
-
- expanded the gem summary and description to clarify its exception, metrics, and telemetry monitoring purpose;
|
|
12
|
-
- highlighted https://chronosmonitor.com.br as the official Chronos Monitor platform for receiving and visualizing observability data;
|
|
13
|
-
- synchronized stable legacy release references and installation examples with version `1.1.3`.
|
|
9
|
+
### Added
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
- fiber-aware execution context with a thread-local fallback;
|
|
12
|
+
- Sidekiq 7 and Rails 7 error reporter integration using public extension APIs;
|
|
13
|
+
- Action Cable notification spans and a dependency-free Faraday middleware;
|
|
14
|
+
- optional W3C `traceparent` propagation and an OpenTelemetry bridge that consumes the active span without installing an SDK or exporter.
|
|
16
15
|
|
|
17
16
|
### Changed
|
|
18
17
|
|
|
19
|
-
- the
|
|
20
|
-
-
|
|
21
|
-
- Rails derives the service name from the application namespace when `CHRONOS_SERVICE_NAME` is absent;
|
|
22
|
-
- Rails applications automatically install the optional Sidekiq 4/5 client and server middleware when Sidekiq is available.
|
|
23
|
-
|
|
24
|
-
### Fixed
|
|
25
|
-
|
|
26
|
-
- configuration snapshots no longer freeze the Rails-owned logger, preventing later logger extensions from raising `FrozenError`;
|
|
27
|
-
- logger lookup and optional Sidekiq installation failures are contained so they cannot abort Rails boot.
|
|
18
|
+
- the transitional runtime range is Ruby 2.7 through 3.4 and the default context strategy is `:fiber_local`;
|
|
19
|
+
- Active Job and Sidekiq envelopes may propagate allowlisted span ID and trace flags in addition to trace/request IDs.
|
|
28
20
|
|
|
29
21
|
### Security
|
|
30
22
|
|
|
31
|
-
-
|
|
32
|
-
- generated Boolean overrides accept only explicit `1/0`, `true/false`, `yes/no`, and `on/off` forms.
|
|
33
|
-
|
|
34
|
-
## [1.1.1] - 2026-08-11
|
|
35
|
-
|
|
36
|
-
### Changed
|
|
37
|
-
|
|
38
|
-
- the Rails install generator now writes every public configuration option with explanatory English comments;
|
|
39
|
-
- the official `https://chronosmonitor.com.br` endpoint is now the default host when applications omit `config.host`;
|
|
40
|
-
- generated initializers no longer read `CHRONOS_HOST`, while explicit `config.host` assignments remain supported.
|
|
23
|
+
- W3C identifiers are syntax-validated, all-zero IDs are rejected, and Rails error reporter context is reduced to bounded allowlisted metadata.
|
|
41
24
|
|
|
42
25
|
## [1.1.0] - 2026-08-05
|
|
43
26
|
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Chronos Ruby
|
|
2
2
|
|
|
3
|
-
Chronos Ruby 1.1.
|
|
3
|
+
Chronos Ruby 1.1.0 é o agente independente de framework para enviar exceções e telemetria limitada de aplicações Ruby ao Chronos. Esta é a linha estável legado, compatível com o protocolo v1 e voltada a Ruby 2.2.10–2.6.
|
|
4
4
|
|
|
5
5
|
## O que a gem coleta
|
|
6
6
|
|
|
@@ -24,7 +24,7 @@ A gem não varre variáveis de ambiente, sistema de arquivos ou lockfiles e não
|
|
|
24
24
|
|
|
25
25
|
## Versões Ruby e Rails suportadas
|
|
26
26
|
|
|
27
|
-
A versão 1.1
|
|
27
|
+
A versão candidata 1.2.0.pre.1 inicia a linha transitional para Ruby 2.7–3.4, Rails 7.x e Sidekiq 7. Ela adiciona contexto por Fiber, Rails Error Reporter, Action Cable, Faraday, Trace Context W3C opcional e coexistência com um SDK OpenTelemetry já configurado. Use-a explicitamente em staging enquanto a matriz transitional é validada; as linhas legadas permanecem disponíveis em releases anteriores.
|
|
28
28
|
|
|
29
29
|
Rubies e frameworks antigos estão fora do suporte de segurança de seus mantenedores. A Chronos oferece compatibilidade técnica, não manutenção de segurança do runtime. Veja [Compatibilidade](docs/compatibility.md).
|
|
30
30
|
|
|
@@ -33,7 +33,7 @@ Rubies e frameworks antigos estão fora do suporte de segurança de seus mantene
|
|
|
33
33
|
Obrigatório: adicione a versão estável ao `Gemfile`.
|
|
34
34
|
|
|
35
35
|
```ruby
|
|
36
|
-
gem "chronos-ruby", "~> 1.1.
|
|
36
|
+
gem "chronos-ruby", "~> 1.1.0"
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Em runtimes antigos, use Bundler compatível:
|
|
@@ -46,7 +46,7 @@ bundle _1.17.3_ install
|
|
|
46
46
|
Sem Bundler:
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
gem install chronos-ruby -v 1.1.
|
|
49
|
+
gem install chronos-ruby -v 1.1.0
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
## Instalação em Rails
|
|
@@ -54,7 +54,7 @@ gem install chronos-ruby -v 1.1.3
|
|
|
54
54
|
Obrigatório: carregue a integração Rails explicitamente para manter Rails/ActiveSupport fora de aplicações Ruby puras.
|
|
55
55
|
|
|
56
56
|
```ruby
|
|
57
|
-
gem "chronos-ruby", "~> 1.1.
|
|
57
|
+
gem "chronos-ruby", "~> 1.1.0", :require => "chronos/rails"
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
Gere o initializer:
|
|
@@ -67,8 +67,7 @@ A Versão 0.5 introduziu Railtie, middleware e subscribers idempotentes por APIs
|
|
|
67
67
|
|
|
68
68
|
## Configuração mínima
|
|
69
69
|
|
|
70
|
-
Obrigatório quando o agente está habilitado: `project_id
|
|
71
|
-
`https://chronosmonitor.com.br` por padrão. Recomendado: definir ambiente e serviço explicitamente.
|
|
70
|
+
Obrigatório quando o agente está habilitado: `project_id`, `project_key` e `host` HTTPS. Recomendado: definir ambiente e serviço explicitamente.
|
|
72
71
|
|
|
73
72
|
```ruby
|
|
74
73
|
require "chronos"
|
|
@@ -76,6 +75,7 @@ require "chronos"
|
|
|
76
75
|
Chronos.configure do |config|
|
|
77
76
|
config.project_id = ENV["CHRONOS_PROJECT_ID"]
|
|
78
77
|
config.project_key = ENV["CHRONOS_PROJECT_KEY"]
|
|
78
|
+
config.host = "https://chronos.example.com"
|
|
79
79
|
config.environment = ENV["APP_ENV"] || "production"
|
|
80
80
|
config.service_name = "billing"
|
|
81
81
|
config.app_version = ENV["APP_VERSION"]
|
|
@@ -204,16 +204,16 @@ Por padrão, SQL bruto e binds não são lidos pelo pipeline de análise. A insp
|
|
|
204
204
|
|
|
205
205
|
## Sidekiq e Active Job
|
|
206
206
|
|
|
207
|
-
A
|
|
207
|
+
A integração mantém o require explícito e suporta a API pública de middleware do Sidekiq 7:
|
|
208
|
+
|
|
209
|
+
O suporte histórico começou em `0.6.0.pre.1`; aplicações em Sidekiq 4/5 devem permanecer numa release legada compatível.
|
|
208
210
|
|
|
209
211
|
```ruby
|
|
210
212
|
gem "sidekiq", "~> 5.0"
|
|
211
|
-
gem "chronos-ruby", "~> 1.1.
|
|
213
|
+
gem "chronos-ruby", "~> 1.1.0", :require => "chronos/sidekiq"
|
|
212
214
|
```
|
|
213
215
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
O envelope de contexto não altera argumentos públicos e contém somente IDs limitados de trace/request. Active Job usa um campo serializado com namespace (`chronos_context`) e hooks públicos. Erros aninhados são deduplicados e reerguidos. Veja [Sidekiq legado](docs/modules/sidekiq-legacy.md), [Active Job](docs/modules/active-job.md) e [Jobs](docs/modules/job-monitoring.md).
|
|
216
|
+
O envelope de contexto não altera argumentos públicos e contém somente IDs limitados de trace/span/request e flags. Active Job usa um campo serializado com namespace (`chronos_context`) e hooks públicos. Erros aninhados são deduplicados e reerguidos. Veja [Sidekiq legado](docs/modules/sidekiq-legacy.md), [Active Job](docs/modules/active-job.md) e [Jobs](docs/modules/job-monitoring.md).
|
|
217
217
|
|
|
218
218
|
## Deploy tracking
|
|
219
219
|
|
|
@@ -263,6 +263,7 @@ A gem não varre o ambiente. Leia somente variáveis escolhidas pela aplicação
|
|
|
263
263
|
Chronos.configure do |config|
|
|
264
264
|
config.project_id = ENV["CHRONOS_PROJECT_ID"]
|
|
265
265
|
config.project_key = ENV["CHRONOS_PROJECT_KEY"]
|
|
266
|
+
config.host = ENV["CHRONOS_HOST"]
|
|
266
267
|
config.environment = ENV["APP_ENV"] || "production"
|
|
267
268
|
config.enabled = ENV["CHRONOS_ENABLED"] != "false"
|
|
268
269
|
config.queue_size = 100
|
|
@@ -320,7 +321,7 @@ Execute suíte e lint no runtime atual:
|
|
|
320
321
|
bundle _1.17.3_ exec rake
|
|
321
322
|
```
|
|
322
323
|
|
|
323
|
-
A matriz CI cobre
|
|
324
|
+
A matriz CI cobre a linha transitional e os checks de pacote/documentação; workflows legados preservam evidência das releases anteriores.
|
|
324
325
|
|
|
325
326
|
## Contribuição
|
|
326
327
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Status
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Aceito para 1.2.
|
|
6
6
|
|
|
7
7
|
## Contexto
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ O Chronos precisa correlacionar trace/request sem duplicar SDKs ou impor depend
|
|
|
10
10
|
|
|
11
11
|
## Decisão
|
|
12
12
|
|
|
13
|
-
Manter IDs de correlação e portas independentes do fornecedor
|
|
13
|
+
Manter IDs de correlação e portas independentes do fornecedor. Na 1.2, a ponte opcional consulta somente o span atual de um SDK já carregado, traduz `trace_id`, `span_id` e flags, e nunca instala SDK, instrumentação ou exporter. IDs Chronos explícitos têm precedência; a presença de OTel deve ser usada pelas integrações para evitar spans paralelos equivalentes.
|
|
14
14
|
|
|
15
15
|
## Alternativas
|
|
16
16
|
|
|
@@ -22,4 +22,4 @@ O protocolo v1 permanece estável e aplicações legadas não recebem novas depe
|
|
|
22
22
|
|
|
23
23
|
## Consequências negativas
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
A ponte não exporta spans OTel completos nem controla exporters; consumidores que precisam desses dados continuam responsáveis pela configuração do SDK.
|
data/docs/compatibility.md
CHANGED
|
@@ -1,39 +1,33 @@
|
|
|
1
1
|
# Compatibility
|
|
2
2
|
|
|
3
|
-
Chronos Ruby 1.1 is the
|
|
3
|
+
Chronos Ruby 1.2.0.pre.1 is the first candidate of the transitional line for Rails 7 and Sidekiq 7. Combinations remain `Best effort` until their dedicated CI and real-application gates pass. Technical compatibility does not make an end-of-life Ruby, Rails, Rack, or Sidekiq release secure. Versions 1.0 and 1.1 remain the frozen legacy line.
|
|
4
4
|
|
|
5
5
|
## Core and Rack
|
|
6
6
|
|
|
7
7
|
| Ruby | Status | Evidence |
|
|
8
8
|
|---|---|---|
|
|
9
|
-
| 2.2
|
|
10
|
-
|
|
|
11
|
-
| 2.
|
|
12
|
-
| 2.5.9 | Supported | Same dedicated Docker gate |
|
|
13
|
-
| 2.6.10 | Supported | Same dedicated Docker gate |
|
|
14
|
-
| 2.7 and newer | Unsupported in 1.x legacy | Belongs to the transitional or modern lines |
|
|
9
|
+
| 2.7–3.2 | Best effort | Transitional matrix introduced in this candidate; promotion requires green CI evidence |
|
|
10
|
+
| 3.3–3.4 | Best effort | Core checks run in modern CI; Rails 8-specific behavior belongs to 2.x |
|
|
11
|
+
| Earlier than 2.7 | Unsupported in 1.2 | Use an appropriate frozen legacy release |
|
|
15
12
|
|
|
16
13
|
## Rails
|
|
17
14
|
|
|
18
15
|
| Ruby | Rails | Status | Evidence |
|
|
19
16
|
|---|---|---|---|
|
|
20
|
-
| 2.2
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
| 2.6.10 | 5.2 | Supported | Same dedicated application gate |
|
|
24
|
-
| Other Ruby/Rails pairs | — | Unsupported | No complete release gate; feature detection alone is not a support claim |
|
|
17
|
+
| 2.7–3.2 | 7.0–7.1 | Best effort | Real Rails applications and the complete integration gate are pending |
|
|
18
|
+
| 3.1–3.4 | 7.2 | Best effort | Feature and package checks; use a validated application combination before production rollout |
|
|
19
|
+
| Rails 4–6 | — | Unsupported in 1.2 | Use a matching earlier Chronos release |
|
|
25
20
|
|
|
26
21
|
## Sidekiq
|
|
27
22
|
|
|
28
23
|
| Ruby | Sidekiq | Status | Evidence |
|
|
29
24
|
|---|---|---|---|
|
|
30
|
-
| 2.
|
|
31
|
-
|
|
|
32
|
-
| Other Ruby/Sidekiq pairs | — | Unsupported | No complete release gate |
|
|
25
|
+
| 2.7–3.4 | 7.x | Best effort | Real Sidekiq 7 smoke applications are pending |
|
|
26
|
+
| Sidekiq 4–6 | — | Unsupported in 1.2 | Use a matching earlier Chronos release |
|
|
33
27
|
|
|
34
28
|
Active Job uses the public `serialize`, `deserialize`, and `perform_now` extension points with a bounded namespaced field. Support follows the validated Rails pairs above. Adapters that bypass these hooks require their own evidence.
|
|
35
29
|
|
|
36
|
-
|
|
30
|
+
Historical evidence remains in [Version 1.0 readiness](release-1.0-readiness.md) and [Version 1.1 readiness](release-1.1-readiness.md).
|
|
37
31
|
|
|
38
32
|
Status meanings:
|
|
39
33
|
|
data/docs/configuration.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|---|---:|---|---|
|
|
7
7
|
| `project_id` | Yes when enabled | `nil` | Public project identifier included in the envelope |
|
|
8
8
|
| `project_key` | Yes when enabled | `nil` | Secret authentication key sent only as an HTTP header |
|
|
9
|
-
| `host` |
|
|
9
|
+
| `host` | Yes when enabled | `nil` | Absolute Chronos HTTP endpoint; HTTPS is required by default |
|
|
10
10
|
| `environment` | Recommended | `production` | Application environment |
|
|
11
11
|
| `app_version` | Optional | `nil` | Application release/version identifier |
|
|
12
12
|
| `service_name` | Recommended | `nil` | Logical service name |
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
| `sampling_rate` | Optional | `1.0` | Local upper bound for event sampling |
|
|
48
48
|
| `enabled_event_types` | Optional | exception, request, query, job, cache, external_http, dependencies, deploy, metric_batch | Local allowlist for supported event envelopes |
|
|
49
49
|
| `max_remote_send_interval` | Optional | `60.0` | Local upper bound for remotely requested send spacing |
|
|
50
|
-
| `context_store` | Optional | `:
|
|
50
|
+
| `context_store` | Optional | `:fiber_local` | `:fiber_local`, `:thread_local`, or an object implementing `get`, `set`, `clear`, and `with_context` |
|
|
51
51
|
| `breadcrumb_capacity` | Optional | `20` | Positive count of newest breadcrumbs retained per execution |
|
|
52
52
|
| `breadcrumb_max_bytes` | Optional | `2048` | Maximum bytes per normalized breadcrumb; minimum `128` |
|
|
53
53
|
| `rails_enabled` | Optional | `true` | Enables automatic Rails middleware and subscribers |
|
|
@@ -75,6 +75,8 @@
|
|
|
75
75
|
| `apm_transaction_max_connections` | Optional | `100` | Maximum concurrently tracked transaction connections; range 1–500 |
|
|
76
76
|
| `external_http_enabled` | Optional | `false` | Allows explicit per-instance outbound `Net::HTTP` instrumentation |
|
|
77
77
|
| `external_http_trace_headers` | Optional | `true` | Propagates Chronos trace/request headers on instrumented requests |
|
|
78
|
+
| `w3c_trace_context` | Optional | `false` | Injects a validated W3C `traceparent` header when trace and span IDs exist |
|
|
79
|
+
| `opentelemetry_bridge` | Optional | `true` | Consumes the current OpenTelemetry span when an SDK is already active; installs nothing |
|
|
78
80
|
| `cache_key_mode` | Optional | `:none` | `:none` omits keys; `:sha256` emits a project-scoped key hash |
|
|
79
81
|
| `dependency_reporting` | Optional | `true` | Emits one bounded dependency event per configured agent |
|
|
80
82
|
| `dependency_max_items` | Optional | `100` | Loaded gem entries retained in the inventory; range 1–200 |
|
|
@@ -100,7 +102,7 @@ Chronos.configure do |config|
|
|
|
100
102
|
config.max_retries = 3
|
|
101
103
|
config.backlog_size = 100
|
|
102
104
|
config.circuit_failure_threshold = 5
|
|
103
|
-
config.context_store = :
|
|
105
|
+
config.context_store = :fiber_local
|
|
104
106
|
config.breadcrumb_capacity = 20
|
|
105
107
|
config.rails_capture_in_test = false
|
|
106
108
|
config.rails_capture_in_console = false
|
|
@@ -125,6 +127,8 @@ Chronos.configure do |config|
|
|
|
125
127
|
config.apm_transaction_max_connections = 100
|
|
126
128
|
config.external_http_enabled = false
|
|
127
129
|
config.external_http_trace_headers = true
|
|
130
|
+
config.w3c_trace_context = false
|
|
131
|
+
config.opentelemetry_bridge = true
|
|
128
132
|
config.cache_key_mode = :none
|
|
129
133
|
config.dependency_reporting = true
|
|
130
134
|
config.dependency_max_items = 100
|
data/docs/modules/context.md
CHANGED
|
@@ -6,7 +6,7 @@ O contexto relaciona uma exceção ou métrica ao request/job atual sem criar de
|
|
|
6
6
|
|
|
7
7
|
## Fluxo e classes
|
|
8
8
|
|
|
9
|
-
`Chronos::Ports::ContextStore` define `get`, `set`, `clear` e `with_context`. Na linha
|
|
9
|
+
`Chronos::Ports::ContextStore` define `get`, `set`, `clear` e `with_context`. Na linha 1.2, `Chronos::Adapters::FiberLocalContextStore` usa storage do Fiber quando disponível e volta com segurança ao adapter thread-local. A fachada combina o contexto explícito com o escopo atual; o serializer sanitiza e limita tudo antes da fila. Rack limpa o escopo em `ensure`, enquanto Sidekiq e Active Job propagam somente `trace_id`, `span_id`, `trace_flags` e `request_id`.
|
|
10
10
|
|
|
11
11
|
## Extensão, riscos e exemplo
|
|
12
12
|
|
|
@@ -10,6 +10,7 @@ Chronos.configure do |config|
|
|
|
10
10
|
# connection settings omitted
|
|
11
11
|
config.external_http_enabled = true
|
|
12
12
|
config.external_http_trace_headers = true
|
|
13
|
+
config.w3c_trace_context = true
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
http = Net::HTTP.new("payments.example.com", 443)
|
|
@@ -18,10 +19,10 @@ Chronos.instrument_net_http(http)
|
|
|
18
19
|
response = http.request(Net::HTTP::Get.new("/health"))
|
|
19
20
|
```
|
|
20
21
|
|
|
21
|
-
The event contains a bounded lowercase host, uppercase method, response status, monotonic duration, timeout flag, connection-error flag, and error class. A request made inside a Chronos context receives `X-Chronos-Trace-ID` and `X-Chronos-Request-ID` unless the application already set those headers. Disable propagation with `external_http_trace_headers = false`.
|
|
22
|
+
The event contains a bounded lowercase host, uppercase method, response status, monotonic duration, timeout flag, connection-error flag, and error class. A request made inside a Chronos context receives `X-Chronos-Trace-ID` and `X-Chronos-Request-ID` unless the application already set those headers. With `w3c_trace_context = true`, Net::HTTP and `Chronos::Integrations::FaradayMiddleware` also preserve an existing header or inject a validated `traceparent`. Disable all propagation with `external_http_trace_headers = false`.
|
|
22
23
|
|
|
23
24
|
The wrapper never reads or records the path, query string, Authorization, other request headers, request body, response headers/body, or exception message. The native streaming block is forwarded and the identical HTTP exception is re-raised. Telemetry failures are contained.
|
|
24
25
|
|
|
25
|
-
Successful and failed calls become bounded `external_http` APM groups keyed only by host and method. A call carrying a trace ID contributes its duration to the enclosing request's `external_http` breakdown. Faraday
|
|
26
|
+
Successful and failed calls become bounded `external_http` APM groups keyed only by host and method. A call carrying a trace ID contributes its duration to the enclosing request's `external_http` breakdown. Faraday is supported through explicit middleware installation; HTTP.rb, Excon, and RestClient remain outside this release.
|
|
26
27
|
|
|
27
28
|
Installation is idempotent per object. A `false` result means collection is disabled, the object is incompatible or already instrumented, or installation was contained after an internal error.
|
|
@@ -16,7 +16,7 @@ Run:
|
|
|
16
16
|
rails generate chronos:install
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
The generator creates `config/initializers/chronos.rb`. The
|
|
19
|
+
The generator creates `config/initializers/chronos.rb`. The template reads only explicitly named `CHRONOS_*` variables, uses `Rails.env`, adopts `Rails.logger` when available, and disables automatic integration in test and console by default. It invokes the idempotent installer as a fallback for applications that disabled Bundler auto-require, so the Railtie and initializer paths cannot create duplicate hooks. It never scans all environment variables or modifies routes and application classes.
|
|
20
20
|
|
|
21
21
|
## Captured integrations
|
|
22
22
|
|
|
@@ -57,4 +57,4 @@ The repository contains independent applications under `examples/rails-4.2` and
|
|
|
57
57
|
|
|
58
58
|
## Limits
|
|
59
59
|
|
|
60
|
-
Version 0.7 aggregates controller, SQL, and job timings into bounded APM batches. SQL literals and binds remain excluded while a bounded normalized query and fingerprint are produced. Sidekiq remains
|
|
60
|
+
Version 0.7 aggregates controller, SQL, and job timings into bounded APM batches. SQL literals and binds remain excluded while a bounded normalized query and fingerprint are produced. Sidekiq support remains a separate optional integration. Version `0.9.0.pre.2` provides bounded Active Job trace/request propagation through a namespaced serialized field; adapters that replace the standard Active Job serialization/execution hooks require separate compatibility evidence.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Sidekiq 4/5 legacy integration
|
|
2
2
|
|
|
3
|
-
Version `0.6.0.pre.1` starts the legacy jobs line with optional Sidekiq 4 and 5 client and server middleware.
|
|
3
|
+
Version `0.6.0.pre.1` starts the legacy jobs line with optional Sidekiq 4 and 5 client and server middleware. Load it after declaring Sidekiq:
|
|
4
4
|
|
|
5
5
|
```ruby
|
|
6
6
|
gem "sidekiq", "~> 5.0"
|
|
7
|
-
gem "chronos-ruby", "~> 1.1.
|
|
7
|
+
gem "chronos-ruby", "~> 1.1.0", :require => "chronos/sidekiq"
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
`chronos/sidekiq` installs middleware through the public `configure_client` and `configure_server` APIs. It does nothing when Sidekiq is unavailable, and the core gem never requires Sidekiq. Installation adds no Chronos thread or Redis/database connection per job; delivery continues through the agent's existing fixed worker pool.
|
|
11
11
|
|
|
12
12
|
The client middleware adds a top-level `chronos` metadata object to the Sidekiq envelope. It never changes the public `args` array. Only `trace_id` and `request_id` propagate, with schema version and enqueue time. The server scopes that context for the worker, measures duration and calculable queue latency, and emits one `job` event.
|
|
13
13
|
|
data/docs/troubleshooting.md
CHANGED
|
@@ -56,7 +56,7 @@ Require `chronos/capistrano` after the Capistrano/Rake task DSL is loaded. The i
|
|
|
56
56
|
|
|
57
57
|
## Sidekiq telemetry is missing
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Require `chronos/sidekiq` after Sidekiq is available and configure Chronos before jobs run. The entry point uses Sidekiq's public client/server middleware configuration and remains optional. Requiring only `chronos` or `chronos/rails` does not load Sidekiq. A job already enqueued before client middleware installation may lack propagated trace context, but server timing and failure capture can still run.
|
|
60
60
|
|
|
61
61
|
## A failed Sidekiq job appears twice
|
|
62
62
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Chronos
|
|
2
|
+
module Adapters
|
|
3
|
+
# Stores execution context on the current Fiber when Ruby exposes Fiber storage.
|
|
4
|
+
#
|
|
5
|
+
# @responsibility Isolate context between concurrent fibers and restore nested scopes.
|
|
6
|
+
# @motivation Rails 7 applications increasingly multiplex work on one thread.
|
|
7
|
+
# @limits Fiber storage is not propagated automatically to newly-created fibers.
|
|
8
|
+
# @collaborators ContextStore port and Agent composition root.
|
|
9
|
+
# @thread_safety Each fiber owns its value and may be used from concurrent threads.
|
|
10
|
+
# @compatibility Ruby 3.2+ Fiber storage; falls back to thread-local storage otherwise.
|
|
11
|
+
# @example
|
|
12
|
+
# store.with_context(:request_id => "r1") { store.get }
|
|
13
|
+
# @errors Previous context is restored even when the block raises.
|
|
14
|
+
# @performance Constant-time storage operations with a bounded hash merge.
|
|
15
|
+
class FiberLocalContextStore
|
|
16
|
+
def initialize(fallback = ThreadLocalContextStore.new)
|
|
17
|
+
@key = "chronos_context_#{object_id}".to_sym
|
|
18
|
+
@fallback = fallback
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def get
|
|
22
|
+
supported? ? (Fiber[@key] || {}) : @fallback.get
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def set(context)
|
|
26
|
+
raise ArgumentError, "context must be a Hash" unless context.is_a?(Hash)
|
|
27
|
+
|
|
28
|
+
supported? ? Fiber[@key] = context : @fallback.set(context)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def clear
|
|
32
|
+
supported? ? Fiber[@key] = nil : @fallback.clear
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def with_context(context)
|
|
37
|
+
previous = get
|
|
38
|
+
set(previous.merge(valid_context(context)))
|
|
39
|
+
yield
|
|
40
|
+
ensure
|
|
41
|
+
previous && !previous.empty? ? set(previous) : clear
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def supported?
|
|
47
|
+
Fiber.respond_to?(:[]) && Fiber.respond_to?(:[]=)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def valid_context(context)
|
|
51
|
+
raise ArgumentError, "context must be a Hash" unless context.is_a?(Hash)
|
|
52
|
+
|
|
53
|
+
context
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/chronos/agent.rb
CHANGED
|
@@ -148,7 +148,8 @@ module Chronos
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def external_http_integration_options
|
|
151
|
-
{:enabled => @config.external_http_enabled, :trace_headers => @config.external_http_trace_headers
|
|
151
|
+
{:enabled => @config.external_http_enabled, :trace_headers => @config.external_http_trace_headers,
|
|
152
|
+
:w3c_trace_context => @config.w3c_trace_context}
|
|
152
153
|
end
|
|
153
154
|
|
|
154
155
|
def cache_integration_options
|
|
@@ -165,6 +166,10 @@ module Chronos
|
|
|
165
166
|
"request_id" => nested["request_id"] || nested[:request_id] ||
|
|
166
167
|
request["request_id"] || request[:request_id]
|
|
167
168
|
}
|
|
169
|
+
if @config.opentelemetry_bridge
|
|
170
|
+
otel = Integrations::OpenTelemetry.current_context
|
|
171
|
+
values = otel.merge(values.delete_if { |_key, value| value.to_s.empty? })
|
|
172
|
+
end
|
|
168
173
|
values.delete_if { |_key, value| value.to_s.empty? }
|
|
169
174
|
rescue StandardError
|
|
170
175
|
{}
|
|
@@ -237,6 +242,7 @@ module Chronos
|
|
|
237
242
|
|
|
238
243
|
def build_context_store(strategy)
|
|
239
244
|
return Adapters::ThreadLocalContextStore.new if strategy == :thread_local
|
|
245
|
+
return Adapters::FiberLocalContextStore.new if strategy == :fiber_local
|
|
240
246
|
|
|
241
247
|
strategy
|
|
242
248
|
end
|
|
@@ -110,6 +110,8 @@ module Chronos
|
|
|
110
110
|
errors = []
|
|
111
111
|
errors << "external_http_enabled must be true or false" unless boolean?(external_http_enabled)
|
|
112
112
|
errors << "external_http_trace_headers must be true or false" unless boolean?(external_http_trace_headers)
|
|
113
|
+
errors << "w3c_trace_context must be true or false" unless boolean?(w3c_trace_context)
|
|
114
|
+
errors << "opentelemetry_bridge must be true or false" unless boolean?(opentelemetry_bridge)
|
|
113
115
|
errors << "cache_key_mode must be :none or :sha256" unless [:none, :sha256].include?(cache_key_mode)
|
|
114
116
|
errors << "dependency_reporting must be true or false" unless boolean?(dependency_reporting)
|
|
115
117
|
unless dependency_max_items.is_a?(Integer) && dependency_max_items >= 1 && dependency_max_items <= 200
|
|
@@ -3,7 +3,7 @@ module Chronos
|
|
|
3
3
|
#
|
|
4
4
|
# @responsibility Expose validated settings without mutable containers.
|
|
5
5
|
# @motivation Keep capture behavior stable while multiple threads run.
|
|
6
|
-
# @limits
|
|
6
|
+
# @limits It cannot be edited after creation.
|
|
7
7
|
# @collaborators Configuration and runtime services.
|
|
8
8
|
# @thread_safety Safe to share between threads after construction.
|
|
9
9
|
# @compatibility Ruby 2.2.10 through Ruby 2.6.
|
|
@@ -17,7 +17,7 @@ module Chronos
|
|
|
17
17
|
def initialize(values)
|
|
18
18
|
Configuration::ATTRIBUTES.each do |attribute|
|
|
19
19
|
value = values[attribute]
|
|
20
|
-
deep_freeze(value)
|
|
20
|
+
deep_freeze(value)
|
|
21
21
|
instance_variable_set("@#{attribute}", value)
|
|
22
22
|
end
|
|
23
23
|
freeze
|
|
@@ -67,8 +67,8 @@ module Chronos
|
|
|
67
67
|
|
|
68
68
|
def context_errors
|
|
69
69
|
errors = []
|
|
70
|
-
unless
|
|
71
|
-
errors << "context_store must be :thread_local or implement get, set, clear, and with_context"
|
|
70
|
+
unless [:thread_local, :fiber_local].include?(context_store) || compatible_context_store?
|
|
71
|
+
errors << "context_store must be :thread_local, :fiber_local, or implement get, set, clear, and with_context"
|
|
72
72
|
end
|
|
73
73
|
errors << "breadcrumb_capacity must be a positive integer" unless positive_integer?(breadcrumb_capacity)
|
|
74
74
|
unless breadcrumb_max_bytes.is_a?(Integer) && breadcrumb_max_bytes >= 128
|
|
@@ -23,7 +23,6 @@ module Chronos
|
|
|
23
23
|
class Configuration
|
|
24
24
|
include Internal::ConfigurationValidation
|
|
25
25
|
include Internal::ApmConfigurationValidation
|
|
26
|
-
DEFAULT_HOST = "https://chronosmonitor.com.br".freeze
|
|
27
26
|
DEFAULT_BLOCKLIST_KEYS = %w(
|
|
28
27
|
password password_confirmation passwd secret api_key apikey authorization
|
|
29
28
|
token access_token refresh_token private_key client_secret cookie set-cookie
|
|
@@ -55,6 +54,7 @@ module Chronos
|
|
|
55
54
|
:apm_query_inspection_min_duration_ms, :apm_query_inspection_max_queries,
|
|
56
55
|
:apm_transaction_tracking_enabled, :apm_transaction_max_connections,
|
|
57
56
|
:external_http_enabled, :external_http_trace_headers,
|
|
57
|
+
:w3c_trace_context, :opentelemetry_bridge,
|
|
58
58
|
:cache_key_mode, :dependency_reporting, :dependency_max_items
|
|
59
59
|
].freeze
|
|
60
60
|
|
|
@@ -106,7 +106,7 @@ module Chronos
|
|
|
106
106
|
def initialize_core_defaults
|
|
107
107
|
@project_id = nil
|
|
108
108
|
@project_key = nil
|
|
109
|
-
@host =
|
|
109
|
+
@host = nil
|
|
110
110
|
@environment = "production"
|
|
111
111
|
@app_version = nil
|
|
112
112
|
@service_name = nil
|
|
@@ -124,7 +124,7 @@ module Chronos
|
|
|
124
124
|
@user_agent = "chronos-ruby/#{Chronos::VERSION}"
|
|
125
125
|
@max_payload_size = 1_048_576
|
|
126
126
|
@gzip = false
|
|
127
|
-
@context_store = :
|
|
127
|
+
@context_store = :fiber_local
|
|
128
128
|
@breadcrumb_capacity = 20
|
|
129
129
|
@breadcrumb_max_bytes = 2048
|
|
130
130
|
end
|
|
@@ -168,6 +168,8 @@ module Chronos
|
|
|
168
168
|
def initialize_observability_defaults
|
|
169
169
|
@external_http_enabled = false
|
|
170
170
|
@external_http_trace_headers = true
|
|
171
|
+
@w3c_trace_context = false
|
|
172
|
+
@opentelemetry_bridge = true
|
|
171
173
|
@cache_key_mode = :none
|
|
172
174
|
@dependency_reporting = true
|
|
173
175
|
@dependency_max_items = 100
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Chronos
|
|
2
|
+
module Core
|
|
3
|
+
# Parses and formats the W3C Trace Context headers without an OpenTelemetry dependency.
|
|
4
|
+
module TraceContext
|
|
5
|
+
TRACEPARENT = /\A([\da-f]{2})-([\da-f]{32})-([\da-f]{16})-([\da-f]{2})\z/.freeze
|
|
6
|
+
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def parse(value)
|
|
10
|
+
match = TRACEPARENT.match(value.to_s.downcase)
|
|
11
|
+
return {} unless match && match[1] == "00"
|
|
12
|
+
return {} if match[2] == ("0" * 32) || match[3] == ("0" * 16)
|
|
13
|
+
|
|
14
|
+
{"trace_id" => match[2], "span_id" => match[3], "trace_flags" => match[4]}
|
|
15
|
+
rescue StandardError
|
|
16
|
+
{}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def format(context)
|
|
20
|
+
trace_id = value(context, "trace_id")
|
|
21
|
+
span_id = value(context, "span_id")
|
|
22
|
+
flags = value(context, "trace_flags")
|
|
23
|
+
return nil unless trace_id =~ /\A[\da-f]{32}\z/ && span_id =~ /\A[\da-f]{16}\z/
|
|
24
|
+
return nil if trace_id == ("0" * 32) || span_id == ("0" * 16)
|
|
25
|
+
|
|
26
|
+
"00-#{trace_id}-#{span_id}-#{flags =~ /\A[\da-f]{2}\z/ ? flags : '01'}"
|
|
27
|
+
rescue StandardError
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def value(context, key)
|
|
32
|
+
return "" unless context.is_a?(Hash)
|
|
33
|
+
|
|
34
|
+
(context[key] || context[key.to_sym]).to_s.downcase
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -40,7 +40,7 @@ module Chronos
|
|
|
40
40
|
def envelope(notifier)
|
|
41
41
|
source = notifier.respond_to?(:propagation_context) ? notifier.propagation_context : {}
|
|
42
42
|
source = {} unless source.is_a?(Hash)
|
|
43
|
-
context = %w(trace_id request_id).each_with_object({}) do |key, result|
|
|
43
|
+
context = %w(trace_id span_id trace_flags request_id).each_with_object({}) do |key, result|
|
|
44
44
|
value = source[key] || source[key.to_sym]
|
|
45
45
|
result[key] = bounded(value) unless value.to_s.empty?
|
|
46
46
|
end
|
|
@@ -57,7 +57,7 @@ module Chronos
|
|
|
57
57
|
source = value["context"] || value[:context]
|
|
58
58
|
return {} unless source.is_a?(Hash)
|
|
59
59
|
|
|
60
|
-
%w(trace_id request_id).each_with_object({}) do |key, result|
|
|
60
|
+
%w(trace_id span_id trace_flags request_id).each_with_object({}) do |key, result|
|
|
61
61
|
candidate = source[key] || source[key.to_sym]
|
|
62
62
|
result[key] = bounded(candidate) unless candidate.to_s.empty?
|
|
63
63
|
end
|