makoto-developer/strata

GitHub: makoto-developer/strata

Strata 是一款面向多语言微服务的静态依赖与函数级调用图可视化工具,在 CI 中自动检测循环依赖和架构层次违规。

Stars: 1 | Forks: 0

# Strata [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/makoto-developer/strata/actions/workflows/ci.yml) [![文档](https://img.shields.io/badge/📖_ドキュメント-makoto--developer.github.io%2Fstrata-0a7368)](https://makoto-developer.github.io/strata/) [![License](https://img.shields.io/badge/license-AGPL--3.0--only-blue)](LICENSE) [![Release](https://img.shields.io/github/v/release/makoto-developer/strata?label=release)](https://github.com/makoto-developer/strata/releases/latest) **一款用于将微服务代码作为“层”来阅读的依赖与调用图可视化工具。** 支持跨越 gRPC、REST、GraphQL,在函数级别追踪处理流程。 ``` strata serve ./my-monorepo # ブラウザで構造・API・アーキ図を見る strata check ./my-monorepo # CI で循環依存・レイヤー違反を検査する ``` ## 您是否遇到过这样的情况 微服务在运维几年后,通常会陷入以下状态: - **没人能立即回答“这个处理流程经过哪里?”。** 仓库分散,语言不一, 没有人掌握全局。虽然有规范文档,但无法保证与代码完全一致 - **即使查看 proto 也无法知道“谁在调用它”。** 即使能读懂 RPC 的定义, 调用方却在其他的仓库、其他的语言中。即使使用 grep 也搜不到 - **无法断言“这个 API 已经没被使用了”。** 因此无法删除。 因为无法删除,没用的代码就永远残留了下来 - **REST、GraphQL、gRPC 混杂在一起,追踪在协议边界处中断** - **架构无法在代码审查中得到保障。** 诸如“domain 层不应依赖 infra 层”的约定, 在差异审查中是无法检测出来的,所以会逐渐被破坏 ## Strata 所做的事 **无需启动服务,也无需引入链路追踪基础设施,仅靠静态分析**就能填补这 5 个空白。 | 痛点 | Strata 的答案 | | --- | --- | | 不知道流程经过了哪里 | 将 `⚡RPC → 实现handler → 函数 → 下一个服务` **作为函数级别的一条流程显示** | | 不知道谁在调用 | 通过 proto 的 RPC 名、HTTP 路径、GraphQL 字段**反向查找调用方** | | 没用的 API 无法删除 | 为零调用方的 API 标注 **“疑似未使用?”“仅测试”徽章**。作为代码清理的依据 | | 追踪在协议边界处中断 | 将 gRPC / REST / GraphQL / webhook **放在同一个图表中** | | 无法维护架构 | 在 **CI 中检查**循环依赖、层次违规、禁止依赖规则(违规则 exit 1) | ## Strata 的特点 我们将降低引入门槛的优先级置于功能之上。 - 🔒 **完全本地化、零传输。** 没有遥测,也没有自动更新检查。 由于根本不存在对外通信的代码,**绝不会将公司内部代码外泄** (服务器仅绑定到 `127.0.0.1`) - 📦 **运行时依赖为零。** 不生成 `node_modules`。供应链的审查对象 “仅限这个仓库”即可 - ⚡ **速度快。** 实测 **1,050 个文件 / 1,644 个节点的 monorepo 只需 0.26 秒**即可解析 (Apple M 系列,无缓存)。因为没有等待时间,可以随时轻松运行多次 - 🪶 **轻量。** 本体代码仅 **约 530KB**(`src` + `web`)。 二进制版本包含 Node.js 为 37MB(压缩后) - 🔧 **无需语言的工具链。** 即使在没有安装 Go 或 Python 的机器上, 也能解析 Go 或 Python 的代码(基于文本和语法级别的解析) - 🧱 **无需构建。** `git clone` 后执行 `node src/cli.ts serve .` 即可运行 - 🌐 **离线可用。** 在无网络环境或内网中也能直接使用 - 📤 **可共享分析结果。** 通过 `strata export` 生成 **一个自包含的 HTML 文件**。 无需服务器,扔到 Slack 里对方就能直接在浏览器中打开 ## 与现有方案的差异 | 方案 | 局限性 | Strata | | --- | --- | --- | | 手绘架构图 | 画完的瞬间就会与实现产生偏差。无法确认依据 | **从代码生成**。点击方框即可深入到函数和代码行 | | IDE 的“查找引用” | 只能停留在单一仓库、单一语言内部。无法跨越 RPC 边界 | 通过 proto / 路径 / GraphQL 字段**跨越服务边界** | | 分布式追踪(如 OpenTelemetry 等) | 只能看到实际发生过的调用路径。**无法了解未触发的路径**。引入成本也很高 | 基于静态分析,**即使不运行也能看到所有路径**。引入只需 clone | | 现有的依赖可视化工具 | 大多只针对单一语言。往往停留在文件/模块级别 | **跨语言 + 函数级别**。将 gRPC / REST / GraphQL 放在同一个图表中 | **不依赖 IDE。** 详细规范请参阅 [docs/SPEC.md](docs/SPEC.md),关于设计意图请参考 [为什么是这样的形态](https://makoto-developer.github.io/strata/why/)。 ![Strata Viewer Demo](https://static.pigsec.cn/wp-content/uploads/repos/cas/06/0609f2b8fa00bc9f724815319bde7f95717f925082a7a378f37a3dd3c02d4667.gif) ## 界面导览(能做什么) 每个选项卡都对应着“想要解答的问题”。图片会自动适应深色/浅色显示主题。 ### 🗺 结构 — “这个依赖的方向正确吗?” 以树状结构和连线显示依赖关系。**向上的线(玫瑰色) = 层次违规**,虚线 = 跨越服务边界。 鼠标悬停在某行上时,仅保留与该行相连的线,进行层次化后会按层(地层)显示色带。 構造タブ: ツリーと依存線、レイヤー違反の強調 ### ⚡ API — “谁在调用这个 API?” 将 gRPC 的 RPC、HTTP endpoint、GraphQL 字段汇总为一个目录。选中后 会显示**调用方(上游)以及从实现出发的下游流程**,点击函数即可在对应代码行打开源码。 通过“疑似未使用?”“无实现”“仅测试”等徽章,一目了然地看出哪些 API 可以删除、哪些尚未实现。 API タブ: RPC カタログ、上流・下流フロー、ソース表示 ### 🧭 图 — “想向他人说明服务构成” 以服务为单位的方框和箭头。包含每个层级的色带、边界的调用数(⚡RPC / ⇄HTTP / ◈GraphQL 的明细), 甚至外部系统(虚线方框)都可以一览无余。点击方框会显示依赖源、依赖目标以及公开的 API。 図タブ: サービス単位のアーキテクチャ図とレイヤー帯 ### 🚪 Entry Point — “应该从哪里开始阅读?” 罗列了 `func main`、页面(LiveView)、操作事件。点击后会在结构视图中聚焦到该位置, 开始下游的追踪。这是新加入团队的成员首选打开的选项卡。 エントリーポイントタブ: main や画面の一覧 ### 📁 项目 — “想将多个仓库汇总查看” 添加、编辑、切换加载的仓库。如果设置为**捆绑多个仓库的复合项目**, 即使在 monorepo 架构下,gRPC / HTTP 的服务间连接也能跨仓库进行解析。 プロジェクトタブ: リポジトリの追加・編集・切り替え ``` graph LR gateway["gateway"] -->|"3"| user["user-service"] gateway -->|"2"| order["order-service"] order -->|"3"| user federation -.->|"RPC"| user web -.->|"RPC"| proto["proto"] classDef unstable fill:#fde,stroke:#d46; class gateway,federation unstable ``` 📖 **[说明书(文档站点)](https://makoto-developer.github.io/strata/)** ・ ❓ **[提问请到 GitHub Issue](https://github.com/makoto-developer/strata/issues/new?template=3_question.yml)** ・ 🧪 **[示例系统](https://github.com/makoto-developer/strata-sample-platform)** ## 目录 - [您是否遇到过这样的情况](#こんなことになっていませんか) - [Strata 所做的事](#strata-がやること) - [Strata 的特点](#strata-の性格) - [与现有方案的差异](#既存のやり方との違い) - [界面导览(能做什么)](#画面ツアー何ができるか) - [支持的语言](#対応言語) - [安装说明](#インストール) - [快速入门](#クイックスタート) - [可实现的功能(功能一览)](#できること機能一覧) - [命令参考](#コマンドリファレンス) - [配置 `strata.config.json`](#設定-strataconfigjson) - [CI 集成](#ci-連携) - [使用 Viewer](#ビューアの使い方) - [解析机制与局限](#解析の仕組みと限界) - [使用的技术与致谢](#使っているもの謝辞) - [License](#ライセンス) ## 支持的语言 **Go / TypeScript / JavaScript / Python / Elixir / Protocol Buffers(gRPC)**。 **无需** Go/Python 等的工具链(基于文本和语法级别的静态分析)。 ## 环境要求 - Node.js **22.18 以上**(为了直接运行 TypeScript。外部依赖为零,无需构建) - 作为解析对象的仓库 ## 安装说明 仅在 **GitHub 上发布**(未发布至 npm)。 ### macOS(Apple Silicon) 二进制 无需安装 Node.js。这是包含了 runtime 的单一可执行文件。 ``` curl -fsSL https://github.com/makoto-developer/strata/releases/latest/download/strata-macos-arm64.tar.gz | tar xz sudo mv strata /usr/local/bin/ strata --version ``` | 项目 | 支持 | | --- | --- | | OS | **macOS 13 Ventura 及以上** | | CPU | **Apple Silicon(M1 / M2 / M3 / M4 …)**。不提供 Intel Mac 版本 | | 内置 Runtime | Node.js v24.18.0 | 仅有 ad-hoc 签名(未经 Apple 公证)。如果通过浏览器下载, 请使用 `xattr -d com.apple.quarantine ./strata` 命令移除隔离属性。 在 Intel Mac / Linux / Windows 上请使用下文的 git clone 版本(功能相同)。 ### Homebrew ``` brew tap makoto-developer/strata brew trust makoto-developer/strata # 公式以外の tap は明示的な信頼が必要(Homebrew の仕様) brew install strata strata --version strata serve /path/to/your-monorepo ``` ### mise / asdf(准备 Node 后通过 git 引入) ``` mise use -g node@22.18 # asdf の場合: asdf install nodejs 22.18.0 git clone https://github.com/makoto-developer/strata.git cd strata && npm link # `strata` コマンドが使えるようになる strata serve /path/to/your-monorepo ``` ### 仅 git clone(无需安装) ``` git clone https://github.com/makoto-developer/strata.git node strata/src/cli.ts serve /path/to/your-monorepo ``` ## 快速入门 ``` # ① ビューアを起動(ブラウザで http://localhost:7333/。--watch で変更を自動反映) strata serve /path/to/your-monorepo --watch # ② コールツリーを端末で(--up で呼び出し元をたどる) strata trace /path/to/your-monorepo 'Gateway.handleUser' # ③ 循環依存 + アーキテクチャルールを CI で検査(問題があれば exit 1) strata check /path/to/your-monorepo # ④ サービス結合度メトリクス strata metrics /path/to/your-monorepo ``` ### 首先尝试(内置 Demo) ``` strata serve examples/demo strata trace examples/demo 'Gateway.handleUser' strata check examples/demo # 意図的に仕込んだ循環 2 件で exit 1 strata metrics examples/demo ``` `strata metrics examples/demo` 的输出示例: ``` service Ca Ce I loc api ──────────────────────────────────────────────────── proto 5 0 0.00 57 6 user-service 3 1 0.25 117 0 gateway 0 3 1.00 83 0 order-service 1 2 0.67 51 0 ``` `Ca`=被依赖数, `Ce`=依赖数, `I`=不稳定度 `Ce/(Ca+Ce)`。 I 值越高表示“依赖越多,越容易受到变更影响”,越低表示“被依赖越多,变更影响范围越广”。 ## 可实现的功能(功能一览) ### 🗺 可视化与探索(Viewer) - **结构视图**:地铁线路图风格的连线 + 层次化 + 地层(strata)色带。 “向上依赖 = 层次违规”“循环依赖”一目了然 - **API 选项卡**:将 gRPC(proto / service / RPC)、⇄HTTP endpoint、◈GraphQL 字段 汇总为一个目录显示 + 流程显示。 可跨越服务边界追踪 `⚡RPC → 实现handler → 函数 → ⚡其他服务的 RPC` - **图选项卡**:以服务为单位的架构图。可将依赖**展开至函数级别** - **Entry Point 选项卡**:列出进程启动点(main)、页面(LiveView)、操作事件 - **源码显示**:语法高亮、定义跳转、悬停预览、git blame / commit / PR - **⭐ 书签**:在关注的节点上做标记,可从列表快速跳转(`b` 键) - **键盘操作**:`↑↓←→` 移动、展开,`/` 搜索,`b` 书签,`Esc` 关闭,`Alt+←→` 后退/前进(`?` 查看列表) - **URL 共享**:focus / 搜索 / 排序会反映在 URL 中,可重新加载恢复或共享 - **watch**:通过 `serve --watch` 在文件更改时自动重新加载浏览器 ### 🔬 解析 - **多语言**:跨语言解析 Go / TS / JS / Python / Elixir / proto / GraphQL SDL - **gRPC 服务边界**:将 proto 作为“标准”,连接 `客户端函数 → ⚡RPC → 服务端实现` - **⇄ HTTP / REST**:检测 gin / echo / chi / gorilla mux / net-http(包括 Go 1.22 的 `"GET /path"`)/ Express / Fastify / Hono / Next.js App Router / FastAPI / Flask / Phoenix Router 的路由, 并与 `fetch` / `axios` / `http.NewRequest` / `requests` 等调用及其路径进行匹配连接 - **🪝 webhook**:将 `/webhooks/...` 的接收端和对外部 SaaS 的发送作为“外部系统”分别进行可视化 - **◈ GraphQL**:将 SDL 中的 Query / Mutation / Subscription 节点化,并连接 resolver 实现(gqlgen / Apollo)、 客户端的 `gql\`query\`` 操作、基于 federation 的 `extend type @key` 的子图间引用 - **循环依赖检测**(Tarjan SCC) / **层次违规**可视化 - **🛡 gRPC Interceptor 检测**:检测授权等横切中间件,并显示在服务/流程中 - **⚙ 配置接口**:检测各个服务所需的环境变量 - **✉ 异步(Pub/Sub)**:通过 `messaging` 配置,将 publish/subscribe 作为基于 topic 的依赖进行可视化 ### 🛡 治理与 CI - **架构规则检查**:声明禁止依赖并在 CI 中 fail(`check`) - **SARIF 输出**:将循环及规则违规作为注释标注在 GitHub Code Scanning 中(`check --sarif`) - **循环基线**:已知的循环,仅对新增循环 fail(`check --baseline`) - **差异分析**:比较 2 个 git ref,检测依赖的增减、新增/解决的循环(`diff`) ### 📤 输出 - **自包含 HTML** 导出(`export`) / **mermaid + Markdown 报告**(`report`) - **耦合度指标**(`metrics`) ## 命令参考 | 命令 | 说明 | | --- | --- | | `strata serve [dir\|model.json] [--port N] [--watch]` | 启动 viewer(默认 7333) | | `strata scan [dir] [-o model.json]` | 输出依赖模型(JSON) | | `strata check [dir\|model.json] [--json] [--baseline F] [--update-baseline] [--sarif -o f]` | 循环 + 规则检查(exit 1) | | `strata metrics [dir\|model.json] [--json]` | 服务耦合度(Ca/Ce/不稳定度) | | `strata diff [--json]` | 2 个模型的差异(依赖增减・循环) | | `strata trace [dir\|model.json] <函数名/ID> [--up] [--depth N]` | 显示调用树 | | `strata report [dir\|model.json] [-o report.md]` | mermaid + 指标 + Markdown | | `strata export [dir\|model.json] [-o report.html]` | 自包含 HTML | | `strata init [dir] [--force]` | 生成 `strata.config.json` 骨架 | ## 配置 `strata.config.json` 放置在 workspace 的根目录下(全为可选)。 ``` { "name": "my-platform", "services": [ // サービスのグルーピング(表示上の最上位階層) { "name": "gateway", "path": "gateway" }, { "name": "user-service", "path": "services/user" } ], "exclude": ["experimental"], // 除外(パス前方一致 or ディレクトリ名) "includeTests": false, // テストコードをグラフに含めるか(既定: false) "testPaths": ["tools/test-client"], // テスト扱いにする追加パス // アーキテクチャルール: 禁止依存(check で違反すると exit 1) "forbidden": [ { "name": "domain-no-infra", "from": "**/domain", "to": "**/infra", "comment": "ドメイン層はインフラを参照しない" }, { "name": "handler-no-repo", "from": "**/handler", "to": "**/repository", "comment": "ハンドラは repository を直接触らずユースケース経由にする" } ], // 数値しきい値: 超えると check が exit 1(結合度・循環の fitness function) "thresholds": { "maxCycles": 0, // 循環グループ数の上限 "maxInstability": 0.85, // 各サービスの不安定度 I の上限 "maxEfferent": 8 // 各サービスが依存する数(Ce)の上限 }, // 非同期(Pub/Sub)検出: 発行/購読メソッド名を指定(opt-in・既定は無効) "messaging": { "publish": ["Publish", "Emit"], "subscribe": ["Subscribe", "On"] }, // HTTP(REST / webhook)検出。既定は有効 "http": { "enabled": true, "externalHosts": true, // 未解決の絶対 URL を「外部システム」ノードにする "webhookPatterns": ["/callbacks/"] // webhook 扱いにするパスの追加パターン }, // GraphQL 検出。既定は有効 "graphql": { "enabled": true } } ``` - `forbidden` 的 `from`/`to` 是针对节点 id、标签的**glob**(`**/` 表示 0 层及以上的层级,`*` 表示 1 层)。 由于会与边端点及其祖先进行匹配,因此以包为单位的规则同样对函数级别的边有效。 不包含 glob 的模式将以**路径片段(segment)**为单位进行匹配(`web` 会匹配 `web/src/...`, 但不会匹配类似 `webhook-in` 的子字符串)。 - 如果配置了 `messaging`,将检测类似 `bus.Publish("order.created", …)` 的调用, 并生成 `publisher → ✉topic → subscriber` 的事件边。 ## CI 集成 ### 循环 + 架构规则(GitHub Actions) ``` - uses: actions/setup-node@v4 with: { node-version: 22 } - run: git clone --depth 1 https://github.com/makoto-developer/strata.git - name: アーキテクチャ検査 run: node strata/src/cli.ts check . ``` ### GitHub Code Scanning(通过 SARIF 在 PR 中标注) ``` - name: Strata 検査(SARIF) run: node strata/src/cli.ts check . --sarif -o strata.sarif || true - uses: github/codeql-action/upload-sarif@v3 with: { sarif_file: strata.sarif } ``` ### 仅针对差异中的新增循环 fail ``` # 在 base branch 和 topic branch 上分别执行 scan → diff node strata/src/cli.ts scan base/ -o base.json node strata/src/cli.ts scan . -o head.json node strata/src/cli.ts diff base.json head.json # 新規循環があれば exit 1 ``` ## 使用 Viewer - **1 行 = 1 个元素**(S=服务 / M=模块 / P=包 / ⬢ proto / ƒ 函数 / ⚡ RPC / ✉ topic)。 ▸/▾ 展开与折叠 - 依赖关系通过**左侧通道的地铁线路图**显示。▶ 的前端为依赖目标,**灰色=向下(正常)/玫瑰色=向上(层次违规)**。 **虚线=RPC / proto / 事件边界**,粗细=依赖数,**红色背景=循环** - 点击行即可**focus**(绿色=依赖目标, 蓝色=依赖源)。选中函数/RPC 即显示**调用树** - **⭐ 书签**:通过行首的 ☆ 或 `b` 键注册,可从顶部导航栏的“★ n”查看列表并跳转 - **键盘**:`↑↓` 移动 / `→←` 展开・折叠 / `Enter` 开闭 / `/` 搜索 / `Esc` 关闭 / `Alt+←→` 后退・前进 - 选中服务后,将显示依赖目标/依赖源、公开 API 的使用情况、**🛡 Interceptor** 以及 **⚙ 环境变量**。 依赖关系可**展开至函数级别**,点击各个函数即可跳转 ### 项目管理 在“项目”选项卡中注册并切换多个仓库(`~/.config/strata/projects.json`)。 通过**复合项目**,可以将多个仓库作为一个依赖图进行解析。 ## 解析机制与局限 - 基于文本和语法级别的静态分析(无类型推断)。采取**宁可遗漏也不误报**的方针, 确保图表中出现的依赖全都是真实存在的 - 服务间连接以 proto 为“标准”,通过匹配 `go_package` / 生成的 stub / RPC 名进行连接 - 不追踪跨越 interface 的调用、高阶函数及反射。 经由消息队列的依赖通过 `messaging` 配置进行检测(未配置则不作处理) - 详情及各语言的支持范围请参阅:[docs/SPEC.md](docs/SPEC.md) ## 开发 ``` npm test # CLI・解析エンジン + ビューア/サーバの DOM/HTTP スモーク npm run typecheck # tsc --noEmit(strict) ``` ### 关于构思 “将依赖关系视为层(strata),并将层次违规可视化”这一理念, 是基于架构可视化工具的一般思路。代码、图标、文案均为本项目的原创,未借用任何其他工具的内容。 ## License 基于 **AGPL-3.0-only** 提供([LICENSE](LICENSE))。Copyright (c) 2026 makoto-developer. - 如果仅仅是作为工具使用(运行),无论是个人还是企业均可免费自由使用 - 若要分发修改版,或提供内置了本工具的服务,则有义务公开源代码。 若需要其他条件(如商业 license 等),请与作者协商 - 贡献的条件请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 本工具为完全的独立实现(未借用任何其他产品的代码或资产)。 分发物中包含的第三方代码声明: - **macOS 版二进制文件**中附带了 Node.js(MIT)。License 全文请见 压缩包内的 `THIRD-PARTY-NOTICES.txt` - 源码分发物中不包含第三方代码(运行时依赖为零)。用于开发和构建的 OSS 请参阅 [使用的技术与致谢](#使っているもの謝辞) 有关问题或 Bug 的反馈渠道,请参阅 [SUPPORT.md](SUPPORT.md)。
标签:MITM代理, Python工具, WebSocket, 代码可视化, 依赖分析, 自定义脚本, 调用图