infrablockchain-docs
ko
ko
  • 인프라블록체인
    • 배우기
      • 아키텍처
        • 아키텍처
        • 네트워크 참여자
        • 파라체인
          • 시스템 파라체인
      • 프로토콜
        • 시스템 토큰
        • 트랜잭션 수수료
        • Proof of Transaction
      • Substrate
        • 배우기
          • 기초 지식
            • 암호학
            • 블록체인 기본 개념
            • 합의
            • 네트워크와 노드
            • 트랜잭션과 블록 기본 사항
            • 트랜잭션 수명주기
            • 오프체인 작업
            • 라이트 클라이언트
            • Substrate를 위한 Rust
            • 라이브러리 소개
            • 아키텍처와 Rust 라이브러리
            • 파일 구조
            • 계정, 주소 및 키
            • 트랜잭션 형식
            • 난수 생성
          • 프레임
            • FRAME 팔레트
            • FRAME 매크로
            • 커스텀 팔레트
            • 팔레트 커플링
            • Origin
            • 이벤트와 에러
            • 런타임 스토리지 구조
            • 상태 전이와 스토리지
            • SCALE 인코딩
            • 트랜잭션, Weight 및 수수료
            • 런타임 API
            • 런타임 업그레이드
            • 런타임 개발
          • 계정 데이터 구조
          • 주소 형식
          • 용어집
          • cli
            • 아카이브
            • 메모리 프로파일러
            • 노드 템플릿
            • 사이드카
            • srtool
            • 서브키
            • subxt
            • try-runtime
            • tx-wrapper
          • 런타임 개발
            • 기본
              • Genesis 상태 구성하기
              • 런타임 상수 구성
              • 체인 스펙을 커스텀하기
              • 팔레트 가져오기
              • 도우미 함수 사용하기
            • 합의 모델
              • 작업 증명을 사용하는 체인 구성
              • 하이브리드 노드 생성하기
            • 오프체인 워커
              • 오프체인 HTTP 요청하기
              • 오프체인 인덱싱
              • 오프체인 로컬 스토리지
            • 팔레트 설계
              • 크라우드펀딩 구성하기
              • 스토리지 구조체 (struct) 생성하기
              • 잠금 가능한 통화 구현
              • 무작위성 적용하기
              • 느슨한 팔레트 결합 사용하기
              • 타이트한 팔레트 결합 사용하기
            • 파라체인 개발
              • HRMP 채널 추가하기
              • 로컬 파라체인 노드 추가하기
              • 릴레이 체인에 연결하기
              • 솔로 체인을 변환하기
              • 론칭 준비
              • 콜레이터 선택
              • 파라체인 업그레이드
            • 스토리지 마이그레이션
              • 기본 저장소 마이그레이션
              • 스토리지 마이그레이션 트리거
            • 테스트
              • 기본 테스트 설정하기
              • 전송 함수 테스트하기
            • 도구
              • 체인을 위한 txwrapper 생성
              • REST 엔드포인트를 사용하여 체인 데이터 가져오기
              • try-runtime 사용하기
              • Wasm 바이너리 검증하기
            • 가중치
              • 벤치마크 추가
              • 수수료 계산하기
              • 조건부 가중치 사용
              • 사용자 정의 가중치 사용하기
        • 빌드하기
          • 제작할 것을 결정하세요
          • 빌드 프로세스
          • 결정론적 런타임 빌드
          • 체인 스펙
          • Genesis 구성
          • 애플리케이션 개발
          • RPC
          • 문제 해결
        • 튜토리얼
          • 설치하기
            • 개발자 도구
            • 리눅스 개발 환경
            • macOS 개발 환경
            • Rust 툴체인
            • Rust 문제 해결 방법
            • Windows 개발 환경
          • 빠른 시작
            • 코드 탐색하기
            • 런타임 수정하기
            • 노드 시작하기
            • Substrate 한눈에 보기
          • 블록체인 구축
            • 신뢰할 수 있는 노드 추가
            • 특정 노드 승인
            • 로컬 블록체인 구축하기
            • 네트워크 시뮬레이션
            • 실행 중인 네트워크 업그레이드
          • 애플리케이션 로직 구축
            • 런타임에 팔레트 추가하기
            • 오프체인 워커 추가
            • 사용자 정의 팔레트 게시
            • 함수 호출의 출처 지정하기
            • 사용자 정의 팔레트에서 매크로 사용하기
          • 유용한 도구들
            • EVM 계정에 접근하기
            • 이더리움 통합
            • 사이드카 엔드포인트 탐색하기
            • 경량 클라이언트 노드 통합
          • 스마트 컨트랙트
            • 스마트 컨트랙트
            • 토큰 계약 작성하기
            • 스마트 컨트랙트 개발하기
            • 첫 번째 계약 준비하기
            • 스마트 컨트랙트 문제 해결
            • 값 저장을 위한 맵 사용
      • XCM
        • XCM
        • XCM 형식
    • 서비스 체인
      • 인프라DID
      • 인프라EVM
      • URAuth(Universal Resource Auth)
    • 데브 옵스
      • 체인 빌드
      • 배포
      • 모니터링
    • 튜토리얼
      • 기초
        • 시스템 토큰 관리 프로세스
        • 시스템 토큰을 트랜잭션 수수료로 사용해보기
        • 트랜잭션에 투표 포함 시키기
        • 밸리데이터 보상 받기
      • 구축하기
        • 인프라릴레이체인 구축하기
        • 파라체인 구축하기
        • 메시지 전달 채널 열기
        • XCM을 이용하여 토큰 전송하기
        • Asynchronous Backing 적용하기
      • 테스트
        • 벤치마크
        • 런타임 확인
        • 디버그
        • 테스트 네트워크에서 파라체인 시뮬레이션하기
        • 단위 테스트
      • 서비스체인
        • 인프라DID
          • 구축하기
          • 공개키 추가하기
          • 서비스 엔드포인트 등록하기
          • DID 생성하기
        • 인프라EVM
          • 구축하기
          • EVM에 자금 입금 및 인출하기
          • ERC20 토큰 컨트랙트 배포하기
          • ERC721 토큰 컨트랙트 배포하기
          • ERC1155 토큰 컨트랙트 배포하기
  • 뉴날 데이터 마켓
