제 6 장 오류와 관측 가능성
오류 모델과 관측 가능성은 Fayger 의 3 계층을 가로지르는 두 개의 공통 도선입니다. 이를 통해 외부 호출자는 같은 의미론으로 실패를 이해하고, 위치를 파악하고, 실행을 모니터링합니다.
6.1 통일 오류 모델
struct FaygerError {
code: ErrorCode
source_layer: Layer // loader | runtime | adapter | host
message: String
context: Map<String, Value>
cause: Option<Box<FaygerError>>
}
필드 의미:
- code: 안정적이며 문서화 가능한 식별자. 호출자 분기 결정에 사용. 버전 간 의미를 변경하지 않습니다.
- source_layer: 오류를 처음 만든 계층을 표시. 해당 모듈 진단 매뉴얼로 라우팅하기 쉽습니다.
- message: 사람용 설명. 짧으며 code 정보를 반복하지 않습니다.
- context: 도구용 구조화 키-값 쌍. 오류를 유발한 핵심 필드(offset, missing_fields, current_state, expected_range 등)를 최소한 포함합니다.
- cause: 계층을 가로지르는 오류 인과 체인. 오류를 감쌀 때 하위 계층 오류를 cause 에 넣어 정보를 삼키지 않습니다.
6.2 오류 발생 및 전파 규칙
- 근접 구성: 각 계층은 자기 경계 내에서
FaygerError를 구성하고source_layer를 표시합니다. - 단계적 감싸기: 상위 계층이 의미를 보강해야 한다면
cause에 하위 계층 오류를 보존하고source_layer를 다시 쓰지 않습니다. - 컨텍스트 손실 금지:
context는 오류 유발 핵심 필드를 최소한 포함합니다. - 실패 보존:
Failed에 진입한 BuF_Instance 는 마지막 Universal_Instruction 과 대응 오류를failure_info에 고정하여 인스턴스가 명시적으로 폐기될 때까지 보존합니다.
6.3 오류 체인 예시
3 계층을 가로지르는 일반적 전파:
[top] RT_INSTANCE_FAILED (source_layer = runtime)
└── cause:
[mid] ADP_HOST_CALL_FAILED (source_layer = adapter)
└── cause:
[low] <호스트 원시 오류> (source_layer = host)
호출자가 cause 를 따라가며 얻는 계층 시퀀스는 [runtime, adapter, host] 로, 실제 발생 순서의 "안에서 밖으로" 와 일치합니다. 이 성질은 속성 기반 테스트로 지속 검증합니다.
6.4 주요 오류 코드 개요
| 발생 계층 | 오류 코드 | 발생 조건 |
|---|---|---|
| Loader | LDR_PARSE_FAIL | BuF 바이트 스트림 비정상 |
| Loader | LDR_DIGEST_MISMATCH | Section 다이제스트 불일치(Eager) |
| Loader | LDR_LAZY_DIGEST_MISMATCH | Section 다이제스트 불일치(Lazy 첫 접근) |
| Loader | LDR_SIGNATURE_FAIL | 강제 모드 하 서명 부재 / 서명 무효 |
| Loader | LDR_SCHEMA_UNSUPPORTED | schema 버전 지원 범위 밖 |
| Loader | LDR_RUNTIME_VERSION_TOO_HIGH | Runtime_Interface 최소 버전이 현재보다 높음 |
| Loader | LDR_MISSING_REQUIRED_FIELD | 직렬화 시 Manifest 필수 필드 누락 |
| Loader | LDR_PROFILE_REQUIRED_SECTION_MISSING | 현 프로파일 하 Required Section 적재 불가 |
| Loader | LDR_LAZY_SOURCE_UNAVAILABLE | Lazy 후속 접근 시 BuF_Source 사용 불가 |
| Loader | LDR_SOURCE_READ_FAILED | BuF_Source 읽기 오류(Eager 또는 Lazy) |
| Runtime | RT_ILLEGAL_TRANSITION | 불법 라이프사이클 전이 |
| Runtime | RT_IMPL_NOT_FOUND | 라우팅이 일치 구현을 찾지 못함 |
| Runtime | RT_IMPL_MISSING_METHODS | 등록된 구현이 필수 메서드 누락 |
| Runtime | RT_QUOTA_EXCEEDED | 리소스 사용 쿼터 초과 |
| Runtime | RT_INSTANCE_FAILED | 인스턴스가 Failed 진입 |
| Adapter | ADP_NO_MATCHING_PLATFORM | 현재 호스트에 일치 어댑터 없음 |
| Adapter | ADP_UNSUPPORTED_INSTRUCTION | 현재 어댑터가 명령 미지원 |
| Adapter | ADP_CAPABILITY_DENIED | 축소 후 권한 부족 |
| Adapter | ADP_HOST_CALL_FAILED | 시스템 호출 번역 후 호스트 측 실패 |
로더 계층 오류의 context.phase 필드는 eager 또는 lazy 를 표시하여, 호출자가 단계별로 라우팅할 수 있게 합니다: 시작 단계 실패는 다른 소스나 다른 프로파일로의 폴백 또는 재시도를 트리거할 수 있고, 실행 단계 Lazy 실패는 보통 해당 Section 의 접근에만 영향을 주며 호출자가 축소 여부를 결정합니다.
6.5 관측 가능성 이벤트 버스
interface EventBus {
publish(event: FaygerEvent)
subscribe(filter: EventFilter, handler: EventHandler) -> SubscriptionId
set_debug_enabled(enabled: bool)
}
이벤트 분류:
- Lifecycle Event: BuF_Instance 상태 전이.
from,to,timestamp,instance_id보유. - Quota Event: 리소스 샘플링, 초과, 일시 정지.
- Loader Event: 적재 단계 진입 / 완료 / 실패. 단계 이름 보유.
- Adapter Event: 명령 디스패치, 권한 축소 결과, 미지원 명령 기록.
- Debug Event:
set_debug_enabled(true)일 때만 출력. 심층 분석용.
Lifecycle 이벤트 시퀀스 일관성
임의 인스턴스의 합법 전이 시퀀스 [(s₀, s₁), (s₁, s₂), …] 에 대해, 이벤트 버스가 발행하는 시퀀스는 다음을 만족해야 합니다:
- 길이가 같다.
- 각
eᵢ.from == sᵢ₋₁,eᵢ.to == sᵢ. eᵢ.timestamp는 단조 비감소.
6.6 호스트 로그 / 추적 채널 통합
호스트가 로그/추적 채널(systemd-journal, OS Logger, 브라우저 console, In-App SDK 채널 등)을 제공할 때, 어댑터 계층은 Fayger 내부 이벤트를 해당 채널로 매핑합니다:
- 매핑 규칙은 Platform_Adapter 가 자기 기술하며, 런타임 계층은 채널 차이를 알지 못합니다.
- 이벤트 레벨(debug / info / warn / error)은 호스트 채널의 대응 레벨에 매핑됩니다.
- Lifecycle Event 와 Loader Event 는 info, Quota / Adapter 오류는 warn / error 입니다.
호스트에 로그 채널이 없으면 이벤트는 EventBus 에 머물며 구독자가 소비합니다.
6.7 디버그 이벤트 스위치
디버그 레벨 이벤트 출력은 기본 꺼짐. 활성화 방법:
event_bus.set_debug_enabled(true)
디버그 이벤트에는 다음이 포함됩니다:
- 각 Universal_Instruction 의 디스패치 상세.
- 각 권한 축소의 입력과 출력.
- 리소스 모니터의 각 샘플 값.
양이 많으므로 디버그 구독자는 능동적으로 필터링, 속도 제한, 또는 파일 저장을 해야 합니다.
6.8 상태 조회 인터페이스
Fayger 는 운영과 진단을 위해 다음 조회 인터페이스를 노출해야 합니다:
| 조회 | 반환 |
|---|---|
state(instance_id) | 현재 Lifecycle_State |
failure_info(instance_id) | 실패를 유발한 마지막 Universal_Instruction 과 오류 객체 |
list_implementations() | 등록된 Runtime_Implementation 디스크립터 목록 |
current_adapter() | 현재 선택된 Platform_Adapter 디스크립터 |
granted_capabilities(instance_id) | 해당 인스턴스가 축소 후 실제 보유한 권한 집합 |
이 인터페이스들은 모두 읽기 전용, 멱등이며, 어떤 상태에서도 호출 가능합니다.
6.9 기본 보안 자세
- 강제 서명 모드는 기본 꺼짐(개발 편의), 릴리스 빌드는 설정 계층에서 켜짐 을 권장합니다.
- 디버그 이벤트는 기본 꺼짐. 명시적으로 활성화해야 합니다.
- 선언되지 않은 권한은 BuF 에 대해 기본 거부 입니다.
- 인식되지 않은 Universal_Instruction 카테고리는 기본 거부 이며, "조용한 통과" 는 허용하지 않습니다.
