.NET 분산 추적 개념

분산 추적은 엔지니어가 특히 여러 머신 또는 프로세스에 분산될 수 있는 애플리케이션 내에서 오류 및 성능 문제를 지역화하는 데 도움이 되는 진단 기술입니다. 분산 추적이 유용한 위치 및 시작할 예제 코드에 관한 일반적인 내용은 분산 추적 개요를 참조하세요.

추적 및 활동

애플리케이션이 새 요청을 수신할 때마다 해당 요청을 추적과 연결할 수 있습니다. .NET으로 작성된 애플리케이션 구성 요소에서 추적의 작업 단위는 System.Diagnostics.Activity의 인스턴스로 나타내며 전체적으로 추적은 해당 활동의 트리를 구성하고 많은 개별 프로세스에 걸쳐 있을 수 있습니다. 새 요청에 대해 만들어진 첫 번째 활동은 추적 트리의 루트를 구성하며 요청을 처리하여 전체 시간 및 성공/실패를 추적합니다. 필요한 경우 자식 활동을 만들어 개별적으로 추적할 수 있는 여러 단계로 작업을 세분화할 수 있습니다. 예를 들어 웹 서버에서 특정 인바운드 HTTP 요청을 추적한 활동이 제공된 경우 요청을 완료하는 데 필요한 각 데이터베이스 쿼리를 추적하기 위해 자식 활동을 만들 수 있습니다. 이렇게 하면 각 쿼리의 기간 및 성공을 개별적으로 기록할 수 있습니다. 활동은 OperationName, 이름 값 쌍 Tags, Events와 같은 각 작업 단위의 기타 정보를 기록할 수 있습니다. 이름은 수행되는 작업의 유형을 식별하며 태그는 작업의 설명 매개 변수를 기록할 수 있고 이벤트는 타임스탬프 진단 메시지를 기록하는 간단한 로깅 메커니즘입니다.

참고 항목

분산 추적에서 작업 단위의 또 다른 일반적인 업계 이름은 ‘Span’입니다. .NET은 이 개념에 대해 ‘범위’라는 이름이 제대로 확립되기 여러 해 전에 ‘활동’이라는 용어를 채택했습니다.

작업 ID

분산 추적 트리에서 활동 간 부모-자식 관계는 고유한 ID를 사용하여 설정됩니다. .NET의 분산 추적 구현은 다음과 같은 두 가지 ID 체계를 지원합니다. W3C 표준 TraceContext는 .NET 5 이상의 기본값이며, ‘계층 구조’라는 이전 .NET 규칙은 이전 버전과의 호환성을 위해 사용할 수 있습니다. Activity.DefaultIdFormat은 사용되는 ID 체계를 제어합니다. W3C TraceContext 표준에서 모든 추적에는 전역적으로 고유한 16바이트 추적 ID(Activity.TraceId)가 할당되고 추적 내 모든 활동에는 고유한 8바이트 범위 ID(Activity.SpanId)가 할당됩니다. 각 활동은 추적 ID, 자체 범위 ID, 부모의 범위 ID(Activity.ParentSpanId)를 기록합니다. 분산 추적은 프로세스 경계에 걸쳐 작업을 추적할 수 있으므로 부모 및 자식 활동이 같은 프로세스에 없을 수도 있습니다. 추적 ID 및 부모 범위 ID를 조합하면 부모 활동이 있는 프로세스와 관계없이 전역적으로 부모 활동을 고유하게 식별할 수 있습니다.

Activity.DefaultIdFormat은 새 추적을 시작하는 데 사용되는 ID 형식을 제어하지만, 기본적으로 기존 추적에 새 활동을 추가하면 부모 활동이 사용 중인 형식이 사용됩니다. Activity.ForceDefaultIdFormat을 true로 설정하면 이 동작이 재정의되고 부모가 다른 ID 형식을 사용하는 경우에도 모든 새 활동이 DefaultIdFormat을 사용하여 생성됩니다.

활동 시작 및 중지

프로세스의 각 스레드에는 Activity.Current를 통해 액세스할 수 있는, 해당 스레드에서 발생하는 작업을 추적 중인 해당 Activity 개체가 있을 수 있습니다. 현재 활동은 서로 다른 스레드에서 처리되는 비동기 호출뿐만 아니라 한 스레드의 모든 동기 호출을 따라 자동으로 이동합니다. 활동 A가 스레드의 현재 활동이고 코드가 새 활동 B를 시작하면 B는 해당 스레드에서 새로운 현재 활동이 됩니다. 또한 기본적으로 활동 B는 활동 A를 부모로 처리합니다. 활동 B가 나중에 중지되면 활동 A가 스레드의 현재 활동으로 복원됩니다. 활동이 시작되면 현재 시간을 Activity.StartTimeUtc로 캡처합니다. 활동이 중지되면 Activity.Duration은 현재 시간과 시작 시간의 차이로 계산됩니다.

