> ## Documentation Index
> Fetch the complete documentation index at: https://docs.logbrew.co/llms.txt
> Use this file to discover all available pages before exploring further.

# 분산 트레이싱: 트레이스, 스팬, 컨텍스트

> LogBrew에서 분산 트레이스와 스팬이 요청, 로그, 이슈, 액션, 메트릭을 어떻게 연결하는지 알아보세요.

분산 트레이싱은 요청이나 작업 1건이 계측된 서비스를 거쳐 가는 과정을 따라갑니다. 트레이스는 그 작업에 속한 스팬을 묶습니다. 각 스팬은 HTTP 요청, 데이터베이스 호출, 큐 작업, 백그라운드 잡처럼 시간을 잰 작업 1개입니다. 스팬이 빠지면 경로의 일부를 알 수 없습니다.

로그에 실패는 보고되었지만 작업 경로가 없을 때 트레이스를 사용하세요. 트레이스로 다음을 확인할 수 있습니다.

* 어떤 작업이 요청을 시작했는지
* 요청이 어디에서 시간을 썼는지
* 어떤 자식 작업이 오류를 반환했는지
* 어떤 로그, 이슈, 액션, 메트릭이 같은 트레이스 ID를 가졌는지
* 어떤 서비스, 환경, 릴리스가 각 스팬을 보냈는지

## 트레이스와 스팬 필드

| 필드 | 의미 |
| - | - |
| `trace_id` | 스팬이 속한 트레이스를 식별합니다. |
| `span_id` | 트레이스 안의 작업 1개를 식별합니다. |
| `parent_span_id` | 자식 작업을 그 작업을 시작한 작업과 연결합니다. 루트 스팬에는 없습니다. |
| `name` | 라우트 템플릿처럼 작업에 붙인 이름입니다. |
| `operation` | `http.server`나 `db.query` 같은 작업 유형입니다. |
| `status` | `ok`, `error`, `cancelled` 같은 보고된 결과입니다. |
| `started_at` | 작업이 시작된 시각입니다. |
| `duration_ms` | 작업이 실행된 시간(밀리초)입니다. |
| `service_name`, `environment`, `release` | 스팬을 보낸 서비스의 범위입니다. |

루트 스팬은 트레이스를 시작하며 부모가 없습니다. 자식 스팬은 같은 트레이스 ID, 고유한 스팬 ID, 부모 ID를 가집니다. 작업은 이 ID로만 연결됩니다. 타임스탬프만으로는 연결되지 않습니다. LogBrew는 `status`가 `error`인 스팬만 오류 스팬으로 셉니다.

## 여러 서비스를 거치는 요청

1. 웹 서비스가 체크아웃 라우트의 서버 스팬을 시작합니다.
2. 결제 클라이언트가 아웃바운드 HTTP 요청의 자식 스팬을 만듭니다.
3. 결제 서비스가 자체 서버 스팬으로 트레이스를 이어 갑니다.
4. 데이터베이스 헬퍼가 쓰기 작업의 자식 스팬을 기록합니다.
5. 앱이 활성 결제 스팬 안에서 안전한 오류 로그를 보냅니다.

다섯 기록 모두 트레이스 ID가 같습니다. 트레이스 컨텍스트를 받지 못한 서비스의 작업은 시간이 겹치더라도 트레이스에 포함되지 않습니다.

## 컨텍스트 전파

LogBrew SDK는 W3C 트레이스 컨텍스트를 사용합니다. 예를 들어 Node.js SDK는 들어온 `traceparent` 헤더가 유효하면 새 요청 스팬으로 그 트레이스를 이어 갑니다. 헤더가 없거나 유효하지 않으면 새 루트를 시작합니다. 그 요청 범위 안에서 수집된 로그, 이슈, 액션, 메트릭은 요청의 트레이스를 가집니다.

아웃바운드 계측은 `tracePropagationTargets`처럼 직접 설정한 대상에만 `traceparent` 헤더를 씁니다. 트레이스 컨텍스트는 신뢰할 수 있고 계측된 서비스에만 보내세요. 트레이스 ID는 작업을 서로 연관 짓습니다. 인증 수단이 아닙니다.

