본문 바로가기
WIKI 기술 지식 베이스

C / C++ 로그 수집

원문 보기 위키 갱신

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %} 이 제품은 선택한 Datadog 사이트에서 지원되지 않아요. ({% placeholder "user-datadog-site-name" /%}). {% /alert %}

{% /callout %}

Datadog의 dd-sdk-cpp 라이브러리를 사용해 C 및 C++ 애플리케이션에서 Datadog로 로그를 보내고 다음 기능을 활용할 수 있어요:

  • JSON 형식으로 기본 제공되는 형태로 Datadog에 로그 기록.
  • 보내는 모든 로그에 사용자 정의 속성 추가.
  • 실제 클라이언트 IP 주소 기록.
  • 자동 벌크 게시로 네트워크 사용량 최적화.

출처: 문서

본문

설정

  1. 빌드 시스템에서 C++ SDK를 의존성으로 선언해 추가하세요.

{% tab title="CMake (FetchContent)" %} CMake의 FetchContent 모듈을 사용하면 SDK를 소스에서 다운로드·빌드해 바이너리 호환성을 보장하고 빌드 구성에 대한 완전한 제어권을 얻을 수 있어요.

프로젝트의 CMakeLists.txt에서 CMake의 FetchContent 모듈을 사용해 SDK를 프로젝트의 일부로 다운로드·빌드하세요:

include(FetchContent)
FetchContent_Declare(
    Datadog
    GIT_REPOSITORY https://github.com/DataDog/dd-sdk-cpp.git
    GIT_TAG        <version>
)
FetchContent_MakeAvailable(Datadog)

<version>을 SDK의 GitHub Releases의 릴리스 태그(예: 0.3.0)로 바꾸거나, 선택한 릴리스의 전체 커밋 SHA를 사용하세요.

SDK를 애플리케이션의 의존성으로 추가하려면 그 CMake 타깃을 datadog_enable()에 전달하세요:

datadog_enable(my-app)

CMake 설정에 대한 자세한 내용은 고급 빌드 구성을 참고하세요. {% /tab %}

{% tab title="CMake (find_package)" %} CMake를 사용하지만 미리 컴파일된 SDK 바이너리를 선호한다면 CMake의 find_package() 명령을 사용하세요.

  • SDK의 GitHub Releases에서 플랫폼용 릴리스 아카이브를 다운로드한 뒤, 프로젝트의 디렉터리(예: external/datadog-sdk/)에 압축을 풀어요.
  • CMakeLists.txt에서 그 디렉터리를 CMAKE_PREFIX_PATH에 추가하고 find_package를 호출하세요:
list(APPEND CMAKE_PREFIX_PATH external/datadog-sdk)
find_package(Datadog REQUIRED)

SDK를 애플리케이션의 의존성으로 추가하려면 그 CMake 타깃을 datadog_enable()에 전달하세요:

datadog_enable(my-app)

CMake 설정에 대한 자세한 내용은 고급 빌드 구성을 참고하세요. {% /tab %}

{% tab title="기타 빌드 시스템" %} CMake를 사용하지 않는다면 미리 컴파일된 바이너리를 다운로드하거나 소스에서 SDK를 빌드하세요. 그런 다음 컴파일러와 링커를 적절한 헤더·라이브러리에 연결하세요. 예를 들어 Makefile에서:

INCLUDES = -Iexternal/datadog-sdk/include
LDFLAGS  = -Lexternal/datadog-sdk/lib
LDLIBS   = -lddsdkcpp -lcurl -luuid

빌드 구성에 대한 자세한 내용은 고급 빌드 구성을 참고하세요. {% /tab %} 애플리케이션 컨텍스트와 Datadog 클라이언트 토큰으로 Datadog SDK를 초기화하세요. 보안상의 이유로 클라이언트 토큰을 사용해야 해요. Datadog API 키는 애플리케이션 바이너리에서 클라이언트 측에 노출되므로 dd-sdk-cpp 라이브러리 구성에 사용할 수 없어요. 클라이언트 토큰 설정에 대한 자세한 내용은 클라이언트 토큰 문서를 참고하세요.

애플리케이션 코드에서 적절한 SDK 헤더를 포함하세요:

{% tab title="C++" %}

#include "datadog.hpp"

{% /tab %}

{% tab title="C (FFI)" %}