Powered by GitBook
On this page
  • 로깅 유틸리티
  • Printable trait
  • Substrate의 자체 Print 함수
  • std인 경우
  1. 인프라블록체인
  2. 튜토리얼
  3. 테스트

디버그

Previous런타임 확인Next테스트 네트워크에서 파라체인 시뮬레이션하기

Last updated 1 year ago

디버깅은 소프트웨어 개발의 모든 분야에서 필수적이며, 블록체인도 예외는 아닙니다. Rust 디버깅을 위해 사용되는 대부분의 도구는 Substrate에도 적용됩니다.

로깅 유틸리티

Rust의 로깅 API를 사용하여 런타임을 디버깅할 수 있습니다. 이를 위해 와 를 포함한 여러 매크로를 사용할 수 있습니다.

예를 들어, 팔렛의 Cargo.toml 파일을 로 업데이트한 후에는 log::info!를 사용하여 콘솔에 로그를 남길 수 있습니다:

pub fn do_something(origin) -> DispatchResult {

	let who = ensure_signed(origin)?;
	let my_val: u32 = 777;

	Something::put(my_val);

	log::info!("called by {:?}", who);

	Self::deposit_event(RawEvent::SomethingStored(my_val, who));
	Ok(())
}

Printable trait

Printable trait은 no_std와 std에서 런타임에서 출력하는 방법을 제공합니다. print 함수는 를 구현한 모든 타입과 함께 작동합니다. Substrate는 기본적으로 몇 가지 타입 (u8, u32, u64, usize, &[u8], &str)에 대해 이 trait을 구현합니다. 또한 사용자 정의 타입에 대해서도 구현할 수 있습니다. 다음은 노드 템플릿을 기반으로 한 팔렛의 Error 타입에 대한 구현 예시입니다.

use sp_runtime::traits::Printable;
use sp_runtime::print;
#[frame_support::pallet]
pub mod pallet {
	// 팔렛의 에러들
	#[pallet::error]
	pub enum Error<T> {
		/// 값이 None인 경우
		NoneValue,
		/// 값이 최대치에 도달하여 더 이상 증가할 수 없는 경우
		StorageOverflow,
	}

	impl<T: Config> Printable for Error<T> {
		fn print(&self) {
			match self {
				Error::NoneValue => "잘못된 값".print(),
				Error::StorageOverflow => "값이 초과되어 오버플로우 발생".print(),
				_ => "잘못된 에러 케이스".print(),
			}
		}
	}
}
/// 매개변수를 받지 않고, 스토리지 값을 증가시키려고 시도하고, 오류가 발생할 수 있음
pub fn cause_error(origin) -> dispatch::DispatchResult {
	// 서명된 것인지 확인하고 서명자를 가져옴. ensure_root와 ensure_none도 참고
	let _who = ensure_signed(origin)?;

	print!("내 테스트 메시지");

	match Something::get() {
		None => {
			print(Error::<T>::NoneValue);
			Err(Error::<T>::NoneValue)?
		}
		Some(old) => {
			let new = old.checked_add(1).ok_or(
				{
					print(Error::<T>::StorageOverflow);
					Error::<T>::StorageOverflow
				})?;
			Something::put(new);
			Ok(())
		},
	}
}

