exis_ray 0.5.11 → 0.7.0
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 +12 -0
- data/CLAUDE.md +12 -4
- data/README.md +17 -2
- data/lib/exis_ray/configuration.rb +47 -2
- data/lib/exis_ray/json_formatter.rb +24 -1
- data/lib/exis_ray/log_subscriber.rb +161 -3
- data/lib/exis_ray/railtie.rb +13 -14
- data/lib/exis_ray/task_monitor.rb +23 -5
- data/lib/exis_ray/version.rb +1 -1
- data/skill/SKILL.md +9 -3
- data/skill/references/standard.md +155 -0
- data/skills.lock +10 -1
- data/skills.yml +34 -9
- data/spec/exis_ray/configuration_spec.rb +73 -4
- data/spec/exis_ray/json_formatter_spec.rb +72 -0
- data/spec/exis_ray/log_subscriber_spec.rb +326 -0
- data/spec/exis_ray/task_monitor_spec.rb +108 -0
- metadata +7 -15
- data/.agents/skills/agent-review/SKILL.md +0 -213
- data/.agents/skills/ai-reports/SKILL.md +0 -211
- data/.agents/skills/documentation-writer/SKILL.md +0 -45
- data/.agents/skills/gem-release/SKILL.md +0 -116
- data/.agents/skills/quality-code/SKILL.md +0 -51
- data/.agents/skills/skill-builder/SKILL.md +0 -293
- data/.agents/skills/skill-manager/SKILL.md +0 -172
- data/.agents/skills/skill-manager/scripts/sync.rb +0 -310
- data/.agents/skills/yard/SKILL.md +0 -311
- data/.agents/skills/yard/references/tipos.md +0 -144
- data/MANIFEST.md +0 -222
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Estándar de Logging Wispro — Complemento
|
|
2
|
+
|
|
3
|
+
> Este documento recoge las reglas del estándar de logging del ecosistema Wispro que **no** están ya cubiertas en `SKILL.md`. Para formato general (`component=x event=y`), niveles, `source`, DEBUG block form, reloj monotónico, filtrado de claves sensibles y campos auto-inyectados, ver `SKILL.md`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Data First — Unidad en la key, número en el valor
|
|
8
|
+
|
|
9
|
+
Regla de oro para métricas operables: **separar la unidad del dato numérico**. Nunca incluir unidades dentro de los valores.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
# Incorrecto
|
|
13
|
+
duration="0.5s" memory="128MB"
|
|
14
|
+
|
|
15
|
+
# Correcto
|
|
16
|
+
duration_s=0.5 memory_mb=128
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Sufijos de unidad estándar:
|
|
20
|
+
|
|
21
|
+
| Sufijo | Tipo | Uso |
|
|
22
|
+
|:---------|:--------|:----|
|
|
23
|
+
| `_s` | Float | Segundos. Estándar para duraciones y latencias. |
|
|
24
|
+
| `_ms` | Integer | Milisegundos. Precisión técnica interna de alta frecuencia. |
|
|
25
|
+
| `_count` | Integer | Cantidades o volúmenes. Ej: `record_count`, `retry_count`. |
|
|
26
|
+
| `_bytes` / `_kb` / `_mb` | Integer | Almacenamiento o memoria. |
|
|
27
|
+
| `_human` | String | (Opcional) Texto legible. Ej: `duration_human="2 minutes 5 seconds"`. |
|
|
28
|
+
|
|
29
|
+
Los valores numéricos se emiten como números reales (sin comillas) para que el motor de logs haga casting automático.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Alineación con OpenTelemetry
|
|
34
|
+
|
|
35
|
+
`ExisRay` sigue el **OpenTelemetry Log Data Model**. Los campos del estándar Wispro se mapean a las convenciones semánticas oficiales de OTel:
|
|
36
|
+
|
|
37
|
+
| Campo Wispro | OTel Semantic Convention | Descripción |
|
|
38
|
+
|:--------------|:--------------------------------|:------------|
|
|
39
|
+
| `body` | `body` | Contenido principal del log (texto libre). |
|
|
40
|
+
| `level` | `severity_text` | Nivel de importancia. |
|
|
41
|
+
| `http_status` | `http.response.status_code` | Código de respuesta HTTP (Integer). |
|
|
42
|
+
| `outcome` | `otel.status_code` (enum) | Resultado semántico de tasks/jobs (`success`/`failed`). |
|
|
43
|
+
| `method` | `http.request.method` | Método HTTP. |
|
|
44
|
+
| `path` | `url.path` | Ruta del request. |
|
|
45
|
+
| `user_id` | `user.id` | Identificador del usuario. |
|
|
46
|
+
|
|
47
|
+
> **Nota sobre `duration_s`**: OTel no define un atributo genérico `duration`. Las duraciones se expresan implícitamente en spans (diferencia entre `start_time` y `end_time`), o en métricas específicas como `http.server.request.duration` (histograma en segundos, según la convención de métricas). En logs Wispro, `duration_s` es una **extensión propia** que permite queries directas sin contexto de span.
|
|
48
|
+
|
|
49
|
+
Para campos nuevos, seguir las OpenTelemetry Semantic Conventions siempre que exista una equivalencia oficial.
|
|
50
|
+
|
|
51
|
+
### Naming de campos OTel en formato flat
|
|
52
|
+
|
|
53
|
+
ExisRay emite JSON flat (ver divergencia D2 más abajo). Al mapear campos OTel al formato flat, aplicar estas reglas:
|
|
54
|
+
|
|
55
|
+
1. **Dots → underscores**: `messaging.system` → `messaging_system`, `exception.type` → `exception.type` (excepción: los campos `exception.*` mantienen el dot por estar en transición OTel).
|
|
56
|
+
2. **Preservar el prefijo semántico**: nunca abreviar el namespace OTel. `messaging.system` se convierte en `messaging_system`, **no** en `system`. El prefijo evita colisiones con otros campos del log (ej: `source: "system"` ya existe en ExisRay).
|
|
57
|
+
3. **Sufijo de unidad donde aplique**: si el campo OTel tiene unidad implícita, agregar el sufijo Wispro (`_s`, `_ms`, `_bytes`). Ej: `http.server.request.duration` → `duration_s`.
|
|
58
|
+
|
|
59
|
+
Ejemplos de mapeo existente:
|
|
60
|
+
|
|
61
|
+
| OTel Semantic Convention | Campo flat ExisRay |
|
|
62
|
+
|:-------------------------|:-------------------|
|
|
63
|
+
| `http.response.status_code` | `http_status` |
|
|
64
|
+
| `user_agent.original` | `user_agent_original` |
|
|
65
|
+
| `server.address` | `server_address` |
|
|
66
|
+
| `service.version` | `service_version` |
|
|
67
|
+
| `deployment.environment` | `deployment_environment` |
|
|
68
|
+
| `exception.type` | `exception.type` (en transición) |
|
|
69
|
+
| `messaging.system` | `messaging_system` |
|
|
70
|
+
| `messaging.operation` | `messaging_operation` |
|
|
71
|
+
| `messaging.destination.name` | `messaging_destination_name` |
|
|
72
|
+
| `messaging.message.id` | `messaging_message_id` |
|
|
73
|
+
| `messaging.rabbitmq.destination.routing_key` | `messaging_routing_key` |
|
|
74
|
+
|
|
75
|
+
**Regla de oro**: si al leer el campo aislado de su contexto no queda claro a qué dominio pertenece (ej: `system`, `operation`, `id`, `name`), le falta el prefijo.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Divergencias deliberadas con OpenTelemetry
|
|
80
|
+
|
|
81
|
+
ExisRay no pretende ser una implementación OTel. Las siguientes divergencias son decisiones conscientes con razones de peso:
|
|
82
|
+
|
|
83
|
+
### Wire format AWS X-Ray, no W3C Trace Context
|
|
84
|
+
|
|
85
|
+
OTel usa `traceparent: 00-<trace-id>-<parent-id>-<flags>`. ExisRay usa `X-Amzn-Trace-Id: Root=1-...;Self=...`.
|
|
86
|
+
|
|
87
|
+
**Razón**: toda la infraestructura Wispro vive en AWS con X-Ray como backend de trazas. Si en el futuro se migra a un backend OTel-native, la traducción ocurrirá solo en el edge (HTTP middleware), sin tocar el core.
|
|
88
|
+
|
|
89
|
+
### Flat JSON, no resource/attributes anidado
|
|
90
|
+
|
|
91
|
+
OTel Log Data Model anida: `{"Resource": {...}, "Attributes": {...}, "Body": "..."}`. ExisRay emite flat: `{"service": "...", "component": "...", ...}`.
|
|
92
|
+
|
|
93
|
+
**Razón**: los agregadores comunes (CloudWatch, Loki, Datadog) indexan mejor JSON flat. Queries como `component:auth AND event:login_failed` son triviales en flat. Un exporter OTel futuro haría el unflatten al emitir.
|
|
94
|
+
|
|
95
|
+
### Sufijos de unidad en keys (`_s`, `_ms`, `_bytes`)
|
|
96
|
+
|
|
97
|
+
OTel usa unit metadata UCUM o nombres sin sufijo. ExisRay usa sufijos explícitos.
|
|
98
|
+
|
|
99
|
+
**Razón**: en JSON flat, un campo llamado `duration` sin unidad es ambiguo. El sufijo hace que el consumidor humano y el parser automático sepan la unidad sin metadata externa (regla "Data First" Wispro).
|
|
100
|
+
|
|
101
|
+
### Campo `source` (http/sidekiq/task/system)
|
|
102
|
+
|
|
103
|
+
No tiene equivalente OTel directo. Lo más parecido es `span.kind`, pero mide otra cosa.
|
|
104
|
+
|
|
105
|
+
**Razón**: es el campo más útil para filtrado operacional — saber si un error viene de una request HTTP, un job o un consumer es la primera pregunta al mirar logs. Es una **extensión Wispro**.
|
|
106
|
+
|
|
107
|
+
### Campo `component`
|
|
108
|
+
|
|
109
|
+
OTel lo más parecido es `instrumentation.scope.name`. ExisRay lo usa para identificar el módulo de negocio (`component=billing`, `component=auth`).
|
|
110
|
+
|
|
111
|
+
**Razón**: `component` es dominio-específico y útil para filtrado operacional. Convive sin conflicto con `instrumentation.scope.name` si en el futuro se agrega el emisor técnico.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Ciclo de Vida del Evento
|
|
116
|
+
|
|
117
|
+
### Procesos, Jobs y Tasks
|
|
118
|
+
|
|
119
|
+
Todo proceso aislado debe reportar inicio y finalización con estructura consistente:
|
|
120
|
+
|
|
121
|
+
- `event`: identificador de estado (`task_started`, `task_finished`, `job_started`, `job_finished`).
|
|
122
|
+
- `outcome`: resultado final como **string semántico**, nunca un código numérico: `success`, `failed`, `aborted`.
|
|
123
|
+
- `duration_s`: tiempo total de ejecución (reloj monotónico).
|
|
124
|
+
- `error_class` y `error_message`: **obligatorios solo en caso de fallo**.
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
128
|
+
begin
|
|
129
|
+
InvoiceService.process_all
|
|
130
|
+
duration_s = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
131
|
+
Rails.logger.info("component=billing event=task_finished outcome=success duration_s=#{duration_s} record_count=500")
|
|
132
|
+
rescue => e
|
|
133
|
+
duration_s = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
|
134
|
+
Rails.logger.error("component=billing event=task_finished outcome=failed duration_s=#{duration_s} error_class=#{e.class} error_message=\"#{e.message}\"")
|
|
135
|
+
raise
|
|
136
|
+
end
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`ExisRay::TaskMonitor` implementa exactamente este contrato para Rake/Cron.
|
|
140
|
+
|
|
141
|
+
### Peticiones HTTP
|
|
142
|
+
|
|
143
|
+
Los logs de cierre de request estandarizan el reporte de rendimiento:
|
|
144
|
+
|
|
145
|
+
- `http_status`: **código HTTP como Integer** (ej: `200`, `404`, `500`).
|
|
146
|
+
- `duration_s`: tiempo total de respuesta del servidor.
|
|
147
|
+
- `[subsystem]_runtime_s`: desglose opcional por capa (`db_runtime_s`, `view_runtime_s`).
|
|
148
|
+
|
|
149
|
+
`ExisRay::LogSubscriber` emite este shape automáticamente — no hace falta loguearlo manualmente.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Regla de Oro
|
|
154
|
+
|
|
155
|
+
> Tu log manual solo debe contener datos de **tu lógica de negocio**. La infraestructura (ExisRay) ya sabe quién sos, de dónde venís y cuál es tu ID de traza — no dupliques esos campos en los logs manuales.
|
data/skills.lock
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
synced_at: '2026-04-
|
|
2
|
+
synced_at: '2026-04-05 18:20:39'
|
|
3
3
|
skills:
|
|
4
|
+
- name: action-plan
|
|
5
|
+
scope: local
|
|
6
|
+
path: "/Users/gabriel/src/gems/exis_ray/.agents/skills/action-plan"
|
|
4
7
|
- name: agent-review
|
|
5
8
|
scope: local
|
|
6
9
|
path: "/Users/gabriel/src/gems/exis_ray/.agents/skills/agent-review"
|
|
@@ -10,9 +13,15 @@ skills:
|
|
|
10
13
|
- name: documentation-writer
|
|
11
14
|
scope: local
|
|
12
15
|
path: "/Users/gabriel/src/gems/exis_ray/.agents/skills/documentation-writer"
|
|
16
|
+
- name: find-skills
|
|
17
|
+
scope: local
|
|
18
|
+
path: "/Users/gabriel/src/gems/exis_ray/.agents/skills/find-skills"
|
|
13
19
|
- name: gem-release
|
|
14
20
|
scope: local
|
|
15
21
|
path: "/Users/gabriel/src/gems/exis_ray/.agents/skills/gem-release"
|
|
22
|
+
- name: opentelemetry
|
|
23
|
+
scope: local
|
|
24
|
+
path: "/Users/gabriel/src/gems/exis_ray/.agents/skills/opentelemetry"
|
|
16
25
|
- name: quality-code
|
|
17
26
|
scope: local
|
|
18
27
|
path: "/Users/gabriel/src/gems/exis_ray/.agents/skills/quality-code"
|
data/skills.yml
CHANGED
|
@@ -2,23 +2,48 @@ mcps:
|
|
|
2
2
|
- github
|
|
3
3
|
- clickup
|
|
4
4
|
skills:
|
|
5
|
-
|
|
5
|
+
skill-manager:
|
|
6
6
|
repo: sequre/ai_knowledge
|
|
7
|
-
|
|
7
|
+
scope: local
|
|
8
|
+
yard:
|
|
8
9
|
repo: sequre/ai_knowledge
|
|
9
|
-
|
|
10
|
+
scope: local
|
|
11
|
+
quality-code:
|
|
10
12
|
repo: sequre/ai_knowledge
|
|
11
|
-
|
|
13
|
+
scope: local
|
|
14
|
+
gem-release:
|
|
12
15
|
repo: sequre/ai_knowledge
|
|
13
|
-
|
|
16
|
+
scope: local
|
|
17
|
+
skill-builder:
|
|
14
18
|
repo: sequre/ai_knowledge
|
|
15
|
-
|
|
19
|
+
scope: local
|
|
20
|
+
ai-reports:
|
|
16
21
|
repo: sequre/ai_knowledge
|
|
17
|
-
|
|
22
|
+
scope: local
|
|
23
|
+
environment:
|
|
24
|
+
space_id: "${AI_REPORTS_SPACE_ID}"
|
|
25
|
+
bug_reports_list_id: "${AI_REPORTS_BUG_REPORTS_LIST_ID}"
|
|
26
|
+
improvements_list_id: "${AI_REPORTS_IMPROVEMENTS_LIST_ID}"
|
|
27
|
+
agent-review:
|
|
18
28
|
repo: sequre/ai_knowledge
|
|
19
|
-
|
|
29
|
+
scope: local
|
|
30
|
+
environment:
|
|
31
|
+
space_id: "${AGENT_REVIEW_SAPCE_ID}"
|
|
32
|
+
list_id: "${AGENT_LIST_ID}"
|
|
33
|
+
action-plan:
|
|
34
|
+
repo: sequre/ai_knowledge
|
|
35
|
+
environment:
|
|
36
|
+
space_id: "${AGENT_REVIEW_SAPCE_ID}"
|
|
37
|
+
list_id: "${AGENT_ACTION_PLAN_LIST_ID}"
|
|
38
|
+
documentation-writer:
|
|
20
39
|
repo: github/awesome-copilot
|
|
21
40
|
path: skills/documentation-writer
|
|
22
|
-
|
|
41
|
+
scope: local
|
|
42
|
+
find-skills:
|
|
23
43
|
repo: vercel-labs/skills
|
|
24
44
|
path: skills/find-skills
|
|
45
|
+
scope: local
|
|
46
|
+
opentelemetry:
|
|
47
|
+
repo: bobmatnyc/claude-mpm-skills
|
|
48
|
+
path: universal/observability/opentelemetry
|
|
49
|
+
scope: local
|
|
@@ -14,12 +14,12 @@ RSpec.describe ExisRay::Configuration do
|
|
|
14
14
|
expect(config.propagation_trace_header).to eq("X-Amzn-Trace-Id")
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
it "reporter_class por defecto es
|
|
18
|
-
expect(config.reporter_class).to
|
|
17
|
+
it "reporter_class por defecto es nil" do
|
|
18
|
+
expect(config.reporter_class).to be_nil
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
it "current_class por defecto es
|
|
22
|
-
expect(config.current_class).to
|
|
21
|
+
it "current_class por defecto es nil" do
|
|
22
|
+
expect(config.current_class).to be_nil
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
it "log_format por defecto es :text" do
|
|
@@ -29,6 +29,75 @@ RSpec.describe ExisRay::Configuration do
|
|
|
29
29
|
it "log_subscriber_class por defecto es nil" do
|
|
30
30
|
expect(config.log_subscriber_class).to be_nil
|
|
31
31
|
end
|
|
32
|
+
|
|
33
|
+
it "service_version por defecto es nil fuera de Rails" do
|
|
34
|
+
expect(config.service_version).to be_nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "deployment_environment por defecto es nil fuera de Rails" do
|
|
38
|
+
expect(config.deployment_environment).to be_nil
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "resource attributes OTel" do
|
|
43
|
+
it "permite setear service_version" do
|
|
44
|
+
config = described_class.new
|
|
45
|
+
config.service_version = "2.0.0"
|
|
46
|
+
|
|
47
|
+
expect(config.service_version).to eq("2.0.0")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "permite setear deployment_environment" do
|
|
51
|
+
config = described_class.new
|
|
52
|
+
config.deployment_environment = "staging"
|
|
53
|
+
|
|
54
|
+
expect(config.deployment_environment).to eq("staging")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "#default_service_version" do
|
|
58
|
+
it "retorna nil cuando Rails no está definido" do
|
|
59
|
+
expect(described_class.new.default_service_version).to be_nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "lee config.version (atributo directo) con prioridad sobre config.x.version" do
|
|
63
|
+
rails_config = Struct.new(:version).new("1.2.3")
|
|
64
|
+
allow(rails_config).to receive(:respond_to?).and_call_original
|
|
65
|
+
app = Struct.new(:config).new(rails_config)
|
|
66
|
+
stub_const("Rails", Class.new do
|
|
67
|
+
define_singleton_method(:application) { app }
|
|
68
|
+
end)
|
|
69
|
+
|
|
70
|
+
expect(described_class.new.default_service_version).to eq("1.2.3")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "cae a config.x.version si config.version no está definido" do
|
|
74
|
+
x_config = Struct.new(:version).new("3.0.0")
|
|
75
|
+
rails_config = Struct.new(:x).new(x_config)
|
|
76
|
+
app = Struct.new(:config).new(rails_config)
|
|
77
|
+
stub_const("Rails", Class.new do
|
|
78
|
+
define_singleton_method(:application) { app }
|
|
79
|
+
end)
|
|
80
|
+
|
|
81
|
+
expect(described_class.new.default_service_version).to eq("3.0.0")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "retorna nil si config.x.version es un OrderedOptions vacío (no un string)" do
|
|
85
|
+
x_config = ActiveSupport::OrderedOptions.new
|
|
86
|
+
rails_config = Struct.new(:x).new(x_config)
|
|
87
|
+
app = Struct.new(:config).new(rails_config)
|
|
88
|
+
stub_const("Rails", Class.new do
|
|
89
|
+
define_singleton_method(:application) { app }
|
|
90
|
+
end)
|
|
91
|
+
|
|
92
|
+
expect(described_class.new.default_service_version).to be_nil
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe "#default_deployment_environment" do
|
|
97
|
+
it "retorna nil cuando Rails no está definido" do
|
|
98
|
+
expect(described_class.new.default_deployment_environment).to be_nil
|
|
99
|
+
end
|
|
100
|
+
end
|
|
32
101
|
end
|
|
33
102
|
|
|
34
103
|
describe "#json_logs?" do
|
|
@@ -141,6 +141,78 @@ RSpec.describe ExisRay::JsonFormatter do
|
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
describe "severity_number (OTel Log Data Model)" do
|
|
145
|
+
it "inyecta severity_number=9 para INFO" do
|
|
146
|
+
result = JSON.parse(formatter.call("INFO", timestamp, progname, "event=x"))
|
|
147
|
+
|
|
148
|
+
expect(result["severity_number"]).to eq(9)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "inyecta severity_number=13 para WARN" do
|
|
152
|
+
result = JSON.parse(formatter.call("WARN", timestamp, progname, "event=x"))
|
|
153
|
+
|
|
154
|
+
expect(result["severity_number"]).to eq(13)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "inyecta severity_number=17 para ERROR" do
|
|
158
|
+
result = JSON.parse(formatter.call("ERROR", timestamp, progname, "event=x"))
|
|
159
|
+
|
|
160
|
+
expect(result["severity_number"]).to eq(17)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "inyecta severity_number=5 para DEBUG" do
|
|
164
|
+
result = JSON.parse(formatter.call("DEBUG", timestamp, progname, "event=x"))
|
|
165
|
+
|
|
166
|
+
expect(result["severity_number"]).to eq(5)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "inyecta severity_number=21 para FATAL" do
|
|
170
|
+
result = JSON.parse(formatter.call("FATAL", timestamp, progname, "event=x"))
|
|
171
|
+
|
|
172
|
+
expect(result["severity_number"]).to eq(21)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "omite severity_number para niveles no estándar" do
|
|
176
|
+
result = JSON.parse(formatter.call("CUSTOM", timestamp, progname, "event=x"))
|
|
177
|
+
|
|
178
|
+
expect(result).not_to have_key("severity_number")
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe "resource attributes OTel (service_version, deployment_environment)" do
|
|
183
|
+
it "inyecta service_version cuando Configuration lo provee" do
|
|
184
|
+
allow(ExisRay.configuration).to receive_messages(service_version: "1.2.3", deployment_environment: nil)
|
|
185
|
+
|
|
186
|
+
result = call("event=boot")
|
|
187
|
+
|
|
188
|
+
expect(result["service_version"]).to eq("1.2.3")
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "inyecta deployment_environment cuando Configuration lo provee" do
|
|
192
|
+
allow(ExisRay.configuration).to receive_messages(service_version: nil, deployment_environment: "production")
|
|
193
|
+
|
|
194
|
+
result = call("event=boot")
|
|
195
|
+
|
|
196
|
+
expect(result["deployment_environment"]).to eq("production")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "omite service_version cuando es nil" do
|
|
200
|
+
allow(ExisRay.configuration).to receive_messages(service_version: nil, deployment_environment: "test")
|
|
201
|
+
|
|
202
|
+
result = call("event=boot")
|
|
203
|
+
|
|
204
|
+
expect(result).not_to have_key("service_version")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "omite deployment_environment cuando es nil" do
|
|
208
|
+
allow(ExisRay.configuration).to receive_messages(service_version: "1.0", deployment_environment: nil)
|
|
209
|
+
|
|
210
|
+
result = call("event=boot")
|
|
211
|
+
|
|
212
|
+
expect(result).not_to have_key("deployment_environment")
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
144
216
|
describe "inyeccion de contexto de negocio" do
|
|
145
217
|
let(:current_mock) do
|
|
146
218
|
Class.new do
|