Abseil Flag introspection·validation
#검증 — Validator
flag 값이 합법한 범위인지 자동 검증.
#include "absl/flags/flag.h"
ABSL_FLAG(int32_t, port, 8080, "HTTP port");
static const auto port_validator = []() { int32_t p = absl::GetFlag(FLAGS_port); if (p <= 0 || p > 65535) { LOG(FATAL) << "invalid --port: " << p; } return true;}();또는 더 형식적인 AbslParseFlag 단계에서 검증(아래).
#Custom type — AbslParseFlag / AbslUnparseFlag
내장 타입 외에는 두 함수를 정의해 flag 시스템에 등록.
struct LogLevel { enum Value { kDebug, kInfo, kWarn, kError } value;};
bool AbslParseFlag(absl::string_view text, LogLevel* out, std::string* error) { if (text == "debug") { out->value = LogLevel::kDebug; return true; } if (text == "info") { out->value = LogLevel::kInfo; return true; } if (text == "warn") { out->value = LogLevel::kWarn; return true; } if (text == "error") { out->value = LogLevel::kError; return true; } *error = absl::StrCat("expected debug/info/warn/error, got ", text); return false;}
std::string AbslUnparseFlag(LogLevel level) { switch (level.value) { case LogLevel::kDebug: return "debug"; case LogLevel::kInfo: return "info"; case LogLevel::kWarn: return "warn"; case LogLevel::kError: return "error"; } return "?";}
ABSL_FLAG(LogLevel, log_level, LogLevel{LogLevel::kInfo}, "logging level");Parse는 유효성 검증을 포함 — 잘못된 값이면 false 반환하고 error에 메시지. ParseCommandLine이 이 에러를 표시한다.
$ ./app --log_level=traceERROR: --log_level=trace: expected debug/info/warn/error, got trace#Enum flag — 흔한 패턴
enum class Verbosity { kQuiet, kNormal, kVerbose, kDebug };
bool AbslParseFlag(absl::string_view text, Verbosity* v, std::string* err) { static const auto kMap = absl::flat_hash_map<absl::string_view, Verbosity>{ {"quiet", Verbosity::kQuiet}, {"normal", Verbosity::kNormal}, {"verbose", Verbosity::kVerbose}, {"debug", Verbosity::kDebug}, }; auto it = kMap.find(text); if (it == kMap.end()) { *err = absl::StrCat("unknown verbosity: ", text); return false; } *v = it->second; return true;}
std::string AbslUnparseFlag(Verbosity v) { switch (v) { case Verbosity::kQuiet: return "quiet"; case Verbosity::kNormal: return "normal"; case Verbosity::kVerbose: return "verbose"; case Verbosity::kDebug: return "debug"; } return "?";}
ABSL_FLAG(Verbosity, verbosity, Verbosity::kNormal, "logging verbosity");int flag보다 이름이 명령행에 노출 되어 readability가 좋다.
#Range validation — Parse 안에서
struct PortNumber { uint16_t value;};
bool AbslParseFlag(absl::string_view text, PortNumber* p, std::string* err) { int n; if (!absl::SimpleAtoi(text, &n)) { *err = absl::StrCat("not a number: ", text); return false; } if (n <= 0 || n > 65535) { *err = absl::StrCat("out of range [1, 65535]: ", n); return false; } p->value = static_cast<uint16_t>(n); return true;}
std::string AbslUnparseFlag(PortNumber p) { return absl::StrCat(p.value); }
ABSL_FLAG(PortNumber, port, PortNumber{8080}, "HTTP port");absl::SimpleAtoi로 안전 파싱. 잘못된 값이면 false로 거부.
#ReflectionFlag / introspection
런타임에 flag 메타데이터를 조회.
#include "absl/flags/reflection.h"
const absl::CommandLineFlag* f = absl::FindCommandLineFlag("port");if (f) { LOG(INFO) << "name: " << f->Name(); LOG(INFO) << "help: " << f->Help(); LOG(INFO) << "type: " << f->Typename(); LOG(INFO) << "current: " << f->CurrentValue(); LOG(INFO) << "default: " << f->DefaultValue();}모든 flag 순회:
absl::flags_internal::ForEachFlag([](absl::CommandLineFlag& f) { LOG(INFO) << f.Name() << " = " << f.CurrentValue();});debug endpoint(/_/flags)로 노출하면 운영 중 현재 설정 확인 가능.
#SetFlag — 런타임 변경
absl::SetFlag(&FLAGS_port, 9090); // 타입 안전
// 이름(문자열)으로 설정하려면 reflection API를 거친다std::string err;absl::FindCommandLineFlag("port")->ParseFrom("9090", &err);두 경로 모두 thread-safe. 다만 이미 캡처된 값은 안 바뀐다.
const bool verbose = absl::GetFlag(FLAGS_verbose); // 캡처absl::SetFlag(&FLAGS_verbose, true);if (verbose) { ... } // 여전히 이전 값런타임 변경을 감지하려면 매번 GetFlag 호출(atomic load — 가볍지만 hot path는 회피).
#Admin endpoint 예 — HTTP로 flag 변경
void HandleSetFlag(absl::string_view name, absl::string_view value) { auto* f = absl::FindCommandLineFlag(std::string(name)); if (!f) { Respond(404, "no such flag"); return; } std::string err; if (!f->ParseFrom(value, &err)) { Respond(400, absl::StrCat("invalid value: ", err)); return; } LOG(INFO) << "flag changed: " << name << " = " << value; Respond(200, "ok");}운영 중 디버그·실험 토글에 활용. prod 전용 권한 필수.
#회피 패턴
// 회피 — custom type validation 누락bool AbslParseFlag(absl::string_view text, MyType* m, std::string* err) { m->value = ParseSomething(text); // ❌ 항상 true 반환 return true;}
// Good — 검증bool AbslParseFlag(absl::string_view text, MyType* m, std::string* err) { if (!Validate(text, err)) return false; m->value = ParseSomething(text); return true;}// 회피 — int flag로 enum 표현ABSL_FLAG(int, log_level, 2, "0=debug, 1=info, 2=warn, 3=error"); // ❌ 의미 모호
// Good — enum + custom parserABSL_FLAG(LogLevel, log_level, LogLevel::kWarn, "...");// 회피 — 런타임 변경에 의존하면서 캡처int worker_count = absl::GetFlag(FLAGS_workers);StartPool(worker_count);// 이후 SetFlag(workers, ...) 해도 풀 크기 안 바뀜#정리
- 내장 타입 외 —
AbslParseFlag/AbslUnparseFlag한 쌍으로 custom 등록. Parse안에서 검증 + 변환 모두. 잘못된 값은false+err.- enum flag는 이름이 CLI에 노출 — int magic number 회피.
absl::FindCommandLineFlag+ForEachFlag로 런타임 introspection.SetFlag/SetFlagByName으로 동적 변경. 캡처된 값은 안 바뀌므로 hot path 주의.
#다음 장 예고
Part 13-01: Google 스타일의 Abseil 사용 패턴 — 코드 리뷰 정리.
#관련 항목
Abseil Code Review · 66 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 ParseCommandLine 동작
absl::ParseCommandLine — argv를 flag로 분리하고 positional 인자를 돌려주는 단일 진입점.
같은 시리즈에서 이어 읽기
ABSL_FLAG 정의 분석
ABSL_FLAG — gflags의 후속이자 Abseil 표준 command-line flag. type-safe definition과 GetFlag/SetFlag 접근.
같은 시리즈에서 이어 읽기
absl::PeriodicSampler — 적응형 샘플링·jitter 회피
absl::profiling_internal::PeriodicSampler — sampling rate를 동적으로 조정, geometric distribution으로 jitter 회피. 메모리 할당 추적·profiling 인프라의 기반.
같은 시리즈에서 이어 읽기