#include "datadog.h"

{% /tab %}

애플리케이션의 시작 순서에서 가능한 한 일찍 Core를 생성하세요:

{% tab title="C++" %}

datadog::CoreConfig config("<client_token>", "<service>", "<env>");
config.SetApplicationStoragePath("<app-storage-dir>");
auto core = datadog::Core::Create(config, datadog::TrackingConsent::Granted);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_t config;
dd_core_config_init(&config, "<client_token>", "<service>", "<env>");
dd_core_config_set_application_storage_path(&config, "<app-storage-dir>");
dd_core_t* core = dd_core_create(&config, DD_TRACKING_CONSENT_GRANTED);

C API는 명시적 정리가 필요해요:

/* Free all resources held by the core when finished */
dd_core_destroy(core);

{% /tab %}

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: us3.datadoghq.com

Datadog 사이트 구성하기

SetSite를 사용해 Datadog 사이트로 SDK를 구성하세요.

{% tab title="C++" %}

config.SetSite(datadog::Site::us3);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_set_site(&config, DD_SITE_US3);

{% /tab %}

{% /callout %}

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: us5.datadoghq.com

Datadog 사이트 구성하기

SetSite를 사용해 Datadog 사이트로 SDK를 구성하세요.

{% tab title="C++" %}

config.SetSite(datadog::Site::us5);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_set_site(&config, DD_SITE_US5);

{% /tab %}

{% /callout %}

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: app.datadoghq.eu

Datadog 사이트 구성하기

SetSite를 사용해 Datadog 사이트로 SDK를 구성하세요.

{% tab title="C++" %}

config.SetSite(datadog::Site::eu1);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_set_site(&config, DD_SITE_EU1);

{% /tab %}

{% /callout %}

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: ap1.datadoghq.com

Datadog 사이트 구성하기

SetSite를 사용해 Datadog 사이트로 SDK를 구성하세요.

{% tab title="C++" %}

config.SetSite(datadog::Site::ap1);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_set_site(&config, DD_SITE_AP1);

{% /tab %}

{% /callout %}

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: ap2.datadoghq.com

Datadog 사이트 구성하기

SetSite를 사용해 Datadog 사이트로 SDK를 구성하세요.

{% tab title="C++" %}

config.SetSite(datadog::Site::ap2);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_set_site(&config, DD_SITE_AP2);

{% /tab %}

{% /callout %}

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: app.ddog-gov.com

Datadog 사이트 구성하기

SetSite를 사용해 Datadog 사이트로 SDK를 구성하세요.

{% tab title="C++" %}

config.SetSite(datadog::Site::us1_fed);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_set_site(&config, DD_SITE_US1_FED);

{% /tab %}

{% /callout %}

{% callout %}

다음 Datadog 사이트 사용자를 위한 중요 참고 사항: us2.ddog-gov.com

Datadog 사이트 구성하기

SetSite를 사용해 Datadog 사이트로 SDK를 구성하세요.

{% tab title="C++" %}

config.SetSite(datadog::Site::us2_fed);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_config_set_site(&config, DD_SITE_US2_FED);

{% /tab %}

{% /callout %}

<app-storage-dir>는 애플리케이션이 단독으로 사용하는 기존 디렉터리여야 해요. SDK는 그 안에 모든 임시 데이터를 저장할 .datadog/ 하위 디렉터리를 생성해요.

GDPR 규정을 준수하기 위해 SDK는 초기화 시 추적 동의(tracking consent) 값을 요구해요. 추적 동의는 다음 값 중 하나가 될 수 있어요:

  • Pending: SDK가 데이터를 수집해 로컬에 저장하지만 Datadog로는 보내지 않아요. SDK는 새 추적 동의 값을 기다렸다가 저장된 데이터를 어떻게 처리할지 결정해요.
  • Granted: SDK가 모든 대기 중 및 향후 데이터를 Datadog로 보내요.
  • NotGranted: SDK가 모든 대기 중 데이터를 삭제하고 더 이상 데이터를 수집하지 않아요.

SDK 초기화 후 추적 동의를 갱신하려면:

{% tab title="C++" %}

core->SetTrackingConsent(datadog::TrackingConsent::Pending);

{% /tab %}

{% tab title="C (FFI)" %}

dd_core_set_tracking_consent(core, DD_TRACKING_CONSENT_PENDING);

