error-path
한국어 | English
error-path는 기존 Rust 에러 위에 운영용 오류 주소(operational error address) 를 얹는 가벼운 라이브러리입니다. anyhow, thiserror로 만든 자체 타입, eyre, error-stack 등을 대체하지 않습니다. 대신 오류가 시스템의 어느 기능과 경계에 속하는지 일관된 주소로 표현하도록 돕습니다.
login.api.request_login
이 주소는 로그 검색, 고객 지원 응대, 운영 문서, UI 메시지, 오류 카탈로그에서 같은 식별자로 사용할 수 있습니다. 호출 순서를 복원하는 stack trace가 아니라, 사람이 정한 안정적인 운영 주소를 누적하는 것이 목적입니다.
설치
속성 매크로까지 함께 사용하려면 다음 한 줄이면 충분합니다.
[]
= { = "0.1", = ["macros"] }
ErrorPath와 WithErrorPath만 사용한다면 feature 없이 설치합니다.
[]
= "0.1"
최소 지원 Rust 버전(MSRV)은 1.77입니다.
빠른 시작
가장 안쪽 계층부터 안정적인 경로 세그먼트를 선택하고, 바깥 계층의 함수는 주소 조각을 붙입니다.
use ;
let error = request_login.unwrap_err;
assert_eq!;
라이브러리의 핵심 계약은 WithErrorPath입니다. 자체 오류 타입이 ErrorPath를 보관하고 이 trait을 구현하면 같은 매크로를 사용할 수 있습니다.
use ;
오류 처리 지점에서 주소 조회
WithErrorPath는 주소를 누적하고, ErrorPathExt는 이미 생성된 오류에서 주소만 읽습니다. 로그·UI·CS 처리 지점에서는 trait을 import한 뒤 error.error_path()를 사용합니다.
use ErrorPathExt;
let error = request_login.unwrap_err;
let path = error.error_path.expect;
assert_eq!;
자체 오류 타입이 ErrorPathExt를 구현하지 않으면 기본값은 None입니다.
주소와 경로의 의미
주소는 바깥쪽에서 안쪽 순서로 구성됩니다. #[error_path]와 #[error_path_impl]이 안정적인 경로 세그먼트를 앞쪽에 추가합니다.
자체 오류 타입은 코드까지 포함한 구조화된 ErrorPath를 반환하는 API를 제공할 수 있습니다. segments()는 로그나 JSON 필드에 파싱 없이 사용할 수 있고, to_string_with()는 원하는 구분자로 표시합니다.
매크로 사용
macros feature는 다음 속성을 재노출합니다.
use ;
;
#[error_path]는 인자가 없으면 함수 이름을, 문자열 인자가 있으면 그 문자열을 붙입니다.#[error_path_impl]는 각Result반환 메서드에{base}.{method_name}을 붙입니다. 인자가 없으면 trait impl은 trait 이름, inherent impl은 타입 이름을 base로 사용합니다.#[error_path_skip]는#[error_path_impl]블록 안에서 해당 메서드를 제외합니다.
매크로는 반환된 Err(E)에 WithErrorPath::with_error_path(e, path)를 호출합니다. 따라서 대상 함수의 오류 타입 E가 trait을 구현해야 합니다.
주소는 attribute가 붙은 함수가 Err를 반환할 때만 앞에 추가됩니다. 중첩 호출 A -> B -> C에서 C가 실패하면 unwind 중 반환 경계를 거쳐 A.B.C가 됩니다. 함수 진입 시 부모 주소를 자동으로 받지 않으며, task-local·thread-local·함수 인자 전파는 범위 밖입니다.
:: 구분자를 쓰려면 첫 ErrorPath 생성 또는 주소 누적 전에 설정하고, 매크로에도 같은 구분자를 사용합니다.
use ;
set_path_delimiter?;
// login::api::request_login
선택 기능과 어댑터
필요한 에러 시스템의 feature만 켭니다.
[]
= { = "0.1", = ["macros", "anyhow"] }
= "1"
macros:#[error_path],#[error_path_impl],#[error_path_skip]재노출anyhow: 매크로 경로를 typed context로 추가하고 조회eyre:eyre::Report에 경로를 report context로 추가error-stack:error_stack::Report<C>에ErrorPathSegmentattachment 추가stacked-errors:stacked_errors::Error에 locationless kind 추가full: 위 feature를 모두 활성화
외부 에러 어댑터는 각 라이브러리의 context/attachment 기능을 사용합니다. anyhow::Error, eyre::Report, error_stack::Report<C>, stacked_errors::Error 모두 ErrorPathExt를 구현하므로 상위 매크로 경계를 지난 뒤 error.error_path()에서 매크로가 추가한 주소 세그먼트를 반환합니다. 원본 오류 메시지는 해석하거나 포함하지 않습니다.
use ;
let error = anyhow!;
let error = error.with_error_path;
let error = error.with_error_path;
assert_eq!;
최종 주소는 자체 오류 타입이 ErrorPath를 보관하고 ErrorPathExt를 구현해 명시적으로 구성할 수 있습니다. thiserror는 오류 타입을 생성하는 derive macro이므로 별도 어댑터가 필요하지 않습니다. #[derive(thiserror::Error)]로 만든 타입에 WithErrorPath를 구현하면 됩니다. anyhow::bail! 같은 매크로도 반환하는 오류 타입이 WithErrorPath를 구현하거나 해당 adapter feature가 활성화되어 있으면 동작합니다.
구분자 설정
기본 구분자는 .입니다. 전역 구분자는 경로 문자열 해석과 출력에 함께 적용됩니다. 애플리케이션 시작 시 set_path_delimiter로 프로세스 전체 구분자를 한 번 설정할 수 있습니다.
use set_path_delimiter;
set_path_delimiter.expect;
설정 뒤 ErrorPath의 Display, to_string(), 경로 문자열 해석은 ::를 사용합니다. 따라서 매크로 인자와 직접 prefix도 login::api::request_login처럼 같은 구분자로 작성합니다. 첫 ErrorPath 생성·주소 누적·출력 전 설정하지 않으면 기본값 .이 고정됩니다. 빈 문자열과 두 번째 설정은 오류를 반환하며, 환경변수는 읽지 않습니다.
전역 설정과 관계없이 한 번만 다른 형식이 필요하면 ErrorPath::to_string_with("/")를 사용합니다.
범위와 제한
Result<T, E>경계를 다룹니다. panic, thread, spawn 내부 오류를 자동으로 수집하거나 변환하지 않습니다.- 경로는 runtime stack trace나 파일 경로에서 추론하지 않습니다. 안정적인 운영 이름을 직접 정하거나 macro 기본 이름을 사용합니다.
#[error_path]는Result를 반환하는 함수에만 적용해야 합니다.#[error_path_impl]은 반환 타입 이름이Result로 끝나는 메서드만 자동 감쌉니다.- 매크로가 생성하는 경로는
::error_path를 참조합니다. 의존성 이름을 변경했다면error_path라는 이름으로 다시 노출해야 합니다. - 전역 구분자 설정은
ErrorPath의 기본 렌더링에 적용됩니다. 외부 adapter가 이미 보관한 context/attachment 표현을 바꾸지 않습니다.
더 알아보기
라이선스
Apache-2.0 또는 MIT 라이선스 중 하나를 선택해 사용할 수 있습니다.
만든이
용사장이 만들고 관리합니다. akira76@gmail.com