|
# Stardust SDK
星尘(Stardust)多è¯è¨€ SDK。所有è¯è¨€å…±ç”¨ä¸€å¥— HTTP 接入契约:**登录认è¯ã€å¿ƒè·³ä¿æ´»ï¼ˆåº”用性能)ã€åŸ‹ç‚¹ç›‘控**ï¼Œè¯¦è§ [APM-17 监控接入 API](/NewLife/Stardust/Blob/master/SDK/../Doc/APM-17-监控接入API.md)。
## 能力矩阵
| è¯è¨€/è¿è¡Œæ—¶ | 目录 | 登录 | 心跳+性能 | 埋点 | é…ç½®ä¸å¿ƒ | 测试 | çŠ¶æ€ |
|-------------|------|:----:|:--------:|:----:|:--------:|:----:|------|
| C#/.NET | [Stardust](/NewLife/Stardust/Blob/master/SDK/../Stardust) | ✅ | ✅ | ✅ | ✅ | ✅ | 已完备 |
| JavaScript(æµè§ˆå™¨ï¼‰ | [JavaScript](/NewLife/Stardust/Blob/master/SDK/JavaScript) | ✅ | ✅ | ✅ | - | ✅ | ✅ |
| JavaScript/Node.js | [JavaScript](/NewLife/Stardust/Blob/master/SDK/JavaScript) | ✅ | ✅ | ✅ | - | ✅ | ✅ |
| Java 8+ | [Java](/NewLife/Stardust/Blob/master/SDK/Java) | ✅ | ✅ | ✅ | 🔧 | ✅ | ✅ |
| Go 1.18+ | [Go](/NewLife/Stardust/Blob/master/SDK/Go) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Python 3.7+ | [Python](/NewLife/Stardust/Blob/master/SDK/Python) | ✅ | 🟡 | ✅ | ✅ | ✅ | 🟡 |
| PHP 7.4+ | [PHP](/NewLife/Stardust/Blob/master/SDK/PHP) | ✅ | 🟡 | ✅ | ✅ | 🟡 | 🟡 |
| Classic ASP | [ASP](/NewLife/Stardust/Blob/master/SDK/ASP) | ✅ | 🟡 | ✅ | - | ⌠| 🟡 |
> ✅ 已实现并测试;🟡 部分实现;🔧 规划ä¸ï¼›âŒ 未开始。
> Python/PHP/ASP 的登录与埋点已å¯ç”¨ï¼Œå¿ƒè·³åº”用性能(`AppInfo`ï¼‰ä¸Žä»¤ç‰Œç»æœŸå°†åœ¨ P1 è¡¥é½ã€‚
### 自动埋点能力
| è¯è¨€/è¿è¡Œæ—¶ | Web å…¥å£ | 出站 HTTP | æ•°æ®åº“ | Redis |
|-------------|:--------:|:---------:|:------:|:-----:|
| JavaScript(æµè§ˆå™¨ï¼‰ | 页é¢/SPA 路由 | fetch/XHR | - | - |
| JavaScript/Node.js | `http.createServer`ã€Express/Koa | `http`/`https`/`fetch` | `pg`ã€`mysql2` | `redis`ã€`ioredis` |
| Java 8+ | Servlet 自动注册 | `StardustHttp` 一行包装 | `StardustJdbc` 一行包装 | `StardustRedis` 通用包装 |
| Go 1.18+ | `WrapHandler` 一行接入 | 默认 Transport 自动ã€`WrapClient` | `WrapDriver` 一行接入 | 通用包装 + å¯é€‰ go-redis Hook |
| Python 3.7+ | WSGI/ASGIã€Flask/Django/Starlette | `requests`ã€`urllib` | DB-API(sqlite3/pymysql/psycopg2) | `redis` |
| PHP 7.4+ | 文档示例 | 文档示例 | 文档示例 | 文档示例 |
| Classic ASP | 文档示例 | 文档示例 | 文档示例 | 文档示例 |
> 自动埋点默认开å¯ï¼šJS/Python 在创建 tracer/client æ—¶å®‰è£…ï¼Œæ— éœ€é¢å¤–调用 `instrument()`ï¼›Go 默认安装 HTTP å®¢æˆ·ç«¯ä¼ è¾“ï¼›Java çš„ Web å…¥å£ç”± Servlet 容器自动注册,Java 的出站 HTTP/JDBC/Redis 与 Go çš„ Web å…¥å£/æ•°æ®åº“按上表“一行接入â€å³å¯ã€‚è·¨æœåŠ¡é“¾è·¯ç»Ÿä¸€ä½¿ç”¨ W3C `traceparent`,Web å…¥å£è§£æžä¸Šæ¸¸ä¸Šä¸‹æ–‡ï¼Œå‡ºç«™ HTTP æ³¨å…¥å½“å‰ Span ä¸Šä¸‹æ–‡ã€‚å…³é—æ–¹å¼ä¸Žå„è¯è¨€é™åˆ¶è§å¯¹åº”è¯è¨€ README。
>
> æµè§ˆå™¨æŽ¨è使用 `loader.js` + `data-stardust-*` ä¸€è¡ŒæŽ¥å…¥ï¼Œæ— éœ€æ‰‹å†™åˆå§‹åŒ–;方案与åŒè¡Œå¯¹æ¯”è§ [APM-18 æµè§ˆå™¨åŸ‹ç‚¹æ–¹æ¡ˆ](/NewLife/Stardust/Blob/master/SDK/../Doc/APM-18-æµè§ˆå™¨åŸ‹ç‚¹æ–¹æ¡ˆ.md)。
## 引用方å¼
| è¯è¨€/è¿è¡Œæ—¶ | å¼•ç”¨æ–¹å¼ |
|-------------|----------|
| C#/.NET ASP.NET Core | `dotnet add package NewLife.Stardust.Extensions`ï¼ˆè‡ªåŠ¨å¸¦æ ¸å¿ƒ `NewLife.Stardust`) |
| C#/.NET 控制å°/Worker | `dotnet add package NewLife.Stardust` |
| JavaScript/Node.js/æµè§ˆå™¨ | `npm install @newlifex/stardust` |
| Java | Maven `com.newlife:stardust`(备选 `io.github.newlifex:stardust`) |
| Go | `go get github.com/NewLifeX/Stardust/SDK/Go/stardust` |
| Python | `pip install newlifex-stardust` |
| PHP | `composer require newlifex/stardust` |
## 快速开始
### JavaScript(æµè§ˆå™¨ï¼Œä¸€è¡ŒæŽ¥å…¥ï¼‰
```html
<script src="https://cdn.jsdelivr.net/npm/@newlifex/stardust/src/loader.js"
data-stardust-server="http://star.example.com:6600"
data-stardust-app="MyWeb"
data-stardust-release="1.2.3"></script>
```
`loader.js` è‡ªåŠ¨åŠ è½½ `browser.js` 并采集:页é¢åŠ è½½ã€SPA 路由ã€JS 错误ã€èµ„æºé”™è¯¯ã€`fetch`/`XMLHttpRequest`;页é¢éšè—/å¸è½½æ—¶é€šè¿‡ `sendBeacon` 冲刷数æ®ã€‚`data-stardust-token` æŒ‡å‘ Token 端点,`data-stardust-token-value` å¯ç›´æŽ¥æ”¾çŸæœŸ Token(é…åˆ `data-stardust-expire` 秒数),`data-stardust-config` 坿Œ‡å‘åŽç«¯é…置端点。`traceparent` é»˜è®¤åªæ³¨å…¥åŒæºè¯·æ±‚ï¼Œè·¨åŸŸç›®æ ‡éœ€é€šè¿‡ `tracePropagationTargets` é…置(loader å¯ç”¨ `data-stardust-trace-targets="https://api.example.com,..."`),é¿å…è§¦å‘ CORS 预检。
需è¦è‡ªå®šä¹‰æ—¶ä»å¯ç›´æŽ¥å¼•用 `browser.js`:
```html
<script src="https://cdn.jsdelivr.net/npm/@newlifex/stardust/src/browser.js"></script>
<script>
const tracer = Stardust.init({
server: 'http://star.example.com:6600',
appId: 'MyWeb',
tokenProvider: async () => (await fetch('/api/stardust-token')).json(),
version: '1.2.3',
});
const span = tracer.newSpan('checkout');
span.setTag('order=123');
span.finish();
</script>
```
### JavaScript(Node.js)
```javascript
const { StardustTracer } = require('@newlifex/stardust');
const tracer = new StardustTracer({
server: 'http://star.example.com:6600',
appId: 'MyNodeApp',
secret: 'MySecret',
version: '1.2.3',
});
await tracer.start();
const span = tracer.newSpan('业务æ“作');
span.setTag('user=123');
span.finish();
```
### Java
```xml
<dependency>
<groupId>com.newlife</groupId>
<artifactId>stardust</artifactId>
<version>1.0.0</version>
</dependency>
```
> å‘布到 Maven Central 时,若 `com.newlife` 命åç©ºé—´æ— æ³•éªŒè¯ï¼Œå¯æ”¹ç”¨ GitHub 命å空间 `io.github.newlifex`。
```java
// 一行接入:创建ã€å¯åŠ¨å¹¶æ³¨å†Œä¸ºé»˜è®¤å®žä¾‹
StardustTracer tracer = StardustTracer.init("http://star.example.com:6600", "MyJavaApp", "MySecret");
try (Span span = tracer.newSpan("业务æ“作")) {
span.setTag("order=123");
doSomething();
}
tracer.stop();
```
è¯¦è§ [Java SDK](/NewLife/Stardust/Blob/master/SDK/Java/README.md)。
### Go
```go
import "github.com/NewLifeX/Stardust/SDK/Go/stardust"
// 一行接入:创建ã€ç™»å½•å¹¶å¯åŠ¨è‡ªåŠ¨åŸ‹ç‚¹
tracer := stardust.Init("http://star.example.com:6600", "MyGoApp", "MySecret")
defer tracer.Stop()
span := tracer.NewSpan("业务æ“作", "")
span.Tag = "order=123"
span.Finish()
```
è¯¦è§ [Go SDK](/NewLife/Stardust/Blob/master/SDK/Go/README.md)。
## 统一接入è¦ç‚¹
| 项目 | 约定 |
|------|------|
| 登录 | `POST /App/Login`,`AppId + Secret + ClientId + Version` |
| 心跳 | `POST /App/Ping?Token=...`,请求体为 `AppInfo`ï¼Œå« CPU/内å˜/å †/线程/GC ç‰æ€§èƒ½å—段 |
| 埋点 | `POST /Trace/Report`,超过 1KB 用 `/Trace/ReportRaw` + GZip |
| `Version` | **å¿…ä¼ **ï¼›æœåŠ¡ç«¯æ®æ¤è¿”回 `Excludes`ã€`EnableMeter` ç‰åЍæ€å‚æ•° |
| 令牌 | åˆ°æœŸå‰ 5 分钟é‡ç™»å½•;心跳å¯ç»ç¾ï¼›`code=401` é‡ç™»å½•å¹¶é‡è¯•一次 |
| æ—¶é—´ | 埋点与 `Info.Time` 为 Unix 毫秒;`Info.StartTime` 为 ISO 8601 å—符串 |
| å“应 | 统一 `{ code, data }`;错误 `{ code, message }`,HTTP 状æ€ç 固定 200 |
## 目录结构
```
SDK/
├── ASP/ # Classic ASP (VBScript)
├── Go/ # Go
├── Java/ # Java 8+ Maven
├── JavaScript/ # æµè§ˆå™¨ + Node.js
├── PHP/ # PHP
└── Python/ # Python
```
## 其它è¯è¨€è·¯çº¿å›¾
| 优先级 | è¯è¨€/è¿è¡Œæ—¶ | 说明 |
|:------:|-------------|------|
| P1 | Pythonã€PHP | è¡¥ `AppInfo` 心跳性能ã€ä»¤ç‰Œç»æœŸã€`Version` 与动æ€é‡‡æ · |
| P2 | Classic ASPã€Rustã€C/C++ | ASP è¡¥æ€§èƒ½å—æ®µï¼›Rust å¯å¤ç”¨ Native Agent 采集能力 |
| P3 | Kotlinã€Rubyã€Swiftã€Dart/Flutterã€Lua/OpenResty | 按商务/社区需求å¯åŠ¨ï¼›Kotlin å¤ç”¨ Java SDK |
## å‘布计划(å„è¯è¨€ä¸å¤®ä»“库)
| ç”Ÿæ€ | 仓库 | å»ºè®®åæ ‡/åç§° | 说明 |
|------|------|---------------|------|
| NuGet | nuget.org | `NewLife.Stardust`ï¼ˆæ ¸å¿ƒï¼‰/ `NewLife.Stardust.Extensions`(ASP.NET Coreï¼Œå«æ ¸å¿ƒï¼‰ | ASP.NET Core 应用åªéœ€å¼•用 `NewLife.Stardust.Extensions` |
| npm | npmjs.com | `@newlifex/stardust` | `newlife` 已被å 用,统一用 `newlifex` |
| Maven Central | central.sonatype.com | `com.newlife:stardust`(备选 `io.github.newlifex:stardust`) | ä¼˜å…ˆéªŒè¯ `newlife.com`ï¼›æ— åŸŸåæ—¶ç”¨ GitHub 命å空间;需 GPG ç¾å |
| Go | pkg.go.dev / GitHub | `github.com/NewLifeX/Stardust/SDK/Go/stardust` | æ— ä¸å¤®æ³¨å†Œï¼Œæ‰“忍¡å—æ ‡ç¾å³å¯ |
| crates.io | crates.io | `newlifex-stardust`(`stardust` 已被å 用) | Rust SDK å¯åŠ¨æ—¶æ³¨å†Œ |
| PyPI | pypi.org | `newlifex-stardust` | `stardust`/`stardust-sdk` 已被å 用 |
| Packagist | packagist.org | `newlifex/stardust` | Composer 包åå¯ç”¨ |
> å‘布需è¦å„仓库维护者账å·ã€2FA/Tokenã€GPG 密钥与 CI 凿®ï¼›ä»£ç 完æˆä¸ç‰äºŽè‡ªåЍå‘布,æ£å¼å‘版å‰éœ€å…ˆåš `--dry-run`/Staging 验è¯ã€‚
## 贡献
欢迎为其它è¯è¨€è´¡çŒ® SDK。请先阅读 [APM-17 监控接入 API](/NewLife/Stardust/Blob/master/SDK/../Doc/APM-17-监控接入API.md),并确ä¿ç™»å½•ã€å¿ƒè·³æ€§èƒ½ã€åŸ‹ç‚¹ä¸‰é¡¹èƒ½åŠ›ä¸Žç»Ÿä¸€å¥‘çº¦ä¸€è‡´ï¼›æ–°å¢žè¯è¨€è¯·åŒæ¥æ›´æ–°æœ¬æ–‡ä»¶çš„能力矩阵与路线图。
## License
MIT License
|