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

PHP 로그와 트레이스 상호 연관 (Correlating PHP Logs and Traces)

원문 보기 위키 갱신

PHP 애플리케이션의 로그에 트레이스 ID를 주입해 Datadog에서 로그와 트레이스를 연결하는 방법을 안내해요.

출처: 문서

본문

자동 주입

버전 1.12.0부터 PHP 트레이서는 애플리케이션 로그에 트레이스 상호 연관 식별자를 자동으로 주입해요. 이전 트레이서 버전에서 자동 주입을 활성화하려면 환경 변수 DD_LOGS_INJECTION(INI 설정 datadog.logs_injection)을 true로 설정해요.

PHP 트레이서는 Monolog 또는 Laminas Log 같은 PSR-3 호환 로거를 지원해요.

참고: 로깅 라이브러리를 설정해 로그를 JSON 형식으로 생성하도록 해서:

  • 커스텀 파싱 규칙이 필요 없게 하고
  • 스택 트레이스가 로그 이벤트에 제대로 래핑되도록 해요.

로그에서 주입 구성

아직 하지 않았다면 PHP 트레이서를 DD_ENV, DD_SERVICE, DD_VERSION으로 구성해요. 이렇게 하면 로그에 env, service, version을 추가하는 데 최상의 경험이 제공돼요 (자세한 내용은 Unified Service Tagging 참조).

PHP 트레이서는 로그에 트레이스 상호 연관 식별자를 주입하는 다양한 방법을 제공해요:

  • 모든 트레이스 상호 연관 식별자를 로그 컨텍스트에 추가
  • 메시지에서 플레이스홀더 사용
옵션 1: 모든 트레이스 상호 연관 식별자를 로그 컨텍스트에 추가

PHP 트레이서의 기본 동작은 모든 트레이스 상호 연관 식별자를 로그 컨텍스트에 추가하는 것이에요.

예를 들어 Laravel 애플리케이션에서 Monolog 라이브러리를 다음과 같이 사용한다면:

use Illuminate\Support\Facades\Log;
# ...
Log::debug('Hello, World!');

PHP 트레이서는 사용 가능한 트레이스 상호 연관 식별자를 JSON 형식으로 로그 컨텍스트에 추가해요. 위의 로깅된 메시지는 다음과 같이 변환될 수 있어요:

[2022-12-09 16:02:42] production.DEBUG: Hello, World! {"dd.trace_id":"1234567890abcdef","dd.span_id":"1234567890abcdef","dd.service":"laravel","dd.version":"8.0.0","dd.env":"production","status":"debug"}

참고: 메시지에 플레이스홀더가 있거나 메시지에 트레이스 ID가 이미 있으면 PHP 트레이서는 트레이스 상호 연관 식별자를 로그 컨텍스트에 추가하지 않아요.

옵션 2: 메시지에서 플레이스홀더 사용

메시지에서 플레이스홀더를 사용해 로그에 자동으로 주입할 트레이스 상호 연관 식별자를 선택할 수 있어요. PHP 트레이서는 다음 플레이스홀더를 지원해요:

  • %dd.trace_id%: 트레이스 ID
  • %dd.span_id%: 스팬 ID
  • %dd.service%: 서비스 이름
  • %dd.version%: 서비스 버전
  • %dd.env%: 서비스 환경

플레이스홀더는 대소문자를 구분하며 % 문자로 감싸야 해요.

예를 들어 Laravel 애플리케이션에서 Monolog 라이브러리를 사용한다면 로그 메시지에 주입을 다음과 같이 구성할 수 있어요:

use Illuminate\Support\Facades\Log;
# ...
Log::info('Hello, World! [%dd.trace_id% %dd.span_id% %status%]');

PHP 트레이서는 플레이스홀더를 해당 값으로 바꿔요. 예를 들어 위의 로깅된 메시지는 다음과 같이 변환돼요:

[2022-12-09 16:02:42] production.INFO: Hello, World! [dd.trace_id="1234567890abcdef" dd.span_id="1234567890abcdef" status="info"]

참고: PHP 로그 파이프라인에서 제공하는 기본 파싱 규칙을 사용하려면 대괄호가 필수예요. 커스텀 파싱 규칙을 사용한다면 필요에 따라 대괄호를 생략할 수 있어요.

수동 주입

참고: \DDTrace\current_context() 함수는 버전 0.61.0에서 도입되었으며 10진수 트레이스 식별자를 반환해요.

로그와 트레이스를 연결하려면 로그에 각각 트레이스 ID와 스팬 ID를 담는 dd.trace_id와 dd.span_id 속성이 포함되어야 해요.

로그를 파싱하기 위해 Datadog 로그 통합을 사용하지 않는다면, 커스텀 로그 파싱 규칙에서 dd.trace_id와 dd.span_id가 문자열로 파싱되고 Trace Remapper로 리매핑되도록 해야 해요. 자세한 내용은 연관된 로그가 트레이스 ID 패널에 표시되지 않음에서 확인할 수 있어요.

예를 들어 다음 두 속성을 로그에 추가하려면:

  <?php
  $append = sprintf(
      ' [dd.trace_id=%s dd.span_id=%s]',
      \DDTrace\logs_correlation_trace_id(),
      \dd_trace_peek_span_id()
  );
  my_error_logger('Error message.' . $append);
?>

로거가 monolog/monolog 라이브러리를 구현한다면 Logger::pushProcessor()를 사용해 모든 로그 메시지에 식별자를 자동으로 추가해요. monolog v1의 경우 다음 구성을 추가해요:

<?php
  $logger->pushProcessor(function ($record) {
      $record['message'] .= sprintf(
          ' [dd.trace_id=%s dd.span_id=%s]',
          \DDTrace\logs_correlation_trace_id(),
          \dd_trace_peek_span_id()
      );
      return $record;
  });
?>

monolog v2의 경우 다음 구성을 추가해요:

<?php
  $logger->pushProcessor(function ($record) {
      return $record->with(message: $record['message'] . sprintf(
          ' [dd.trace_id=%s dd.span_id=%s]',
          \DDTrace\logs_correlation_trace_id(),
          \dd_trace_peek_span_id()
      ));
    });
  ?>

애플리케이션이 JSON 로그 형식을 사용한다면 로그 메시지에 trace_id와 span_id를 추가하는 대신 trace_id와 span_id를 포함하는 1차 키 dd를 추가할 수 있어요:

<?php
  $logger->pushProcessor(function ($record) use ($context) {
      $record['dd'] = [
          'trace_id' => \DDTrace\logs_correlation_trace_id(),
          'span_id'  => \dd_trace_peek_span_id()
      ];

      return $record;
  });
?>

monolog v3의 경우 다음 구성을 추가해요:

<?php
  $logger->pushProcessor(function ($record) {
        $record->extra['dd'] = [
            'trace_id' => \DDTrace\logs_correlation_trace_id(),
            'span_id'  => \dd_trace_peek_span_id()
        ];
        return $record;
    });
?>

로그를 JSON으로 수집한다면 JSON 로그 전처리로 이동해 Trace Id Attributes 필드에 extra.dd.trace_id를 추가해요.

더 알아보기 (Learn more)