프로세스 경계에 걸쳐 조정

프로세스 경계에 걸쳐 작업을 추적하려면 수신 프로세스가 활동 부모 ID를 참조하는 활동을 만들 수 있도록 해당 ID를 네트워크 전체에 전송해야 합니다. W3C TraceContext ID 형식을 사용하는 경우 .NET은 표준에서 권장하는 HTTP 헤더를 사용하여 이 정보를 전송하기도 합니다. Hierarchical ID 형식을 사용하는 경우 .NET은 사용자 지정 요청 ID HTTP 헤더를 사용하여 ID를 전송합니다. 다른 많은 언어 런타임과는 달리 ASP.NET 웹 서버 및 System.Net.Http와 같은 .NET 기본 제공 라이브러리는 기본적으로 HTTP 메시지에서 활동 ID를 디코딩 및 인코딩하는 방법을 이해합니다. 이 런타임은 동기 및 비동기 호출을 통해 ID를 이동하는 방법도 이해합니다. 즉, HTTP 메시지를 받고 내보내는 .NET 애플리케이션은 앱 개발자의 특별한 코딩이나 타사 라이브러리 종속성 없이 자동으로 분산 추적 ID를 이동하는 데 참여합니다. 타사 라이브러리는 HTTP가 아닌 메시지 프로토콜을 통해 ID를 전송하기 위한 지원을 추가하거나 HTTP를 위한 사용자 지정 인코딩 규칙을 지원할 수 있습니다.

추적 수집

계측된 코드는 분산 추적의 일부로 Activity 개체를 만들 수 있지만, 나중에 전체 추적을 유용하게 검토할 수 있도록 해당 개체의 정보를 중앙 영구 저장소에 전송하고 직렬화해야 합니다. Application Insights, OpenTelemetry 또는 타사 원격 분석이나 APM 공급업체에서 제공하는 라이브러리와 같이 이 작업을 수행할 수 있는 여러 원격 분석 컬렉션 라이브러리가 있습니다. 또는 개발자는 System.Diagnostics.ActivityListener 또는 System.Diagnostics.DiagnosticListener를 사용하여 고유한 사용자 지정 활동 원격 분석 컬렉션을 작성할 수 있습니다. ActivityListener는 개발자에게 활동에 관한 사전 지식이 있는지와 관계없이 모든 활동 관찰을 지원합니다. 이를 통해 ActivityListener는 간단하고 유연한 범용 솔루션이 됩니다. 대조적으로, DiagnosticListener 사용은 DiagnosticSource.StartActivity를 호출하여 계측된 코드를 옵트인해야 하는 더 복잡한 시나리오이며 컬렉션 라이브러리는 시작 시 계측된 코드가 사용한 정확한 명명 정보를 알고 있어야 합니다. DiagnosticSource 및 DiagnosticListener를 사용하면 작성자와 수신기가 임의 .NET 개체를 교환하고 사용자 지정 정보 전달 규칙을 설정할 수 있습니다.

샘플링

높은 처리량 애플리케이션의 성능 향상을 위해 .NET의 분산 추적은 모든 추적을 기록하는 대신 추적 하위 집합만 샘플링하는 기능을 지원합니다. 권장 ActivitySource.StartActivity API를 사용하여 만든 활동의 경우 원격 분석 컬렉션 라이브러리는 ActivityListener.Sample 콜백을 사용하여 샘플링을 제어할 수 있습니다. 로깅 라이브러리는 활동을 전혀 만들지 않거나, 분산 추적 ID를 전파하는 데 필요한 최소 정보를 사용하여 활동을 만들거나, 전체 진단 정보를 채우기 위해 선택할 수 있습니다. 해당 선택 항목은 진단 유용성을 높이기 위해 성능 오버헤드를 늘립니다. Activity.ActivityDiagnosticSource.StartActivity를 호출하는 이전 패턴을 사용하여 시작되는 활동은 먼저 DiagnosticSource.IsEnabled를 호출하여 DiagnosticListener 샘플링을 지원할 수도 있습니다. 전체 진단 정보를 캡처하는 경우에도 .NET 구현은 효율적인 수집기와 결합하여 속도가 빠르도록 설계되었습니다(최신 하드웨어에서 1마이크로초 내에 활동을 만들고 채우고 전송할 수 있음). 샘플링은 기록되지 않은 각 활동의 계측 비용을 100나노초 미만으로 줄일 수 있습니다.

다음 단계

.NET 애플리케이션에서 분산 추적 사용을 시작하는 예제 코드는 분산 추적 계측을 참조하세요.