{% /tab %}

기타 SDK 구성 옵션에 대한 정보는 고급 구성을 참고하세요. Logging 기능을 활성화하고 SDK를 시작하세요: {% tab title="C++" %}

auto logging = datadog::Logging::Register(core);
core->Start();

{% /tab %}

{% tab title="C (FFI)" %}

dd_logging_t* logging = dd_logging_init(core);
dd_core_start(core);

C API는 명시적 정리가 필요해요:

/* Free all resources when finished */
dd_logging_destroy(logging);
dd_core_destroy(core);

{% /tab %} Logger를 생성하고 구성하세요: {% tab title="C++" %}

auto logger = logging->CreateLogger(
    datadog::LoggerConfig()
        .SetName("<logger_name>")
        .SetRemoteLogThreshold(datadog::LogLevel::Info)
);

{% /tab %}

{% tab title="C (FFI)" %}

dd_logger_config_t logger_config;
dd_logger_config_init(&logger_config);
dd_logger_config_set_name(&logger_config, "<logger_name>");
dd_logger_config_set_remote_log_threshold(&logger_config, DD_LOG_LEVEL_INFO);
dd_logger_t* logger = dd_logger_create(logging, &logger_config);

C API는 명시적 정리가 필요해요:

/* Free the logger when finished */
dd_logger_destroy(logger);

{% /tab %} 다음 메서드 중 하나로 사용자 정의 로그 항목을 Datadog로 보내세요: {% tab title="C++" %}

logger->Debug("A debug message.");
logger->Info("Some relevant information.");
logger->Notice("Have you noticed?");
logger->Warn("An important warning.");
logger->Error("An error occurred!");
logger->Critical("Something critical happened!");

{% /tab %}

{% tab title="C (FFI)" %}

dd_logger_debug(logger, "A debug message.", NULL, NULL);
dd_logger_info(logger, "Some relevant information.", NULL, NULL);
dd_logger_notice(logger, "Have you noticed?", NULL, NULL);
dd_logger_warn(logger, "An important warning.", NULL, NULL);
dd_logger_error(logger, "An error occurred!", NULL, NULL);
dd_logger_critical(logger, "Something critical happened!", NULL, NULL);

{% /tab %} (선택 사항) LogError를 사용해 로그 항목에 오류 컨텍스트를 붙이세요. 이는 진단 메시지와 함께 잡은 오류나 예외를 기록하는 데 유용해요. LogError에는 message, kind, stack의 세 가지 선택 필드가 있어요. {% tab title="C++" %}

datadog::LogError err;
err.message = "connection timed out";
err.kind    = "NetworkError";
err.stack   = "<stack trace>";
logger->Error("Failed to fetch config", err);

{% /tab %}

{% tab title="C (FFI)" %}

dd_log_error_t err = {0};
err.message = "connection timed out";
err.kind    = "NetworkError";
err.stack   = "<stack trace>";
dd_logger_error(logger, "Failed to fetch config", &err, NULL);

모든 dd_log_error_t 필드는 선택 사항이에요. 사용하지 않는 필드는 NULL로 설정하세요. {% /tab %} (선택 사항) 로그 메시지와 함께 속성을 제공해 생성되는 로그에 컨텍스트를 추가하세요. 속성은 객체로 전달해야 하며, 각 이름이 붙은 프로퍼티가 결과 로그 이벤트에 포함돼요. {% tab title="C++" %}

datadog::Attribute attrs = datadog::Attribute::Object(1);
attrs.SetObjectProperty("context", datadog::Attribute::String("onboarding flow"));
logger->Info("Clicked OK", {}, attrs);

{% /tab %}

{% tab title="C (FFI)" %}

dd_attribute_t attrs = dd_attribute_object(1);
dd_attribute_t context = dd_attribute_string("onboarding flow");
dd_attribute_object_property_set(&attrs, "context", &context);
dd_attribute_free(&context);

dd_logger_info(logger, "Clicked OK", NULL, &attrs);
dd_attribute_free(&attrs);

{% /tab %}

고급 로깅

로거 초기화

로거를 생성할 때 LoggerConfig의 다음 메서드를 사용할 수 있어요:

메서드 설명
SetName() 이 로거의 모든 로그에 붙는 logger.name 속성 값.
SetService() 이 로거의 service 표준 속성을 재정의해요. 기본값은 SDK 초기화 시 설정된 서비스예요.
SetRemoteLogThreshold() Datadog로 보내는 최소 로그 레벨. 이 레벨 아래의 로그는 삭제돼요.
SetRemoteSampleRate() 업로드할 로그 이벤트의 비율(0.0-100.0; 기본값: 100.0).
SetEnrichWithRumContext() 각 로그 이벤트에 활성 RUM 뷰·세션 컨텍스트를 붙여요(기본값: true).

글로벌 구성

다음 메서드를 사용해 지정된 로거가 보내는 모든 로그에 붙는 태그·속성을 추가하거나 제거하세요.

글로벌 태그
태그 추가

AddTag를 사용해 특정 로거가 보내는 모든 로그에 태그를 추가하세요:

{% tab title="C++" %}

// This adds a tag "build_type:release"
logger->AddTag("build_type", "release");

{% /tab %}

{% tab title="C (FFI)" %}

dd_logger_add_tag_kv(logger, "build_type", "release");

{% /tab %}

<TAG_VALUE>는 String이어야 해요. 자세한 내용은 태그 시작하기를 참고하세요.

태그 제거

RemoveTagsWithKey를 사용해 특정 로거가 보내는 로그에서 주어진 키의 모든 태그를 제거하세요:

{% tab title="C++" %}

// This removes all tags with key "build_type"
logger->RemoveTagsWithKey("build_type");

{% /tab %}

{% tab title="C (FFI)" %}

dd_logger_remove_tags_with_key(logger, "build_type");

{% /tab %}

글로벌 속성
속성 추가

AddAttribute를 사용해 특정 로거가 보내는 모든 로그에 영구 속성을 추가하세요:

{% tab title="C++" %}

// This adds an attribute "version_code" with an integer value for this logger instance.
logger->AddAttribute("version_code", datadog::Attribute::Int(42));

{% /tab %}

{% tab title="C (FFI)" %}

dd_attribute_t ver = dd_attribute_int(42);
dd_logger_add_attribute(logger, "version_code", &ver);
dd_attribute_free(&ver);

{% /tab %}

Logging 기능 객체에서 AddAttribute를 호출해 모든 로거 인스턴스에 걸쳐 속성을 전역으로 추가할 수도 있어요:

{% tab title="C++" %}

// This adds an attribute "version_name" with a string value in all logger instances.
logging->AddAttribute("version_name", datadog::Attribute::String("1.2.3"));

{% /tab %}

{% tab title="C (FFI)" %}

dd_attribute_t ver = dd_attribute_string("1.2.3");
dd_logging_add_attribute(logging, "version_name", &ver);
dd_attribute_free(&ver);

{% /tab %}

<ATTRIBUTE_VALUE>는 어떤 Attribute 유형이든 될 수 있어요: string, integer, double, Boolean 또는 중첩 객체나 배열.

속성 제거

RemoveAttribute를 사용해 특정 로거의 향후 로그에 속성이 붙지 않게 하세요:

{% tab title="C++" %}

// This removes the attribute "version_code" from all further logs sent from this logger instance.
logger->RemoveAttribute("version_code");

{% /tab %}

{% tab title="C (FFI)" %}

dd_logger_remove_attribute(logger, "version_code");

{% /tab %}

모든 로거 인스턴스에서 글로벌 속성을 제거하려면:

{% tab title="C++" %}

// This removes the attribute "version_name" from all further logs sent from all logger instances.
logging->RemoveAttribute("version_name");

{% /tab %}

{% tab title="C (FFI)" %}

dd_logging_remove_attribute(logging, "version_name");

{% /tab %}

배치 수집

모든 로그는 로컬 디바이스에 배치로 저장되며, SDK는 HTTP로 데이터 배치 업로드를 주기적으로 시도해요. 네트워크를 사용할 수 없거나 업로드가 실패하면 배치는 성공적으로 보낼 수 있을 때까지 유지돼요.

SDK의 디스크 사용량을 제한하기 위해, 디스크의 데이터는 너무 오래되면 자동으로 폐기돼요.

데이터가 Datadog로 업로드되기 전에는 구성한 애플리케이션 저장 디렉터리에 일반 텍스트로 저장돼요.

더 알아보기 (Learn more)