RUST_LOG 환경 변수를 사용하여 노드 바이너리를 실행하면 값들이 출력됩니다.

RUST_LOG=runtime=debug ./target/release/node-template --dev

값들은 런타임 함수가 호출될 때마다 터미널이나 표준 출력에 출력됩니다.

2020-01-01 tokio-blocking-driver DEBUG runtime  내 테스트 메시지  <-- str은 기본적으로 Printable을 구현합니다
2020-01-01 tokio-blocking-driver DEBUG runtime  잘못된 값    <-- NoneValue의 사용자 정의 문자열
2020-01-01 tokio-blocking-driver DEBUG runtime  DispatchError
2020-01-01 tokio-blocking-driver DEBUG runtime  8
2020-01-01 tokio-blocking-driver DEBUG runtime  0                <-- Error enum 정의에서의 인덱스 값
2020-01-01 tokio-blocking-driver DEBUG runtime  NoneValue        <-- 에러의 식별자 이름을 담고 있는 str

런타임에 출력 함수를 추가하면 디버그 코드가 포함된 Rust 및 Wasm 바이너리의 크기가 증가하므로 프로덕션에서는 필요하지 않습니다.

Substrate의 자체 Print 함수

use sp_runtime::print;

// --snip--
pub fn do_something(origin) -> DispatchResult {
	print!("do_something 실행");

	let who = ensure_signed(origin)?;
	let my_val: u32 = 777;

	Something::put(my_val);

	print!("my_val 저장 후");

	Self::deposit_event(RawEvent::SomethingStored(my_val, who));
	Ok(())
}
// --snip--

RUST_LOG 환경 변수를 사용하여 체인을 시작하면 출력 로그를 볼 수 있습니다.

RUST_LOG=runtime=debug ./target/release/node-template --dev

값들은 터미널이나 표준 출력에 출력됩니다. 오류가 트리거되면 출력됩니다.

2020-01-01 00:00:00 tokio-blocking-driver DEBUG runtime  do_something 실행
2020-01-01 00:00:00 tokio-blocking-driver DEBUG runtime  my_val 저장 후

std인 경우

이 매크로를 사용하는 한 가지 주의점은 내부 코드가 실제로 네이티브 버전의 런타임을 실행할 때만 실행된다는 것입니다.

use sp_std::if_std; // if_std! 매크로를 스코프에 가져옵니다.

println! 문은 if_std 매크로 내부에 있어야 합니다.

#[pallet::call]
impl<T: Config<I>, I: 'static> Pallet<T, I> {
		// --snip--
		pub fn do_something(origin) -> DispatchResult {

			let who = ensure_signed(origin)?;
			let my_val: u32 = 777;

			Something::put(my_val);

			if_std! {
				// 이 코드는 `std` 기능이 활성화된 경우에만 컴파일되고 실행됩니다.
				println!("안녕하세요 네이티브 월드!");
				println!("내 값은: {:#?}", my_val);
				println!("호출자 계정은: {:#?}", who);
			}

			Self::deposit_event(RawEvent::SomethingStored(my_val, who));
			Ok(())
		}
		// --snip--
}

값들은 런타임 함수가 호출될 때마다 터미널이나 표준 출력에 출력됩니다.

$		2020-01-01 00:00:00 Substrate Node
		2020-01-01 00:00:00   version x.y.z-x86_64-linux-gnu
		2020-01-01 00:00:00   by Anonymous, 2017, 2020
		2020-01-01 00:00:00 Chain specification: Development
		2020-01-01 00:00:00 Node name: my-node-007
		2020-01-01 00:00:00 Roles: AUTHORITY
		2020-01-01 00:00:00 Imported 999 (0x3d7a…ab6e)
		# --snip--
->		안녕하세요 네이티브 월드!
->		내 값은: 777
->		호출자 계정은: d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)
		# --snip--
		2020-01-01 00:00:00 Imported 1000 (0x3d7a…ab6e)

레거시 사용 사례에 대해 Substrate는 Print 디버깅(또는 추적)을 위한 추가 도구를 제공합니다. 를 사용하여 런타임 실행 상태를 로깅할 수 있습니다.

레거시 경우에는 print 이상의 작업을 수행하거나, 디버깅 목적으로 Substrate 특정 트레잇을 신경 쓰지 않고 싶을 수 있습니다. 이러한 경우에는 가 유용합니다.

debug
info
log 크레이트
Printable trait
print 함수
if_std! 매크로