Abseil LOG·VLOG·CHECK 분석
#absl::log의 위치
Google은 오랜 기간 glog 를 사용해 왔다. Abseil의 absl/log/는 glog의 후속이며 인터페이스가 거의 동일하다.
#include "absl/log/log.h"#include "absl/log/check.h"
LOG(INFO) << "user " << user_id << " logged in";LOG(WARNING) << "slow query: " << elapsed;LOG(ERROR) << "failed to send: " << status;
CHECK(ptr != nullptr) << "ptr must be set";CHECK_EQ(actual, expected) << "mismatch";스트림 인터페이스(operator<<)가 표준이다. 인자가 absl::AlphaNum 호환이면(거의 모든 primitive·string·absl::Time 등) 자동 변환.
#Severity 레벨
| 매크로 | 의미 | 보통 동작 |
|---|---|---|
LOG(INFO) | 정보 | stderr/파일 |
LOG(WARNING) | 경고 | stderr/파일 |
LOG(ERROR) | 에러 | stderr/파일 + alert |
LOG(FATAL) | 치명 | 로그 후 abort |
LOG(QFATAL) | 조용한 fatal | stack trace 없이 종료 |
LOG(DFATAL) | debug=FATAL, release=ERROR | 개발 중에만 abort |
FATAL은 반드시 종료. 절대 호출 후 코드가 실행되지 않는다고 가정한다(noreturn 표시).
#초기화 — InitializeLog
main에서 한 번 호출.
#include "absl/log/initialize.h"
int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); absl::InitializeLog(); // ... 이후 LOG 사용 가능}호출 전에는 LOG가 안전히 raw fallback으로 동작(stderr에 단순 출력)한다. 그러나 sink·level 설정이 적용되지 않으므로 production 코드는 초기화를 잊지 말 것.
#출력 포맷
기본 출력은 다음과 같은 한 줄이다.
I20260525 13:00:00.123456 12345 file.cc:42] user 123 logged inI— severity 첫 글자 (I/W/E/F)- 타임스탬프 — UTC, ms 정밀도
- thread id
- 소스 파일 + 라인
- 본문
--log_format/--stderrthreshold 같은 flag로 조절 가능.
#VLOG — verbose level
INFO보다 자세한 정보를 조건부 로 남긴다.
VLOG(1) << "step 1 details";VLOG(2) << "step 1 inner detail";VLOG(3) << "raw payload: " << payload;--v=2 같은 flag로 활성화. 2 이하 레벨만 출력. 비활성 상태에서는 인자 평가도 안 일어남 (if (VLOG_IS_ON(2)) 등가).
VLOG(2) << "expensive: " << ComputeDump(); // ComputeDump 호출 안 됨 — --v < 2이 lazy evaluation 덕에 production에서 자유롭게 VLOG를 뿌려도 비용 없음.
#CHECK — runtime assertion
assert보다 강한 invariant. release 빌드에서도 활성화.
CHECK(ptr != nullptr) << "ptr required";CHECK_EQ(a, b) << "expected a == b, got " << a << " vs " << b;CHECK_NE(x, 0);CHECK_LT(idx, size);CHECK_GE(count, 0);실패 시 LOG(FATAL) → stack trace + abort. 메시지는 실패 직전에만 평가되어 lazy.
CHECK(x.IsValid()) << "x=" << x.DebugDump(); // DebugDump는 실패 시에만 호출#DCHECK — debug 한정
CHECK의 debug-only 버전. release 빌드에서는 완전히 사라진다.
DCHECK(invariant) << "..."; // -DNDEBUG에서 no-opDCHECK_EQ(size, expected);성능에 민감한 hot path에서 비싼 invariant 검증에 적합.
#QCHECK — quiet check
QFATAL의 짝. 실패 시 stack trace 없이 종료.
QCHECK(absl::ParseFlag(input, &v, &err)) << "bad input: " << err;flag·configuration 검증처럼 사용자 입력 에러는 stack trace가 노이즈가 되므로 QCHECK가 깔끔하다.
#LOG_EVERY_N / LOG_FIRST_N
쏟아지는 로그를 제한.
LOG_EVERY_N(WARNING, 100) << "rare event"; // 100번에 한 번LOG_FIRST_N(INFO, 5) << "first 5 only"; // 처음 5번만LOG_EVERY_N_SEC(INFO, 10) << "every 10s"; // 10초에 한 번내부적으로 thread-local counter. 멀티스레드에서는 정확한 N마다가 아니라 근사. 디버그 dump 용도면 충분.
#매크로의 효율
LOG(INFO)는 if (Enabled(INFO)) 검사를 인라인으로 한다. 비활성 severity면 분기 한 번 이면 끝나고 메시지 인자 평가도 일어나지 않는다.
LOG(VERBOSE) << ExpensiveDump(); // VERBOSE 비활성이면 ExpensiveDump 호출 안 됨#작은 예시 — 요청 핸들러
absl::Status HandleRequest(const Request& req) { VLOG(1) << "request: " << req.DebugString();
CHECK(!req.user_id().empty()) << "user_id required";
auto user = LookupUser(req.user_id()); if (!user.ok()) { LOG(WARNING) << "lookup failed for " << req.user_id() << ": " << user.status(); return user.status(); }
auto resp = Process(*user, req); if (!resp.ok()) { LOG(ERROR) << "process failed: " << resp.status(); return resp.status(); }
LOG_EVERY_N(INFO, 1000) << "processed " << req.user_id(); return absl::OkStatus();}#회피 패턴
// 회피 — std::cerr / printfstd::cerr << "error: " << status << "\n"; // ❌ thread-unsafe interleavingprintf("%s\n", msg.c_str()); // ❌ format 안 맞을 수 있음
// GoodLOG(ERROR) << "error: " << status;// 회피 — LOG가 비싼 경우에도 항상 평가LOG(INFO) << "dump: " << ExpensiveDump(); // INFO 비활성이면 낭비
// Good — VLOG로 lazyVLOG(1) << "dump: " << ExpensiveDump();// 회피 — CHECK 대신 if + returnif (!ptr) return absl::InternalError("null"); // ⚠️ invariant 위반인데 복구?
// Good — invariant이면 CHECKCHECK(ptr != nullptr) << "internal invariant";CHECK는 불변식 위반은 곧 버그 라는 의미. 사용자 입력 검증은 Status로.
#정리
LOG(severity)로 스트림 인터페이스. severity별 destination.VLOG(N)+--v=N— 조건부 verbose. 비활성 시 인자 평가 안 됨.CHECK/CHECK_EQ/CHECK_NE등 — release 빌드에서도 활성. invariant 위반 시 abort.DCHECK— debug 한정. release에서 사라짐.LOG_EVERY_N계열로 로그 스팸 억제.
#다음 장 예고
Part 11-02: LogSink — 출력 대상 커스터마이징.
#관련 항목
Abseil Code Review · 60 of 79
- 1 Abseil Code Review — Google production-grade C++ 라이브러리 분석
- 2 Abseil 개요 — Google이 std를 보완한 이유
- 3 Abseil 설계 철학 — std 호환과 추가 기능의 균형
- 4 Abseil 빌드와 의존성 — Bazel vs CMake
- 5 Abseil LTS vs HEAD 릴리스 모델 분석
- 6 Abseil Versioning과 ABI 호환성 정책
- 7 Abseil 매크로 — ABSL_HAVE_*·ABSL_ATTRIBUTE_*
- 8 Abseil ABSL_PREDICT_TRUE/FALSE — branch hint
- 9 absl::LogSeverity — 로그 레벨 타입
- 10 Abseil type_traits — negation·conjunction·void_t
- 11 Abseil Conformance·Policy 분석
- 12 Abseil Memory utilities 분석
- 13 Abseil raw_logging — heap-free 로깅
- 14 Abseil thread_annotations — clang TSA 통합
- 15 absl::Status — exception-free error handling
- 16 absl::StatusOr<T> — 값 또는 에러
- 17 absl status_macros — ASSIGN_OR_RETURN·RETURN_IF_ERROR
- 18 absl::Status payload — 구조화된 에러 컨텍스트
- 19 absl::Status ↔ exception 변환 패턴
- 20 absl::string_view — non-owning 문자열 참조
- 21 absl::string_view 함정 — dangling·c_str·임시 객체
- 22 absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
- 23 absl::StrSplit — Delimiter·Predicate·컨테이너 변환
- 24 absl::StrJoin — 컨테이너 결합과 Formatter
- 25 absl::StrFormat — type-safe printf·FormatSpec
- 26 Abseil ASCII 함수 — locale-free 분류·대소문자 변환
- 27 Abseil Escape — CEscape·HexEscape·Base64
- 28 absl::flat_hash_map — Swiss Table 기반 hash map
- 29 absl::flat_hash_set — set 버전 Swiss Table
- 30 absl::node_hash_map — stable pointer가 필요할 때
- 31 absl::btree_map — sorted·cache-friendly B-tree
- 32 absl::FixedArray — 런타임 크기 stack 배열
- 33 absl::InlinedVector — small buffer optimization
- 34 Abseil Swiss Table internals — control byte·SIMD probing
- 35 absl::Mutex — reader-writer·fairness·deadlock 검출
- 36 absl::Mutex Conditional Critical Section — Await로 cv 없애기
- 37 absl::Notification — once-only signal
- 38 absl::BlockingCounter·Barrier — 다중 thread 조율
- 39 absl::Mutex annotations — clang thread-safety로 race를 컴파일 타임에
- 40 absl::Time·Duration 분석 — 단단한 type
- 41 absl::Time Format·Parse
- 42 absl::CivilTime 분석
- 43 absl::time_zone 분석
- 44 absl::Time mocking — 테스트 친화 시간
- 45 absl::BitGen — 모던 난수 생성기
- 46 Abseil Random Distributions — Uniform·Exponential
- 47 Abseil Mocking Random — 테스트 결정성
- 48 Abseil Random Seeding·Entropy
- 49 absl::int128·uint128 분석
- 50 absl::bits — popcount·countl_zero
- 51 absl::optional vs std::optional
- 52 absl::variant 분석
- 53 absl::span 분석
- 54 absl::any 분석
- 55 absl::compare — three-way 비교
- 56 Abseil utility — apply·in_place
- 57 Abseil AbslHashValue 분석
- 58 Abseil HashState chaining
- 59 Abseil Custom hashable 구현
- 60 Abseil LOG·VLOG·CHECK 분석
- 61 Abseil LogSink 분석
- 62 Abseil LogEntry·structured logging
- 63 Abseil Stack trace·failure_signal_handler
- 64 ABSL_FLAG 정의 분석
- 65 Abseil ParseCommandLine 동작
- 66 Abseil Flag introspection·validation
- 67 Google 스타일의 Abseil 사용 패턴
- 68 Abseil 자주 보는 anti-pattern
- 69 std → absl 마이그레이션 전략
- 70 absl::Cleanup — 함수 종료 시 실행 보장
- 71 Abseil algorithm container 확장 — c_sort·c_find_if·c_count_if
- 72 absl::function_ref와 any_invocable — 함수 객체 전달의 두 축
- 73 absl::bind_front와 Overload — 함수 객체 보조 도구
- 74 absl::Cord — 분산 시스템용 대용량 문자열
- 75 absl::from_chars·SimpleAtoi — 빠른 숫자 변환
- 76 absl::Cord vs std::string — 선택 기준과 메모리 프로파일
- 77 absl::GetStackTrace와 Symbolize — crash 시 readable stack
- 78 absl::ComputeCrc32c — 하드웨어 가속 체크섬
- 79 absl::PeriodicSampler — 적응형 샘플링·jitter 회피
관련 글
Abseil Stack trace·failure_signal_handler
absl::Symbolize, GetStackTrace, InstallFailureSignalHandler — crash 시점에 stack을 찍어 남기는 진단 인프라.
같은 시리즈에서 이어 읽기
Abseil LogEntry·structured logging
absl::LogEntry — 한 로그 항목의 메타데이터(severity, timestamp, source location, message). 구조화 로깅의 기반.
같은 시리즈에서 이어 읽기
Abseil LogSink 분석
absl::LogSink — 출력 destination 커스터마이징. 파일·syslog·원격 collector·테스트 캡처.
같은 시리즈에서 이어 읽기
이 글을 참조하는 글 (9)
- Abseil ParseCommandLine 동작 — Abseil Code Review
- Abseil Stack trace·failure_signal_handler — Abseil Code Review
- Abseil LogEntry·structured logging — Abseil Code Review
- Abseil LogSink 분석 — Abseil Code Review
- Abseil Custom hashable 구현 — Abseil Code Review
- absl::Time Format·Parse — Abseil Code Review
- absl::Status ↔ exception 변환 패턴 — Abseil Code Review
- Abseil raw_logging — heap-free 로깅 — Abseil Code Review
- absl::LogSeverity — 로그 레벨 타입 — Abseil Code Review