큐 메시지도 트레이스 컨텍스트를 담을 수 있습니다. Node.js에서는 프로듀서 작업에서 `createLogBrewQueueTraceHeaders()`를 호출해 메시지에 `traceparent` 헤더를 추가하세요. 컨슈머에서는 그 헤더를 `queueOperationWithLogBrewSpan()`에 `traceparent`로 전달하세요. [JavaScript 큐 트레이싱](/ko/guides/sdk-ingestion#javascript-queue-tracing)을 참고하세요.

Node.js와 Python의 요청 연동과 아웃바운드 연동은 요청 본문, 응답 본문, 쿼리 문자열, 임의 헤더, 원시 `traceparent` 값을 스팬에 기록하지 않습니다. 스팬 이름은 구체적인 URL이 아니라 라우트 템플릿을 따라 지으세요. 사용하는 런타임의 연동 기능은 [SDK 연동](/ko/guides/sdk-ingestion) 문서를 참고하세요.

## <span id="capture-spans">수집 스팬</span>

LogBrew는 새 로그, 이슈, 액션, 메트릭을 모두 트레이스 ID와 함께 저장합니다. 시그널이 같은 전송에 포함된 스팬을 가리키지 않으면, LogBrew가 그 시그널에 수집 스팬 1개를 추가합니다.

| 필드 | 값 |
| - | - |
| `name` | `log capture`, `issue capture`, `action capture`, `metric capture` 중 하나 |
| `operation` | `logbrew.log`, `logbrew.issue`, `logbrew.action`, `logbrew.metric` 중 하나 |
| `duration_ms` | `0` |
| `parent_span_id` | 앱이 시그널을 수집할 때 활성 상태였던 스팬입니다. 활성 스팬이 없었으면 비어 있습니다. |
| `status` | 이슈, `error` 또는 `critical` 로그, 실패한 액션이면 `error`입니다. 그 밖에는 비어 있습니다. |
| `attributes.logbrew.evidence` | `signal_capture` |

이후 시그널의 `span_id`는 해당 수집 스팬을 가리킵니다. 시그널에 트레이스 컨텍스트가 없었다면 LogBrew가 새 트레이스 ID를 만듭니다. 이 트레이스는 LogBrew가 시그널을 저장했다는 사실만 보여 줍니다. 요청 경로를 보여 주지는 않습니다. 한 트레이스에 있는 수집 스팬을 요청 1건으로 해석하지 마세요.

수집 스팬도 `span_count`와 `error_span_count`에 포함됩니다. 그래서 애플리케이션 작업이 하나도 실패하지 않은 트레이스가 오류 로그 때문에 `--status error`로 선택될 수 있습니다. 결론을 내리기 전에 각 오류 스팬의 `operation`을 확인하세요.

## 트레이스 읽기

로그, 이슈, 트레이스 목록에서 가져온 정확한 트레이스 ID를 사용하세요.

```bash theme={null}
logbrew read traces --project "<project_id>" --status error --since 24h --json
logbrew read trace "<trace_id>" --project "<project_id>" --json
```

`--status error`는 오류 스팬이 1개 이상 있는 트레이스를 선택합니다. `--status ok`는 오류 스팬이 없는 트레이스를 선택합니다. `--min-duration-ms 500`은 500밀리초 이상 실행된 트레이스를 선택합니다.

먼저 루트 스팬의 소요 시간을 확인하세요. 그다음 가장 오래 걸린 자식 스팬과 오류 상태를 살펴보세요. 스테이징 트레이스를 프로덕션의 근거로 쓰지 않도록 프로젝트, 서비스, 환경, 릴리스를 계속 확인하세요.

트레이스 1개는 실행 1회를 보여 줄 뿐 성능 기준선이 아닙니다. 성능 개선을 제안하기 전에 여러 트레이스를 관련 메트릭 추세와 비교하세요.

### 트레이스 요약

`GET /api/telemetry/traces/{trace_id}/summary`는 스팬 속성 없이 요약을 반환합니다.

| 필드 | 의미 |
| - | - |
| `root_span` | 부모가 트레이스 안에 없는 스팬 중 가장 이른 스팬입니다. 모든 스팬의 부모가 트레이스 안에 있으면 가장 이른 스팬입니다. |
| `slowest_child_span` | 부모가 있는 스팬 중 가장 오래 걸린 스팬입니다. |
| `slowest_path` | 루트에서 가장 느린 자식 스팬까지 이어지는, 알려진 부모 체인입니다. |
| `error_spans` | 상태가 `error`인 스팬 중 가장 오래 걸린 스팬을 최대 5개까지 보여 줍니다. |
| `services` | 서비스별 스팬 수, 오류 스팬 수, 가장 긴 스팬 소요 시간입니다. |
| `duration_ms` | 가장 이른 스팬 시작부터 가장 늦은 스팬 종료까지의 시간입니다. |

`root_span.parent_span_id`에 값이 있으면 실제 루트 스팬은 트레이스에 없습니다. 이때 `root_span`을 요청의 시작으로 해석하지 마세요.

### 트레이스 분석하기

`logbrew explain trace`는 트레이스 조사 결과를 반환합니다.

```bash theme={null}
logbrew explain trace "<trace_id>" --json
```

| 필드 | 의미 |
| - | - |
| `analysis.status` | `errors_observed`, `latency_focus`, `no_error_observed` 중 하나입니다. |
| `analysis.first_error_span`, `analysis.first_error_path` | 가장 이른 오류 스팬과 그 스팬의 알려진 부모 체인입니다. |
| `analysis.bottleneck_span`, `analysis.bottleneck_path` | 부모가 있는 스팬 중 가장 오래 걸린 스팬과 그 스팬의 알려진 부모 체인입니다. |
| `correlations` | 같은 트레이스 ID를 가진 이슈, 로그, 액션, 메트릭입니다. 각 목록에는 `status`와 `truncated`가 있습니다. |
| `evidence` | 수집됨, 수집 안 됨, 가려짐, 잘림 상태의 필드입니다. |
| `next_actions` | 다음에 할 조회를 우선순위 순서로 나열합니다. |

`analysis.causality`는 `evidence_only`입니다. 이 분석은 근본 원인을 증명하지 않습니다. CLI는 응답 버전 3을 요청합니다. 이 버전에서는 관련 이슈, 액션, 메트릭마다 정확한 `span_id`도 들어 있습니다.

스팬 1개를 부모, 자식, 서비스 경계와 함께 살펴보려면 다음을 실행하세요.

```bash theme={null}
logbrew explain span "<trace_id>" "<span_id>" --project "<project_id>" \
  --environment production --release "<release>" --json
```

`topology.parent_chain_status`는 부모 체인이 완전한지 알려 줍니다.

| 값 | 의미 |
| - | - |
| `root` | 스팬에 부모 ID가 없습니다. |
| `complete` | 루트 스팬까지 모든 부모가 트레이스 안에 있습니다. |
| `missing` | 부모 ID가 트레이스에 없는 스팬을 가리킵니다. |
| `cycle` | 부모 ID가 순환 고리를 이룹니다. |
| `truncated` | 응답 한도 때문에 전체 체인을 보여 줄 수 없습니다. |
| `unavailable` | 트레이스 조회를 끝내지 못했습니다. |

## 트레이스 컨텍스트 누락

모든 이벤트에 요청 트레이스가 있는 것은 아닙니다. 트레이스 상태를 확인하세요.

| 상태 | 의미 |
| - | - |
| `available` | 정확한 트레이스 근거를 읽을 수 있습니다. |
| `not_linked` | 이벤트에 트레이스 ID가 없습니다. 일부 이전 이벤트에는 트레이스 ID가 없습니다. |
| `not_found` | 이벤트에 트레이스 ID가 있지만, 선택한 범위에서 일치하는 트레이스가 없습니다. |
| `unavailable` | 그 시점에 트레이스 근거를 읽지 못했습니다. |

`not_linked`는 오류가 아닙니다. `available` 상태의 트레이스로도 이벤트에 요청 컨텍스트가 없었다는 사실을 알 수 있습니다. 이벤트의 수집 스팬에 `parent_span_id`가 없으면, 앱이 이벤트를 수집할 때 활성 스팬이 없었던 것입니다. 요청 범위 밖의 백그라운드 작업에서 이런 결과가 자주 나옵니다. 빠진 관계를 찾으려면 다음 순서로 확인하세요.

1. 이벤트의 프로젝트, 서비스, 환경, 릴리스, 시각을 확인하세요.
2. 해당 작업이 계측된 요청이나 작업 안에서 실행되었는지 확인하세요.
3. 클라이언트 연동과 서버 연동이 그 경계를 넘어 컨텍스트를 전파하는지 확인하세요.
4. 계측을 고친 다음 새 이벤트를 수집해 읽어 보세요.

새 SDK 버전은 이전에 보낸 이벤트에 트레이스 컨텍스트를 추가하지 않습니다. 타임스탬프, 라우트, 메시지, 릴리스로 이벤트를 트레이스에 연결하지 마세요.

## 프로젝트 1개의 트레이싱 계획 세우기

체크아웃처럼 중요한 요청이나 잡 1개부터 시작하세요. 경계를 하나씩 계측하세요.

1. 들어오는 요청이나 백그라운드 작업에 대한 스팬을 만드세요.
2. 중요한 아웃바운드 호출에 자식 스팬을 추가하세요.
3. 신뢰할 수 있는 서비스 경계를 넘어 W3C 트레이스 컨텍스트를 이어 가세요.
4. 활성 스팬 안에서 안전한 로그를 보내세요.
5. 그 로그를 읽고 트레이스 ID를 연 다음, 루트, 자식, 서비스, 환경, 릴리스, 상태, 소요 시간을 확인하세요.

이 확인을 통과한 다음에만 다음 경계를 추가하세요. 같은 트레이스에 있다는 사실은 연관 관계를 보여 줍니다. 스팬 하나가 이슈를 일으켰다고 증명하지는 않습니다.

스팬 이름을 확인하려면 `logbrew traces --project "<project_id>" --pagination cursor --json`을 실행하세요. `naming_quality` 객체는 그 페이지에서 루트 이름이 일반적인 트레이스(`generic_name_traces`)와 일치하는 라우트가 없는 트레이스(`unmatched_route_traces`)의 수를 셉니다. 이름을 손봐야 하면 `naming_quality.next_action.code`가 `improve_trace_naming`입니다.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.