See your request travel through the system.
Uma dependência. Zero configuração. A árvore completa do que a sua aplicação fez — ao vivo, no navegador, sem deixar a sua máquina.
O Trace2Local transforma a sua aplicação Java numa runtime canvas interativa:
descubra endpoints, dispare requisições do próprio navegador e acompanhe a árvore
da execução em tempo real — código, DynamoDB (delta before/after), SNS, SQS e
SQL — em http://localhost:9876/trace2local.
Ergonomia do Swagger UI, ambição do tracing distribuído: nada sai da sua máquina, tudo em memória, e a UI declara o que não conseguiu observar — nunca inventa.
- Por que Trace2Local
- Demonstração
- Quickstart
- Instalador Maven
- Instrumentação
- Como funciona
- Arquitetura e módulos
- Configuração
- Segurança
- Compatibilidade
- Testes e qualidade
- Documentação
- Roadmap
- Declarações de honestidade
- Contribuindo
- Licença
| 🔍 Árvore em tempo real | Cada requisição vira uma árvore de nós (HTTP, negócio, banco, mensageria) com waterfall de tempos, self-time e erros — a UI reconstrói a árvore como o assembler faz |
| 📊 Delta de dados EXACT | before/after real do DynamoDB (ADR-003) e delta inferred de SQL — mutações correlacionadas por spanId, fora do pipeline OTel |
| 🔌 Sem agente, sem config | Uma dependência Maven. Nada de -javaagent — compatível com GraalVM Native Image (a razão de existir do produto) |
| 🧩 Domínio-agnóstico | O núcleo não conhece "pedido" nem "cliente": e-commerce, logística, fintech, saúde — qualquer área de negócio funciona sem customização |
| 🛡️ Local-first | Bind 127.0.0.1 por padrão, redaction na origem, token Bearer opcional no ingest, CSP restritivo — SECURITY.md |
| 📡 Dois modos | Embedded (a UI sobe no seu JVM) ou Companion/Station (Lambda, sam local e multi-serviço em UMA árvore via OTLP) |
| 🧪 Testável | Asserções sobre a árvore nos seus testes (trace2local-testing), E2E com LocalStack real no CI |
| 📦 Honestidade por design | Spans perdidos, delta indisponível, cobertura sem agente — tudo declarado na UI, nunca presumido (invariantes I1–I3) |
| Visão geral + execuções | Árvore com waterfall | Delta EXACT | Execução com erro |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
<!-- pom.xml -->
<dependency>
<groupId>tech.neural7.trace2local</groupId>
<artifactId>trace2local-spring-boot-starter</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>@RestController
public class PedidoController {
@PostMapping("/pedidos")
public Pedido criar(@RequestBody NovoPedido request) {
return service.criar(request); // @Trace2Local no serviço = nó BUSINESS na árvore
}
}Suba a app e abra http://localhost:9876/trace2local — escolha POST /pedidos,
clique EXECUTE REQUEST e veja a requisição viajar.
docker run -d --name trace2local-station -p 9876:9876 \
-e TRACE2LOCAL_BIND_ADDRESS=0.0.0.0 -e TRACE2LOCAL_ALLOW_NON_LOOPBACK=true \
-e TRACE2LOCAL_STATION_TOKEN=seu-token trace2local-station:0.1.0public class MinhaFuncao extends Trace2LocalLambdaHandler<Map<String, String>, String> {
@Override
protected String handle(Map<String, String> input, Context ctx) { /* ... */ }
}
// envs da função: TRACE2LOCAL_STATION_ENDPOINT + TRACE2LOCAL_STATION_TOKENO runtime abre o span raiz (nó LAMBDA), correlaciona mutações e faz flush
síncrono no fim da invocação (ADR-002) — a árvore aparece no Station.
| Exemplo | O que demonstra | Como rodar |
|---|---|---|
examples/order-service |
Spring Boot + DynamoDB + SNS/SQS fanout + consumidor (JC-1/2/3) + Native Image | docker compose up --build |
examples/lambda-sqs |
Lambda java21 + DynamoDB + SQS no LocalStack, consumidor na MESMA árvore, token Bearer | ./mvnw -f examples/lambda-sqs/pom.xml -DskipTests package && docker compose -f examples/lambda-sqs/docker-compose.yml up |
O plugin trace2local-maven-plugin faz a configuração automática do projeto
e a engenharia reversa dos recursos que aparecem no canvas — além de
auditar os logs e sugerir/gerar o padrão compatível com Datadog e
OpenTelemetry.
./mvnw tech.neural7.trace2local:trace2local-maven-plugin:0.1.0-SNAPSHOT:analyzeEscaneia o bytecode compilado e gera target/trace2local/:
canvas-map.md— o que será mapeado na UI: endpoints Spring (catálogo + disparo), métodos@Trace2Local(nós BUSINESS), serviços AWS SDK v2 e JDBC;report.md— higiene de logs: usos de SLF4J,System.out,printStackTrace, e sugestões concretas (ex.: "Substitua System.out por SLF4J em X — logs fora do SLF4J não correlacionam com o trace").
./mvnw tech.neural7.trace2local:trace2local-maven-plugin:0.1.0-SNAPSHOT:configureIdempotente (nunca sobrescreve arquivo existente):
| Ação | Resultado |
|---|---|
pom.xml |
adiciona trace2local-bom (import) + trace2local-spring-boot-starter (backup em pom.xml.trace2local.bak) |
src/main/resources/trace2local-business.md |
glossário de negócio para a aba STORY (se ausente) |
src/main/resources/application-trace2local.yml |
config inicial (porta, redaction, retention, delta DynamoDB) |
src/main/resources/logback-spring.xml |
padrão de log com correlação de trace nos DOIS padrões |
O starter injeta no MDC, por requisição, as chaves dos dois ecossistemas:
| Chave | Formato | Quem lê |
|---|---|---|
trace_id / span_id |
hex 128/64 bits | OpenTelemetry (coletor Filelog, OTLP logs) |
dd.trace_id / dd.span_id |
decimal unsigned 64 bits | Datadog (correlação de logs padrão) |
Resultado real (demo payment-service):
INFO PaymentController - trace_id=259c9030880bbf221741f9751ba5189c span_id=87b3151e2ab98bac
dd.trace_id=1675894817728829596 dd.span_id=9778182435261483948
- Pix PIX-LOG2 criado
Os MESMOS logs correlacionam no trace local e em pipelines Datadog/OTel —
adicione logger.info(...) de negócio nos seus serviços (o analyze aponta
onde faltam).
// AWS SDK v2 — delta EXACT do DynamoDB + semântica SNS/SQS
DynamoDbClient ddb = Trace2LocalAws.instrument(DynamoDbClient.builder(), traceVantaConfig).build();
// SQL — semântica + delta inferred (opcional)
DataSource ds = Trace2LocalJdbc.wrap(myDataSource, traceVantaConfig);
// Negócio — um nó BUSINESS por método
@Trace2Local("CriarPedido")
public Pedido criar(NovoPedido r) { /* ... */ }
// Qualquer biblioteca sem library instrumentation — SPI via ServiceLoader (AOT-safe)
public interface Trace2LocalExtension {
default void contribute(NodeBuilder node, SpanView span) {}
default Optional<DataMutation> captureMutation(MutationContext ctx) { return Optional.empty(); }
default RedactionPolicy redactionPolicy() { return RedactionPolicy.INHERIT; }
default List<EndpointDescriptor> discoverEndpoints() { return List.of(); }
default int order() { return 0; }
}flowchart LR
I[Instrumentação<br/>starter · aws · jdbc · lambda · @Trace2Local] -->|SpanStart/End + MutationEvent| B[Ring Buffer 4096<br/>descarte declarado na borda]
B --> A[Assembler · virtual thread<br/>TVEM · invariantes I1-I3]
A --> S[ExecutionStore<br/>acervo LRU]
S --> H[HTTP · REST + SSE 20fps] --> U[UI · canvas + inspector]
- Ponte (
trace2local-otel): umSpanProcessoracrescentado ao pipeline OTel do dev — nunca o substitui. Se você já exporta para o Jaeger, continua exportando. - Ring buffer (ADR-006): fila limitada com
offer(), nuncaput()— sob rajada, eventos são descartados e o descarte é exibido. - Assembler: monta o TVEM com eventos fora de ordem; órfão é reparentado
com aviso (I1);
selfTimenunca negativo (I2); fidelidade do delta declarada (I3). - Delta de dados (ADR-003): canal lateral correlacionado por
spanId— payload sensível nunca entra no pipeline OTel do dev. - UI (ADR-004/005): WebJar offline no próprio JAR, um
EventSourcepor aba, tema escuro, teclado completo, waterfall — nenhum byte sai da sua máquina.
| Embedded (padrão) | Companion / Station | |
|---|---|---|
| Onde roda a UI | No JVM da sua app, :9876 |
Container trace2local-station, :9876 |
| Para | Spring Boot local, docker compose, testes |
Lambda, sam local, multi-serviço em uma árvore |
| Telemetria | SpanProcessor in-process | OTLP/HTTP /v1/traces + /t2lingest/v1/mutations (Bearer opcional) |
| Flush em Lambda | — | Síncrono no fim da invocação (o ambiente congela), teto 200 ms |
Visão completa (regras de dependência, fluxo, SPI): docs/ARQUITETURA.md.
| Módulo | Papel |
|---|---|
trace2local-bom |
BOM: versões do projeto e de terceiros — declare sem versão |
trace2local-core |
TVEM, ring buffer, assembler, redaction, config, SPI — POJO + JDK |
trace2local-otel |
Ponte OTel: SpanProcessor, SemanticMapper (anti-corrupção, ADR-008) |
trace2local-ui |
Assets da UI (WebJar, offline absoluto, zero referência externa) |
trace2local-server |
REST + SSE sobre com.sun.net.httpserver (sem framework) |
trace2local-spring-boot-starter |
Autoconfig Boot, catálogo, launcher, guarda de produção, hints AOT |
trace2local-aws |
Delta DynamoDB (EXACT) + semântica SNS/SQS |
trace2local-jdbc |
Semântica SQL + delta inferred |
trace2local-lambda |
Trace2LocalLambdaHandler com flush síncrono |
trace2local-station |
Station standalone do modo Companion (ingest OTLP + mutações) |
trace2local-testing |
JUnit 5 + asserções sobre a árvore (para os seus testes) |
trace2local-architecture |
Regras ArchUnit que travam a arquitetura no CI |
| Propriedade | Padrão | Nota |
|---|---|---|
enabled |
true em dev |
kill switch: -Dtrace2local.enabled=false desliga tudo |
port |
9876 |
0 = efêmera |
bind-address |
127.0.0.1 |
alterar exige allow-non-loopback=true |
buffer.capacity |
4096 |
eventos; descarte na borda é exibido na UI |
retention.max-executions |
100 |
LRU em memória |
payload.max-bytes |
8192 |
por nó |
redaction.mode |
strict |
strict | keys | off |
aws.dynamodb.capture-before |
true (dev) |
eleva ReturnValues e restaura a resposta (R-01) |
jdbc.mutation-capture |
off |
off | inferred |
station.endpoint |
— | modo Companion |
station.token |
— | Bearer do ingest (env TRACE2LOCAL_STATION_TOKEN) |
flush-timeout-ms |
200 |
Lambda |
Política completa e modelo de ameaças: SECURITY.md.
- Bind loopback por padrão; exposição exige flag explícita + avisos.
- Redaction na origem: chaves sensíveis + padrões de valor (JWT, chaves AWS, cartão com Luhn, CPF/CNPJ, tokens GitHub, hashes bcrypt/argon2…) — mitigação declarada.
- Token Bearer opcional no ingest; hardening HTTP (CSP sem
unsafe-inline,nosniff,no-referrer,no-store); limites de entrada; descarte declarado. - Auditoria de CVEs das versões pinadas: nenhuma afetada (Jackson 2.22.2 e AssertJ 3.27.7 são exatamente as versões corrigidas — não rebaixar).
- Reporte: GitHub Security Advisory ou
[email protected].
| Eixo | Suportado |
|---|---|
| JDK (construir/rodar) | 21+ (CI em 21 e 25; bytecode baseline 21 — ADR-009) |
| Maven | 3.9+ (enforced; wrapper incluído) |
| Spring Boot | 4.0/4.1 |
| OpenTelemetry | SDK 1.66 / instrumentation 2.31 (semconv 1.44) |
| AWS SDK | v2 (DynamoDB/SNS/SQS); Lambda java21/java25 |
| GraalVM | Native Image (JDK 25) |
| LocalStack | 3/4 (validado em 4.2) |
| Navegador (UI) | Chrome/Edge/Firefox modernos (offline absoluto — ADR-005) |
Em 0.x a API pode quebrar entre minors (SemVer a partir do 1.0.0 — ADR-010).
./mvnw install # unidade + propriedade + contrato + ArchUnit
./mvnw -Pit -pl examples/order-service verify # E2E LocalStack real (Docker)
./mvnw -Pit -pl examples/lambda-sqs verify # E2E Lambda+SQS (Docker)| Camada | O que cobre |
|---|---|
| Propriedade | Invariantes I1–I3 do TVEM sob eventos fora de ordem e perdidos (jqwik) |
| Contrato | SemanticMapper por fixture de span — bump do OTel quebra aqui, não na UI |
| Arquitetura | Regras de dependência + nenhum literal OTel fora da ponte + UI sem referência externa |
| Segurança | Corpus de redaction, SSRF do launcher, guarda de produção, token Bearer do ingest |
| E2E | LocalStack real (Testcontainers) + consistência UI↔API nas capturas de tela |
| Documento | Conteúdo |
|---|---|
| SPEC.md | Especificação técnica e arquitetural completa |
| ARQUITETURA.md | Módulos, fluxo de runtime, pontos de extensão |
| docs/adr/ | Decisões de arquitetura registradas (ADR-001…010) |
| SECURITY.md | Modelo de ameaças, limites declarados, reporte |
| CHANGELOG.md | Histórico completo desde o primeiro commit |
| CONTRIBUTING.md | Como contribuir (convenções e definição de pronto) |
| docs/qa/ | Evidências de QA: E2E, UX, consistência, telas |
M0–M6 implementados na v0.1; M5 (prova AOT) no CI; M7 entrega o Station. Visões DAG/Waterfall/Sequence e exportação OTLP entram na v0.2 — detalhes em SPEC §11.1.
- Ferramenta de DEV-TIME — não empacote em produção. O starter se
autodesabilita fora de dev e falha o boot se forçado sem
trace2local.i-know-what-im-doing=true(SPEC §8.4). - Quem tem a máquina, tem a UI. Bind
127.0.0.1, sem autenticação — em loopback, auth seria teatro (ADR-007). Expor além do loopback exige flag explícita e emite WARN; para uso remoto, túnel SSH. - A captura do delta do DynamoDB modifica a sua requisição (eleva
ReturnValuese restaura a resposta — há teste provando a restauração; R-01). Desligue comtrace2local.aws.dynamodb.capture-before=false. - Redaction é mitigação, não garantia. Campo de negócio com nome inocente passa — o limite está declarado, não escondido (SPEC §8.3).
- Cobertura sem agente é limitada — a UI diz "não instrumentado", nunca finge completude (R-02).
Desvios registrados da SPEC (honestidade acima de tudo — detalhes nos ADRs):
| Item | SPEC | v0.1 |
|---|---|---|
UpdateItem before/after |
§4.10: ambos em uma chamada | FECHADO com Trace2LocalAws.instrumentWithReadBack (opcional: before do ALL_OLD + after exato por releitura dentro do span); o padrão instrument mantém after EXACT com before=null declarado na UI (a API do DynamoDB devolve UM conjunto por chamada) |
SSE execution.completed |
§5.2: campos flat (status, duration, metrics) |
FECHADO: {"executionId","status","duration" (ISO-8601),"metrics","execution":{…}} — flat conforme a SPEC, payload completo aninhado como extensão compatível |
trace2local.port=0 |
§5.4: "mesma porta da app" | porta efêmera; GET /api/meta expõe a porta real (descoberta programática); mesmo-que-a-app fica para v0.2 (exige servir a UI junto do DispatcherServlet) |
| Schema por springdoc | §4.8 estratégia 1 | records via RecordComponent (integração springdoc na v0.2 — versão compatível com Boot 4 em auditoria) |
| Catálogo Lambda | §4.8: parse de template.yaml |
catálogo vazio (somente-observação), registrado como gap |
jdbc.mutation-capture=before-image |
§4.10: opt-in com aviso | rejeitado com erro explícito (nunca rebaixado em silêncio) |
ScopedValue |
§4.11: interno para executionId | não usado no núcleo (baseline 21 — ADR-009/D-1; migra quando o baseline subir para 23+) |
Pull requests são bem-vindas! Leia CONTRIBUTING.md e o
Código de Conduta. Decisão superada não é apagada —
ADRs ganham status Substituída por; CHANGELOG desde o primeiro commit;
build reprodutível e assinatura GPG no release.
Trace2Local — See your request travel through the system.
Apache-2.0 © 2026 Neural7 Tech · Especificação · ADRs · Arquitetura · Segurança


