A code-to-column change-impact knowledge graph for AI coding agents.
| English | 한국어 |
엔진의 다른 모든 레인은 소스를 읽습니다. 이 레인만은 돌아간 시스템이 무엇을 했는지를 읽고, 그것을 소스가 만들어 낸 그래프 위에 겹쳐 놓습니다.
이 레인이 있는 이유는 소스가 넘지 못하는 벽이 하나 있기 때문입니다. 컨트롤러가
brandService.listBrand() 를 부를 때 소스가 지목하는 것은 인터페이스입니다.
어느 클래스가 응답하는지는 실행 시점에 Spring 이 정하므로, 그 호출의 정직한
읽기는 후보 집합이고 등급은 SOUND_SET 입니다. 구현체가 정확히 하나뿐일
때도 그렇습니다. 비관이 아닙니다. @Transactional 프록시, MyBatis 인터셉터,
@DS 데이터소스 전환, SQL 안의 <if> 는 각각 실제로 도는 클래스를 컴파일러가
지목할 클래스와 다르게 만들 수 있습니다. mapper 인터페이스는 한 걸음 더 나아가서
소스에 구현체가 아예 없습니다. 애플리케이션이 뜰 때 MyBatis 가 씁니다.
트레이스는 바로 그것을 풀어 줍니다. 어느 구현이 요청을 처리했고 어느 statement 를 돌렸는지를 관측하므로, 후보 집합 옆에 실제로 돈 구성원의 이름이 붙고 statement 바인딩에는 증인이 생깁니다. 그래프의 나머지는 아무것도 바뀌지 않습니다.
한 번 관측된 것이 항상은 아닙니다. 트레이스는 어떤 경로가 일어날 수 있다는 것을 증명할 뿐, 그것이 유일한 경로임을 증명하지는 않습니다. 그래서 이렇습니다.
observed: true 와 횟수를 얻습니다. SOUND_SET 에 관측이 더해져도 여전히
SOUND_SET 입니다. 트레이스 때문에 답이 정적 읽기보다 더 강하게 주장하는 상태는
이 엔진에 없습니다.RUNTIME_ONLY 등급의 MAY_CALL 엣지가 됩니다.
이 등급은 모든 질의 모드의 바닥 아래에 있으므로 chain, impact, census 중 어느
걷기도 이 엣지를 따라가지 않습니다.basis.runtimeEvidence 블록을 달고 다니며 트레이스 이름, span 수, 시간 창을
밝힙니다. 그래서 어떤 행에 표시가 없는 것을 본 독자는 그것이 “여기서는 아무것도
돌지 않는다”가 아니라 “이번 캡처가 여기를 지나가지 않았다”는 뜻임을 압니다.--otel <file> 이나 프로파일의 runtimeEvidence.otel
은 사람이 “이것을 일부러 캡처했다”고 말하는 것입니다. 트리에서 트레이스를 찾아
다니지 않습니다. 우연히 놓여 있던 JSON 파일이 이 pack 이 무엇을 돌았다고 주장할지
정하게 두어서는 안 되기 때문입니다.OTLP/JSON 형식의 OpenTelemetry 트레이스 익스포트입니다. 컬렉터의 파일
익스포터가 쓰는 resourceSpans 모양이고, Jaeger 나 Tempo 의 API 익스포트도 같은
모양입니다. 그 밖에는 아무것도 필요 없습니다. 우리 쪽 에이전트도, 분석 시점의
네트워크도, 데이터베이스도 쓰지 않습니다.
cascade analyze --root . --otel evidence/checkout-smoke.json
캡처가 여럿이면 --otel 을 반복합니다. 함께 접히므로, 같은 체인을 담은 두
트레이스는 두 횟수를 합한 하나의 표시가 됩니다.
보통은 여러분이 통제하는 실행 아래에서 도는 OpenTelemetry Java 에이전트가 출처입니다. 통합 테스트 묶음, 스모크 실행, 스테이징 트래픽의 한 조각 같은 것입니다. 기본 설정만으로 HTTP 서버 span 과 JDBC span 을 쓰므로 엔드포인트 조인과 statement 조인에는 그것으로 충분합니다. 디스패치 조인에는 메서드 span 이 더 필요하고, 얻는 방법은 둘입니다.
@WithSpan 을 붙이거나,otel.instrumentation.methods.include 에 클래스와 메서드를 지정).그런 다음 파일로 내보냅니다.
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.traces.exporter=otlp \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.service.name=storefront-api \
-jar app.jar
컬렉터의 파일 익스포터로 OTLP/JSON 을 쓰게 하면 됩니다. 같은 트레이스를 Jaeger 나 Tempo 에서 내보낸 것도 같은 모양이고 같게 읽힙니다.
무언가를 말할 수 있게 되고 싶은 대상을 캡처하십시오. 여기서 값을 만드는 것은 확인된 체인이지 담긴 양이 아니므로, 중요한 화면들을 지나는 5 분짜리 스모크 실행이 하루치 트래픽보다 훨씬 쓸모 있습니다.
이 레인이 쓸 수 있는 것을 담은 속성 모양은 셋입니다. 그중 아무것도 없는 span 은 쓸 수 없음으로 세고, 추측하지 않습니다.
| 무엇을 말하는가 | 읽는 속성 |
|---|---|
| 이름 있는 구체 클래스에서 메서드가 돌았다 | code.namespace + code.function(또는 code.function.name) |
| statement 가 돌았다 | db.statement(또는 db.query.text) |
| 엔드포인트가 호출되었다 | http.route(또는 http.target) + http.method(또는 http.request.method) |
각각의 옛 표기와 새 표기를 모두 받습니다. 어느 쪽이 나오는지는 여러분의 코드가 아니라 에이전트 버전이 정하기 때문입니다.
디스패치. 메서드 span 안에서 돈 메서드 span 은 “호출 대상이 호출자 안에서 돌았다”고 말합니다. 그것을 그래프에서 두 모양으로, 이 순서로 찾습니다.
caller --MAY_CALL--> callee 직접 엣지. 정적 레인이 이미 갖고 있던 것이므로
관측 표시를 붙이고 등급은 손대지 않습니다.caller --MAY_CALL--> interface#m --MAY_CALL--> callee. 중요한 것은
이쪽입니다. 이 두 홉 모양이 바로 인터페이스 디스패치 후보 집합이고,
트레이스는 그중 어느 구성원이 돌았는지를 방금 말한 것입니다. 두 홉 모두 관측
표시를 얻고, 둘 다 SOUND_SET 등급을 그대로 유지합니다.두 모양 중 어느 것도 없고, 또한 트레이스가 두 span 을 직접 중첩했으며,
또한 이 pack 이 두 심볼을 이미 갖고 있을 때만 RUNTIME_ONLY 등급의 새
MAY_CALL 엣지를 씁니다. 그 엣지는 호출 대상이 호출자 안에서 돌았다고 말할
뿐, 소스가 그것을 부른다고 말하지 않습니다. 중첩에 대한 정직한 읽기가 그것입니다.
컨트롤러를 감싸는 Spring 애스펙트가 정확히 이 모양이고, 소스의 어느 줄도 그것을
말하지 않습니다. 트레이스가 본 나머지는 놓을 자리를 찾지 못한 키와 함께
매칭되지 않음으로 셉니다. 이 pack 이 한 번도 읽지 않은 심볼은 이 레인이 만들어
낼 심볼이 아니기 때문입니다.
statement. SQL 을 담은 span 은 그것이 돈 mapper 메서드에 귀속되고,
owner.method statement 노드와 그리로 들어가는 IMPLEMENTS_STMT 엣지에 관측
표시가 붙습니다. SQL 이 실제로 지목한 테이블은 노드에 observedTables 로
기록되는데, 정적으로 유도된 EXECUTES 엣지 옆에 놓이지 그것을 대신하지
않습니다. 동적 SQL 이나 @DS 전환이 실행 시점에 고른 테이블은 보여 줄 발견이지
적용할 정정이 아닙니다.
엔드포인트. 서버 span 의 라우트를 이 pack 이 서빙하는 라우트와 맞춰 봅니다.
먼저 정확한 경로로, 그다음 라우트 템플릿으로 맞추므로 /brand/detail/12 는
/brand/detail/{brandId} 에 닿습니다. 그리고 엔드포인트 노드에 관측 표시가
붙습니다.
페이로드도, SQL 텍스트도 들어가지 않습니다. statement 의 SQL 은 그 안의 테이블
이름을 얻기 위해 읽고 나서 버립니다. 바인딩된 파라미터는 아예 읽지 않습니다.
트레이스가 pack 에 남기는 것은 observed 표시들, 횟수, 테이블 이름, 트레이스 파일
이름, 시간 창입니다. 그러므로 돌아가는 시스템에서 뜬 트레이스라도 그 시스템의
데이터를 분석에 들여오지 않습니다.
트레이스 파일의 내용 해시는 facts index 에 들어갑니다. pack 의 다른 모든 입력이 내용 주소로 다뤄지는 것과 같습니다. 그래서 pack 과 그것이 만들어진 캡처가 어느 캡처를 주장하는지에 대해 어긋날 수 없고, 같은 트레이스는 언제나 같은 pack 다이제스트를 냅니다.
실행이 자기 집계를 찍습니다.
Runtime evidence: 1 trace(s), 10 span(s) (1 carried nothing this lane reads), 7 observation(s):
3 dispatch, 1 statement and 2 route observation(s) matched this pack, 1 matched none
Runtime evidence: 4 static edge(s) marked observed (1 a call the source states,
1 a candidate set the trace narrowed), 1 RUNTIME_ONLY edge(s) added for a hop no
static rule explains, 1 statement(s) and 2 route(s) observed
Runtime evidence: a grade was neither raised nor lowered by any of this.
What the trace did not visit is unknown, not absent
그리고 답에서는 이렇습니다.
flow 의 행 중 트레이스가 본 메서드와 statement 에 observed: true 가 붙고,
구간 전체가 관측된 단계의 link 에도 붙습니다.endpoint_impact 의 행 중 실제로 요청을 서빙한 라우트에 observed: true 가
붙습니다.overview 는 runtime-evidence gap 을 달고, 얼마가 확인되었고 후보 집합이 몇
개나 좁혀졌으며 아무것도 승격되지 않았음을 말합니다.basis.runtimeEvidence 를 달고
다닙니다. observed 표시는 그것이 나온 커버리지 옆에서만 읽을 수 있기
때문입니다.meta.laneStats.otel 에 있습니다.{ "runtimeEvidence": { "har": [], "otel": ["evidence/checkout-smoke.json"] } }
경로는 manifest 디렉터리 기준입니다. runtimeEvidence.otel 은 analyze 가
--otel 없이 돌 때 읽히고, 둘 다 있으면 플래그가 이깁니다.
여러분의 애플리케이션을 실행하지 않고, 운영 접근을 요구하지 않으며, 트레이스가 담고 오지 않은 것을 풀어 보려 하지 않습니다. 그래프를 완전하게 만들지 않습니다. 지나간 경로를 관측된 것으로 만들고, 그것이 어느 것이었는지를 말할 뿐입니다.
관련 문서: 웹 레인과 브라우저 기록, CLI 레퍼런스, English