@loongsuite/cms_instrumentations
v1.0.0
Published
## 简介
Downloads
216
Readme
@loongsuite/cms_instrumentations
简介
CMS Instrumentations 提供官方内置的自动埋点插件集合,用于自动拦截和监控 Node.js 应用程序中的各种操作。通过自动埋点,无需修改业务代码即可获得完整的追踪数据。
特性
- 🔌 自动埋点: 无需修改业务代码的自动监控
- 🌐 HTTP/HTTPS 支持: 完整的 HTTP 客户端和服务端监控
- 🗄️ 数据库支持: MySQL、MongoDB 等数据库操作监控
- ⚡ 高性能: 基于 require-in-the-middle 的高效拦截
- 🔧 可配置: 灵活的配置选项和钩子函数
- 📊 丰富属性: 自动添加语义化属性
安装
# 使用 anpm (推荐)
anpm add @loongsuite/cms_instrumentations
# 或使用 npm
npm install @loongsuite/cms_instrumentations支持的插件
HttpInstrumentation
自动监控 Node.js 的 http 和 https 模块,包括客户端请求和服务端响应。
import { HttpInstrumentation } from '@loongsuite/cms_instrumentations';
const httpInstrumentation = new HttpInstrumentation({
enabled: true,
// 请求钩子
requestHook: (span, request) => {
span.setAttributes({
'http.user_agent': request.headers['user-agent'] || 'unknown',
'custom.request_id': request.headers['x-request-id'] || 'unknown'
});
},
// 响应钩子
responseHook: (span, response) => {
span.setAttributes({
'http.status_code': response.statusCode,
'http.response_size': response.headers['content-length'] || 0
});
}
});MySQLInstrumentation
自动监控 MySQL 数据库操作。
import { MySQLInstrumentation } from '@loongsuite/cms_instrumentations';
const mysqlInstrumentation = new MySQLInstrumentation({
enabled: true,
// 查询钩子
queryHook: (span, query) => {
span.setAttributes({
'db.statement': query.sql,
'db.operation': query.type || 'query'
});
}
});MySQL2Instrumentation
自动监控 MySQL2 数据库操作。
import { MySQL2Instrumentation } from '@loongsuite/cms_instrumentations';
const mysql2Instrumentation = new MySQL2Instrumentation({
enabled: true,
// 连接钩子
connectionHook: (span, connection) => {
span.setAttributes({
'db.connection_string': connection.config.host + ':' + connection.config.port,
'db.user': connection.config.user
});
}
});MongoDBInstrumentation
自动监控 MongoDB 数据库操作。
import { MongoDBInstrumentation } from '@loongsuite/cms_instrumentations';
const mongodbInstrumentation = new MongoDBInstrumentation({
enabled: true,
// 操作钩子
operationHook: (span, operation) => {
span.setAttributes({
'db.operation': operation.operation,
'db.collection': operation.collection
});
}
});主要导出
import {
HttpInstrumentation,
MySQLInstrumentation,
MySQL2Instrumentation,
MongoDBInstrumentation,
Instrumentation,
InstrumentationConfig
} from '@loongsuite/cms_instrumentations';使用示例
HTTP 自动埋点
import { HttpInstrumentation } from '@loongsuite/cms_instrumentations';
import { NodeSDK } from '@loongsuite/cms_node_sdk';
// 创建 HTTP 埋点插件
const httpInstrumentation = new HttpInstrumentation({
enabled: true,
requestHook: (span, request) => {
// 添加自定义属性
span.setAttributes({
'http.user_agent': request.headers['user-agent'],
'http.request_id': request.headers['x-request-id'],
'http.client_ip': request.connection?.remoteAddress
});
},
responseHook: (span, response) => {
// 添加响应相关属性
span.setAttributes({
'http.status_code': response.statusCode,
'http.response_time': Date.now() - span.startTime
});
}
});
// 与 NodeSDK 集成
const sdk = new NodeSDK({
serviceName: 'http-service',
instrumentations: [httpInstrumentation]
});
sdk.start();
// 现在所有的 HTTP 请求都会被自动监控
import * as http from 'http';
const server = http.createServer((req, res) => {
// 这个请求会自动创建 span
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World');
});
server.listen(3000);数据库自动埋点
import { MySQLInstrumentation } from '@loongsuite/cms_instrumentations';
import { NodeSDK } from '@loongsuite/cms_node_sdk';
const mysqlInstrumentation = new MySQLInstrumentation({
enabled: true,
queryHook: (span, query) => {
// 添加查询相关属性
span.setAttributes({
'db.statement': query.sql,
'db.operation': query.type,
'db.table': extractTableName(query.sql)
});
}
});
const sdk = new NodeSDK({
serviceName: 'database-service',
instrumentations: [mysqlInstrumentation]
});
sdk.start();
// 现在所有的 MySQL 查询都会被自动监控
import mysql from 'mysql';
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'test'
});
// 这个查询会自动创建 span
connection.query('SELECT * FROM users WHERE id = ?', [1], (error, results) => {
if (error) throw error;
console.log(results);
});多插件配置
import {
HttpInstrumentation,
MySQLInstrumentation,
MongoDBInstrumentation
} from '@loongsuite/cms_instrumentations';
import { NodeSDK } from '@loongsuite/cms_node_sdk';
// 配置多个埋点插件
const instrumentations = [
new HttpInstrumentation({
enabled: true,
requestHook: (span, request) => {
span.setAttributes({
'service.name': 'api-gateway',
'http.method': request.method,
'http.url': request.url
});
}
}),
new MySQLInstrumentation({
enabled: true,
queryHook: (span, query) => {
span.setAttributes({
'db.system': 'mysql',
'db.statement': query.sql
});
}
}),
new MongoDBInstrumentation({
enabled: true,
operationHook: (span, operation) => {
span.setAttributes({
'db.system': 'mongodb',
'db.operation': operation.operation
});
}
})
];
const sdk = new NodeSDK({
serviceName: 'full-stack-service',
instrumentations
});
sdk.start();自定义埋点插件
import { Instrumentation, InstrumentationConfig } from '@loongsuite/cms_instrumentations';
class CustomInstrumentation extends Instrumentation {
constructor(config: InstrumentationConfig = {}) {
super('custom-instrumentation', '1.0.0', config);
}
init() {
// 注册模块拦截
this._registerInstrumentation({
moduleName: 'custom-module',
instrument: this._instrument.bind(this)
});
}
private _instrument(moduleExports: any, moduleName: string) {
// 拦截模块导出
const originalMethod = moduleExports.customMethod;
moduleExports.customMethod = (...args: any[]) => {
const span = this.tracer.startSpan('custom-operation');
try {
const result = originalMethod.apply(this, args);
span.setStatus({ code: 1 }); // SUCCESS
return result;
} catch (error) {
span.setStatus({ code: 2, message: error.message }); // ERROR
throw error;
} finally {
span.end();
}
};
return moduleExports;
}
}
// 使用自定义插件
const customInstrumentation = new CustomInstrumentation();
const sdk = new NodeSDK({
serviceName: 'custom-service',
instrumentations: [customInstrumentation]
});配置选项
HttpInstrumentation 配置
interface HttpInstrumentationConfig {
enabled?: boolean;
requestHook?: (span: Span, request: any) => void;
responseHook?: (span: Span, response: any) => void;
ignoreIncomingRequestHook?: (request: any) => boolean;
ignoreOutgoingRequestHook?: (request: any) => boolean;
}MySQLInstrumentation 配置
interface MySQLInstrumentationConfig {
enabled?: boolean;
queryHook?: (span: Span, query: any) => void;
connectionHook?: (span: Span, connection: any) => void;
}性能考虑
启用/禁用插件
// 根据环境动态配置
const isDevelopment = process.env.NODE_ENV === 'development';
const httpInstrumentation = new HttpInstrumentation({
enabled: isDevelopment, // 开发环境启用,生产环境禁用
requestHook: isDevelopment ? debugHook : undefined
});选择性拦截
const httpInstrumentation = new HttpInstrumentation({
enabled: true,
// 忽略健康检查请求
ignoreIncomingRequestHook: (request) => {
return request.url === '/health' || request.url === '/ping';
},
// 忽略内部服务调用
ignoreOutgoingRequestHook: (request) => {
return request.hostname === 'internal-service';
}
});与 NodeSDK 集成
NodeSDK 默认启用 HttpInstrumentation,可以通过配置自定义:
import { NodeSDK } from '@loongsuite/cms_node_sdk';
import { HttpInstrumentation } from '@loongsuite/cms_instrumentations';
const sdk = new NodeSDK({
serviceName: 'my-service',
instrumentations: [
new HttpInstrumentation({
enabled: true,
requestHook: (span, request) => {
// 自定义请求处理
}
})
]
});
sdk.start();故障排除
常见问题
- 插件未生效: 确保在模块导入前启用插件
- 性能影响: 合理配置钩子函数,避免复杂操作
- 内存泄漏: 确保正确关闭插件
调试技巧
const httpInstrumentation = new HttpInstrumentation({
enabled: true,
requestHook: (span, request) => {
console.log('HTTP Request intercepted:', {
method: request.method,
url: request.url,
spanId: span.spanContext().spanId
});
}
});依赖
@loongsuite/cms_core: 核心类型和接口定义
许可证
MIT License
