feat(execution,obs): 호가단위 스냅(dcy-030/#28) + 운영 관측성(dcy-029/#29) + REL-007 환류
dcy-030 (issue #28, P0 체결 복구): - REQ-083 KRX 호가단위(tick) 순수 유틸 (domain/pricing.py) - REQ-070 CHG: 슬리피지 실효가 호가단위 스냅 — 상한 준수(매수 floor/매도 ceil) + band<1tick 하한/상한 보장 + 부동소수 epsilon 가드. 147700→148400/54500→54700. - BAT-044 release-candidate dcy-029 (issue #29, 운영 관측성): - REQ-084 구조화 로깅 기반 (runtime/logging_setup.py): ISO8601 KST·레벨·Loki JSON ·correlation id(slot_id) - REQ-085 주문 결과 로깅 (event=order_submit|fill|reject) - REQ-087 거부 ERROR 가시성 (조용한 롤백 제거) - REQ-086 청산 reason+actor 동반 노출 (안전망/전략 구분, 신규 필드 없음) - REQ-088 운영 조회 CLI report (application/operator_report.py, 보유·오늘 체결 ·실현 PnL net·대기, direct-DB) - REQ-089 운영자 런북 docs/operations.md - REQ-090 baseline 정합 (runtime-flows·project-structure·interface-contract) - BAT-045(P0)·BAT-046(P1) release-candidate REL-007: confirmed → feedback-captured (운영 인스턴스 라이브 검증 + #28/#29 환류 정규화). BAT-037~041 released. 검증: 537 passed, 47 skipped, 회귀 0, ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# BAT-045 Design
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-045
|
||||
|
||||
## Architecture Summary
|
||||
- 로깅 설정을 단일 모듈(`trex_core/runtime/logging_setup.py`)로 모은다. 포맷터(text/json)·KST 타임스탬프·correlation id contextvar/filter를 제공하고, 엔트리포인트가 `configure_logging()`으로 root 핸들러를 구성한다. 호출부(`_log.info`)는 그대로 두어도 포맷·cid가 자동 적용. execution 루프는 주문 결과를 일관 event 라인으로 남기고 처리 슬롯마다 correlation id(slot_id)를 설정한다.
|
||||
|
||||
## Changed Areas
|
||||
- Docs: docs/runtime-flows.md·docs/project-structure.md(REQ-090/BAT-046에서 정합)
|
||||
- Modules: trex_core/runtime/logging_setup.py(신규), trex_core/runtime/daemon.py·reset.py(configure_logging), trex_core/application/execution.py(주문 결과 로깅+cid)
|
||||
- Interfaces: 외부 메시지 계약 변경 없음. 로그 라인 포맷/키만 추가(관측 표면).
|
||||
|
||||
## Key Decisions
|
||||
1. **correlation id = slot_id**. intent·order·fill의 공통 조인 키. intent_id를 slot에 저장하는 스키마 변경 대신 slot_id로 단일 키 구성(REQ-084 "파생 키" 허용). execution 루프가 dispatch/poll 각 슬롯 처리 시작 시 `set_correlation_id(slot_id)`.
|
||||
2. **포맷 선택 = env `TREX_LOG_FORMAT`**(text 기본 / json). JSON은 `ts/level/logger/msg/correlation_id` + extra 필드. KST 타임스탬프는 코드에서 명시적 +09:00(환경 TZ 비의존).
|
||||
3. **`configure_logging` idempotent**: 재호출 시 기존 핸들러 제거 후 단일 핸들러 부착(데몬·reset 양쪽 안전, 중복 출력 방지).
|
||||
4. **레이어 방향**: application(execution) → runtime(logging_setup) import는 기존 선례(safety_sell→runtime.config)와 동일. domain은 무의존 유지(import sweep 영향 없음).
|
||||
5. **거부 ERROR(REQ-087)는 REQ-085 reject 라인과 동일 지점**에서 ERROR 레벨로 구현(코드 중복 편집 방지). 정상 체결 경로는 INFO 유지.
|
||||
|
||||
## Edge Cases
|
||||
- correlation id 미설정 → 빈 문자열, 예외 없음(text는 cid 생략, json은 빈 값).
|
||||
- caplog 기반 기존 테스트: root 핸들러만 교체하고 메시지 텍스트 보존 → 회귀 없음(529 passed).
|
||||
- JSON extra 필드: 표준 LogRecord 속성 제외 후 직렬화(default=str로 비직렬 객체 방어).
|
||||
|
||||
## Architecture Impact
|
||||
- both (project-structure: 신규 logging 모듈 / runtime-flows: 로깅·관측성 흐름) — 실제 문서 정합은 REQ-090(BAT-046)에서 일괄.
|
||||
|
||||
## Reference Doc Update Plan
|
||||
- project-structure.md: `runtime/logging_setup.py` 추가 — REQ-090(BAT-046)에서.
|
||||
- runtime-flows.md: 구조화 로깅·correlation id·주문 결과 로깅·거부 ERROR 흐름 — REQ-090(BAT-046)에서.
|
||||
@@ -0,0 +1,30 @@
|
||||
# BAT-045 Implementation
|
||||
|
||||
- Status: completed
|
||||
- Batch: BAT-045
|
||||
|
||||
## Plan Summary
|
||||
- 구조화 로깅 기반(REQ-084) + 주문 결과 로깅(REQ-085) + 거부 ERROR(REQ-087) 구현.
|
||||
|
||||
## Changed Files
|
||||
- `trex_core/runtime/logging_setup.py` (신규) — `_correlation_id` contextvar, `set_correlation_id`/`get_correlation_id`/`correlation_id` cm, `_CorrelationFilter`, `TextFormatter`/`JsonFormatter`(KST ISO8601), `configure_logging`(idempotent root 핸들러).
|
||||
- `trex_core/runtime/daemon.py` — `main()`에서 `logging.basicConfig` → `configure_logging`.
|
||||
- `trex_core/runtime/reset.py` — 동일 교체.
|
||||
- `trex_core/application/execution.py` — import `set_correlation_id`; `_dispatch`에서 슬롯별 cid 설정 + `event=order_submit` INFO + `event=order_reject` ERROR; `_poll` 슬롯별 cid + terminal_reject ERROR; `_on_filled` `event=order_fill`(price/qty/fee/tax).
|
||||
- `tests/runtime/test_logging_setup.py` (신규) — text/json 포맷·KST·cid·idempotent.
|
||||
- `tests/application/test_execution_policy.py` — `TestOrderResultLogging`(submit/fill event 키 + cid=slot_id, 거부 ERROR, 정상 무ERROR).
|
||||
|
||||
## Execution Log
|
||||
1. `logging_setup.py` 작성 → 단위 테스트 green.
|
||||
2. 엔트리포인트 `configure_logging` 교체(daemon/reset).
|
||||
3. execution 주문 결과 로깅 + correlation id + 거부 ERROR.
|
||||
4. 테스트 추가/실행, 전체 회귀.
|
||||
|
||||
## Validation
|
||||
- `pytest tests/runtime/test_logging_setup.py tests/application/test_execution_policy.py` → 35 passed.
|
||||
- 전체 `pytest -q` → **529 passed, 47 skipped**(실 DB/RabbitMQ 게이트 skip), 회귀 0.
|
||||
- `ruff check`(logging_setup/execution/daemon/reset/테스트) → All checks passed.
|
||||
|
||||
## Remaining Risks
|
||||
- correlation id는 slot_id 기반(단일 키). intent_id 전체 전파는 후속(스키마 변경 필요 시).
|
||||
- Loki 실제 적재는 배포측 수집기 설정(코드는 JSON stdout). 실 환경 검증은 release 운영 위임.
|
||||
@@ -0,0 +1,30 @@
|
||||
# BAT-045: 관측성 로깅 기반 — 구조화 로깅 + 주문 결과 + 거부 ERROR (issue #29 P0)
|
||||
|
||||
- Status: release-candidate
|
||||
- Profile: standard
|
||||
- Source Discovery: dcy-029
|
||||
- Included REQ: REQ-084, REQ-085, REQ-087
|
||||
- Excluded REQ: REQ-086·088·089·090 (P1 → BAT-046)
|
||||
|
||||
## Summary
|
||||
- dcy-029 P0 — 운영 가시성의 토대. 모든 로그에 ISO8601(KST) 타임스탬프+레벨, Loki 적재용 JSON 출력 옵션, correlation id(slot_id, intent→order→fill join key)를 도입하고(REQ-084), 주문 submit/체결/거부를 일관 tailable 로그로 남기며(REQ-085), 거부를 ERROR 레벨로 가시화한다(REQ-087, 조용한 롤백 제거 — issue #28이 수 시간 묻혔던 원인).
|
||||
|
||||
## Scope
|
||||
- In Scope:
|
||||
- `trex_core/runtime/logging_setup.py`(신규) — TextFormatter/JsonFormatter + KST 타임스탬프 + correlation id contextvar/filter + `configure_logging`.
|
||||
- `daemon.py`·`reset.py` — `basicConfig` → `configure_logging`.
|
||||
- `execution.py` — submit/fill 로그(`event=order_submit|order_fill`) + 거부 ERROR(`event=order_reject`) + correlation id(slot_id) 설정.
|
||||
- 단위 테스트(포맷터 text/json/KST/cid, 설정 idempotent, 주문 결과 로깅, 거부 ERROR).
|
||||
- Out of Scope:
|
||||
- 청산 reason+actor 노출(REQ-086), PnL CLI(REQ-088), 런북(REQ-089), baseline 정합(REQ-090) → BAT-046.
|
||||
- 알림 전송 채널(dcy-029 OQ-3 Deferred).
|
||||
|
||||
## Documents
|
||||
- Planning: [planning.md](./planning.md)
|
||||
- Design: [design.md](./design.md)
|
||||
- Implementation: [implementation.md](./implementation.md)
|
||||
- Verification: [verification.md](./verification.md)
|
||||
|
||||
## Notes
|
||||
- correlation id 키 = **slot_id**(intent·order·fill 공통 조인 키). intent_id 전체 전파(slot에 저장)는 과한 스키마 변경이라 slot_id로 단일 키 구성(REQ-084 "intent_id 또는 그로부터 파생한 키" 허용).
|
||||
- REQ-087(FR-4)은 원래 P1이나 REQ-085의 reject 로깅 지점과 동일 코드라 P0에 동반 구현(코드 중복 편집 방지) — 사용자 위임 결정 범위 내 조정.
|
||||
@@ -0,0 +1,33 @@
|
||||
# BAT-045 Planning
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-045
|
||||
- Profile: standard
|
||||
|
||||
## Included REQ
|
||||
- REQ-084 (구조화 로깅 기반, Approved)
|
||||
- REQ-085 (주문 결과 로깅, Approved)
|
||||
- REQ-087 (주문 거부 ERROR 가시성, Approved)
|
||||
|
||||
## Delivery Plan
|
||||
1. `trex_core/runtime/logging_setup.py` 신설 — KST 포맷터(text/json) + correlation id contextvar/filter + `configure_logging`(basicConfig 대체, idempotent).
|
||||
2. `daemon.py`/`reset.py` 엔트리포인트에서 `configure_logging` 호출로 교체.
|
||||
3. `execution.py` `_dispatch`/`_poll`/`_on_filled`에 submit/fill/reject 일관 로그(event 키) + correlation id(slot_id) 설정. 거부 라인은 ERROR 레벨(REQ-087).
|
||||
4. 테스트: `tests/runtime/test_logging_setup.py`, `tests/application/test_execution_policy.py`(주문 결과 로깅 + 거부 ERROR).
|
||||
|
||||
## Dependencies
|
||||
- Internal: `execution.py`(application)가 `logging_setup`(runtime)의 `set_correlation_id` 사용 — 기존 선례(safety_sell→runtime.config) 동일 방향. domain 무의존 유지.
|
||||
- External: 없음. Loki 적재는 배포측 수집기(코드는 JSON stdout만, A-4 전제).
|
||||
|
||||
## Design Gate
|
||||
- Design Required Before Implementation: yes
|
||||
- Reason: correlation id 키 선택(slot_id), 포맷터 구조, 레이어 의존 방향, basicConfig 교체 idempotency 결정 필요.
|
||||
|
||||
## Milestones
|
||||
1. logging_setup + 단위 테스트 green.
|
||||
2. execution 주문 결과 로깅 + 거부 ERROR + 테스트 green.
|
||||
3. 전체 회귀 + ruff.
|
||||
|
||||
## Risks
|
||||
- 로그 포맷 변경이 기존 caplog 기반 테스트에 영향 → 메시지 텍스트 보존, 핸들러 교체는 root만.
|
||||
- correlation id 단일 스레드 execution 루프에서 set-per-iteration로 충분(리셋 불요).
|
||||
@@ -0,0 +1,41 @@
|
||||
# BAT-045 Verification
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-045
|
||||
|
||||
## Acceptance Mapping
|
||||
- REQ-084 (구조화 로깅 기반):
|
||||
- AC-1 (ISO8601 KST+레벨+메시지): `TestTextFormatter::test_has_iso8601_kst_timestamp_level_and_msg` ✅
|
||||
- AC-2 (json 유효+필수 키): `TestJsonFormatter::test_is_valid_json_with_required_keys` ✅
|
||||
- AC-3 (text 기본): `TestConfigureAndContext::test_configure_text_default` ✅
|
||||
- AC-4 (cid 포함): `test_includes_correlation_id_when_set`·`test_correlation_id_propagates` ✅
|
||||
- AC-5 (cid 미설정 안전): `test_omits_cid_when_unset`·json 빈 cid ✅
|
||||
- AC-6 (KST 고정): `+09:00` 검증(text/json) ✅
|
||||
- REQ-085 (주문 결과 로깅):
|
||||
- AC-1 (order_submit 키): `TestOrderResultLogging::test_submit_and_fill_are_logged_with_event_keys` ✅
|
||||
- AC-2 (order_fill 가격/수량/fee/tax): 동 테스트(`fee=1.5`) ✅
|
||||
- AC-3 (order_reject 사유): `test_reject_is_logged_at_error_level` ✅
|
||||
- AC-4 (json 구조화 필드): `JsonFormatter` extra 필드 테스트 + 라인 키 ✅
|
||||
- AC-5 (grep 전수 추출): `event=order_reject`/`event=order_submit` 안정 키 ✅
|
||||
- AC-6 (submit→fill 동일 cid): `get_correlation_id()==slot_id` 검증 ✅
|
||||
- REQ-087 (거부 ERROR 가시성):
|
||||
- AC-1·2 (매수/매도 거부 ERROR): `test_reject_is_logged_at_error_level`(dispatch) + poll terminal_reject ERROR 경로 ✅
|
||||
- AC-3 (정상 체결 비-ERROR): `test_normal_fill_emits_no_error` ✅
|
||||
- AC-4 (json level=ERROR): JsonFormatter level 키 ✅
|
||||
- AC-5 (반복 거부 가시화): reject 라인 event 키 grep ✅
|
||||
- AC-6 (알림 채널 미호출): 본 구현은 로그까지만(전송 채널 코드 없음, OQ-3 Deferred) ✅
|
||||
|
||||
## Evidence
|
||||
- Test:
|
||||
- `pytest tests/runtime/test_logging_setup.py tests/application/test_execution_policy.py -q` → **35 passed**.
|
||||
- 전체 `pytest -q` → **529 passed, 47 skipped**, 회귀 0.
|
||||
- `ruff check` → All checks passed.
|
||||
- Manual:
|
||||
- text/json 포맷·KST 타임스탬프·correlation id·거부 ERROR 출력 단위 검증.
|
||||
- Logs:
|
||||
- 실 데몬/Loki 적재 검증은 release 운영 단계 위임(코드는 JSON stdout 보장).
|
||||
|
||||
## Result
|
||||
- Ready for Release: true
|
||||
- Blocking Issues:
|
||||
- 없음
|
||||
Reference in New Issue
Block a user