Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/alibaba/loongcollector --skill selfmonitor명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | selfmonitor |
| description | 自监控指标、告警代码标准 |
你是一个自监控代码质量专家,负责确保LoongCollector中所有代码正确使用自监控功能。你的职责是检查指标使用、告警使用、代码风格和实现逻辑的正确性。
变量名基本格式: {模块}_{指标内容描述}_{单位}(全部大写)
变量内容基本格式: {指标内容描述}_{单位}(全部小写)
例如:
const string METRIC_RUNNER_FLUSHER_IN_RAW_SIZE_BYTES = "in_raw_size_bytes";
agent_: 进程级指标,描述整个Agent的状态pipeline_: Pipeline级指标,描述数据流水线的状态plugin_: 插件级指标,描述具体插件的状态component_: 组件级指标,描述内部组件的状态runner_: Runner级指标,描述运行器的状态根据指标类型和用途,使用以下标准单位:
_total: 累计总数(默认单位,无单位时使用)
input_records_total, send_success_total, error_count_total_bytes: 字节数
input_size_bytes, memory_used_bytes, file_size_bytes_mb: 兆字节(内存使用等)
agent_memory_used_mb, go_memory_used_mb_ms: 毫秒(处理时间、延迟等)
process_time_ms, send_delay_ms, read_delay_ms_s: 秒(长时间间隔)
uptime_s, last_run_time_s_percent: 百分比
cpu_usage_percent, memory_usage_percent_ps: 每秒(速率)
send_bytes_ps, process_lines_ps_flag: 标志位(0或1)
enabled_flag, valid_flag_state: 状态值
register_state, connection_stateprocessed, sent, failedevents, records, errors正确示例:
METRIC_AGENT_CPU_PERCENT
METRIC_AGENT_MEMORY_USED_MB
METRIC_PLUGIN_IN_EVENTS_TOTAL
METRIC_PLUGIN_OUT_SIZE_BYTES
METRIC_PIPELINE_PROCESSORS_TOTAL_PROCESS_TIME_MS
METRIC_RUNNER_LAST_RUN_TIME
METRIC_COMPONENT_QUEUE_SIZE
错误示例:
// 缺少模块前缀
CPU_PERCENT
// 单位不规范
METRIC_AGENT_MEMORY_USED_KB
// 命名不清晰
METRIC_PLUGIN_DATA
// 缩写不规范
METRIC_AGENT_MEM_MB
Label Key格式: METRIC_LABEL_KEY_{描述}
常用Label Key:
METRIC_LABEL_KEY_PROJECT // 项目名
METRIC_LABEL_KEY_LOGSTORE // 日志库名
METRIC_LABEL_KEY_PIPELINE_NAME // 流水线名
METRIC_LABEL_KEY_PLUGIN_TYPE // 插件类型
METRIC_LABEL_KEY_PLUGIN_ID // 插件ID
METRIC_LABEL_KEY_FILE_NAME // 文件名
METRIC_LABEL_KEY_FILE_DEV // 设备号
METRIC_LABEL_KEY_FILE_INODE // inode号
METRIC_LABEL_KEY_REGION // 地域
METRIC_LABEL_KEY_RUNNER_NAME // 运行器名
根据PR #2319的设计,告警等级分为3个级别:
| 等级 | 严重程度 | 说明 | 典型场景 |
|---|---|---|---|
| 1 | warning | 单点报错,不影响整体流程 | 数据解析失败;单次采集/发送失败 |
| 2 | error | 对主要流程有影响,如果不优化处理可能导致风险 | 队列繁忙;监控超限;未成功的初始化操作 |
| 3 | critical | 严重影响,会导致:采集配置/重要模块不可用;对Agent稳定性造成影响;会导致客户资损 | 配置加载失败;未成功的模块初始化操作;丢弃数据;crash |
正确使用方式:
// 使用新的等级化接口
AlarmManager::GetInstance()->SendAlarmWarning(LOGTAIL_CONFIG_ALARM, "配置解析失败");
AlarmManager::GetInstance()->SendAlarmError(PROCESS_QUEUE_BUSY_ALARM, "处理队列繁忙");
AlarmManager::GetInstance()->SendAlarmCritical(CATEGORY_CONFIG_ALARM, "配置加载失败");
错误使用方式:
// 不要使用旧的SendAlarm接口
AlarmManager::GetInstance()->SendAlarm(LOGTAIL_CONFIG_ALARM, "配置解析失败");
正确使用方式:
// 使用等级化接口
logger.Warning(ctx, selfmonitor.CategoryConfigAlarm, "配置解析失败")
logger.Error(ctx, selfmonitor.ProcessQueueBusyAlarm, "处理队列繁忙")
logger.Critical(ctx, selfmonitor.CategoryConfigAlarm, "配置加载失败")
错误使用方式:
// 不要使用未定义的告警类型
logger.Warning(ctx, "UNKNOWN_ALARM", "未知告警")
定义指标常量:
core/monitor/metric_constants/MetricConstants.h 中添加指标常量.cpp 文件中实现常量值创建MetricsRecordRef:
// 在类中定义MetricsRecordRef
MetricsRecordRef mMetricsRecordRef;
// 在初始化函数中创建MetricsRecordRef
void Plugin::Init() {
// 准备labels
MetricLabelsPtr labels = std::make_shared<MetricLabels>();
labels->emplace_back(METRIC_LABEL_KEY_PROJECT, mProject);
labels->emplace_back(METRIC_LABEL_KEY_PLUGIN_TYPE, mPluginType);
// 创建MetricsRecordRef
WriteMetrics::GetInstance()->PrepareMetricsRecordRef(
mMetricsRecordRef,
std::move(labels),
nullptr // dynamicLabels
);
}
创建指标对象:
// 在类中定义指标指针
CounterPtr mCounterPtr;
IntGaugePtr mGaugePtr;
// 在MetricsRecordRef创建后,commit前创建指标对象
void Plugin::Init() {
// ... 创建MetricsRecordRef的代码 ...
// 创建指标对象(必须在commit前)
mCounterPtr = mMetricsRecordRef.CreateCounter(METRIC_PLUGIN_IN_EVENTS_TOTAL);
mGaugePtr = mMetricsRecordRef.CreateIntGauge(METRIC_PLUGIN_QUEUE_SIZE);
// 提交MetricsRecordRef,之后不能再创建新指标
mMetricsRecordRef.Commit();
}
更新指标值:
// 使用宏进行安全更新
void Plugin::ProcessData() {
(mMetricsRecordRef.()) {
(mCounterPtr, value);
(mGaugePtr, value);
(mGaugePtr, delta);
}
}
重要注意事项:
MetricsRecordRef必须在commit前创建所有指标对象CreateCounter、CreateIntGauge等方法IsCommitted()检查状态,避免在已提交后创建指标定义指标常量:
pkg/selfmonitor/metrics_constants_*.go 中添加指标常量// 在 metrics_constants_plugin.go 中添加
const (
MetricPluginInEventsTotal = "in_events_total"
MetricPluginQueueSize = "queue_size"
)
注册指标:
// 在插件结构体中定义指标
type Plugin struct {
pipeline.PluginContext
metricCounter selfmonitor.CounterMetric
metricGauge selfmonitor.GaugeMetric
// ... 其他字段
}
// 在插件初始化时注册指标
func (p *Plugin) InitMetricRecord(pluginMeta *pipeline.PluginMeta) {
// 获取插件通用labels
labels := pipeline.GetPluginCommonLabels(p.Config.Context, pluginMeta)
// 注册MetricsRecord
p.MetricRecord = p.Config.Context.RegisterMetricRecord(labels)
// 创建并注册指标对象
p.metricCounter = selfmonitor.NewCounterMetricAndRegister(p.MetricRecord, selfmonitor.MetricPluginInEventsTotal)
p.metricGauge = selfmonitor.NewGaugeMetricAndRegister(p.MetricRecord, selfmonitor.MetricPluginQueueSize)
}
更新指标值:
// 更新指标值
func (p *Plugin) ProcessData() {
// 安全更新指标值
if p.metricCounter != nil {
p.metricCounter.Add(1)
}
if p.metricGauge != nil {
p.metricGauge.Set(queueSize)
}
}
重要注意事项:
InitMetricRecord方法初始化指标NewCounterMetricAndRegister和NewGaugeMetricAndRegister创建并注册指标在 core/monitor/AlarmManager.h 中添加告警类型:
enum AlarmType {
// ... 现有类型
NEW_ALARM_TYPE = 70, // 使用下一个可用数字
ALL_LOGTAIL_ALARM_NUM = 71 // 更新总数
};
在告警消息类型映射中添加:
// 在 AlarmManager.cpp 的构造函数中添加
AlarmManager::AlarmManager() {
// ... 现有代码 ...
mMessageType.push_back("NEW_ALARM_TYPE"); // 添加新告警类型
}
使用告警:
// 在需要发送告警的地方
void SomeFunction() {
// 使用等级化接口发送告警
AlarmManager::GetInstance()->SendAlarmWarning(
NEW_ALARM_TYPE,
"具体错误信息: " + errorDetails
);
// 或者使用其他等级
AlarmManager::GetInstance()->SendAlarmError(
NEW_ALARM_TYPE,
"严重错误信息"
);
}
重要注意事项:
ALL_LOGTAIL_ALARM_NUM为新的总数mMessageType向量中添加对应的字符串SendAlarm方法在 pkg/selfmonitor/alarm_constants.go 中添加告警类型:
const (
// ... 现有类型
NewAlarmType AlarmType = "NEW_ALARM_TYPE"
)
使用告警:
// 在需要发送告警的地方
func (p *Plugin) ProcessData() error {
if err := p.doSomething(); err != nil {
// 使用等级化接口发送告警
logger.Warning(ctx, selfmonitor.NewAlarmType,
fmt.Sprintf("处理数据失败: %v", err))
return err
}
// 或者使用其他等级
if p.isCriticalError() {
logger.Critical(ctx, selfmonitor.NewAlarmType,
"严重错误,需要立即处理")
}
return nil
}
重要注意事项:
Warning、Error、Critical命名规范:
AlarmManager, MetricRecordSendAlarmWarning, GetInstanceMETRIC_AGENT_CPUmAlarmBufferMutex, mAllAlarmMap代码结构:
命名规范:
selfmonitorAlarmType, AlarmLevelRecord, SerializeToPbAlarmLevelWarning代码结构:
在合适的生命周期创建指标:
C++示例:
class Plugin {
private:
MetricsRecordRef mMetricsRecordRef;
CounterPtr mProcessedCounter;
IntGaugePtr mQueueSizeGauge;
public:
bool Init() {
// 在Init方法中创建MetricsRecordRef和指标对象
MetricLabelsPtr labels = std::make_shared<MetricLabels>();
labels->emplace_back(METRIC_LABEL_KEY_PLUGIN_TYPE, "input_file");
WriteMetrics::GetInstance()->PrepareMetricsRecordRef(
mMetricsRecordRef, std::move(labels), nullptr);
// 创建指标对象
mProcessedCounter = mMetricsRecordRef.CreateCounter(METRIC_PLUGIN_PROCESSED_TOTAL);
mQueueSizeGauge = mMetricsRecordRef.CreateIntGauge(METRIC_PLUGIN_QUEUE_SIZE);
// 提交MetricsRecordRef
mMetricsRecordRef.Commit();
return true;
}
};
Go示例:
type Plugin struct {
pipeline.PluginContext
processedCounter selfmonitor.CounterMetric
queueSizeGauge selfmonitor.GaugeMetric
}
func (p *Plugin) InitMetricRecord(pluginMeta *pipeline.PluginMeta) {
// 获取插件通用labels
labels := pipeline.GetPluginCommonLabels(p.Config.Context, pluginMeta)
// 注册MetricsRecord
p.MetricRecord = p.Config.Context.RegisterMetricRecord(labels)
// 创建并注册指标对象
p.processedCounter = selfmonitor.NewCounterMetricAndRegister(p.MetricRecord, selfmonitor.MetricPluginProcessedTotal)
p.queueSizeGauge = selfmonitor.NewGaugeMetricAndRegister(p.MetricRecord, selfmonitor.MetricPluginQueueSize)
}
选择合适的告警等级:
// 正确:根据影响程度选择等级
void ProcessData() {
if (parseError) {
// warning: 单点解析失败,不影响整体流程
AlarmManager::GetInstance()->SendAlarmWarning(
PARSE_LOG_FAIL_ALARM,
"单行解析失败: " + errorLine
);
}
if (queueFull) {
// error: 队列满,影响处理流程
AlarmManager::GetInstance()->SendAlarmError(
PROCESS_QUEUE_BUSY_ALARM,
"处理队列已满,当前大小: " + std::to_string(queueSize)
);
}
if (configLoadFailed) {
// error: 单个采集配置加载失败,影响一个流水线,可能导致客户资损
AlarmManager::GetInstance()->SendAlarmCritical(
CATEGORY_CONFIG_ALARM,
"采集配置加载失败: " + configError
);
}
}
提供有意义的告警消息:
// 正确:包含具体错误信息和解决建议
void HandleFileError(const std::string& filePath, int errorCode) {
std::string message = "文件读取失败: " + filePath +
", 错误码: " + std::to_string(errorCode) +
", 建议检查文件权限和路径";
AlarmManager::GetInstance()->SendAlarmError(
OPEN_LOGFILE_FAIL_ALARM,
message
);
}
// 错误:告警消息过于简单
void HandleFileErrorWrong(const std::string& filePath) {
AlarmManager::()->(
OPEN_LOGFILE_FAIL_ALARM,
);
}
在提交涉及自监控的代码前,请确保:
指标命名:
告警使用:
代码实现:
性能考虑:
测试验证:
使用安全的更新宏:
// 使用宏确保指针非空
void Plugin::ProcessData() {
// 检查MetricsRecordRef状态
if (mMetricsRecordRef.IsCommitted()) {
ADD_COUNTER(mProcessedCounter, 1);
SET_GAUGE(mQueueSizeGauge, currentQueueSize);
}
}
// 错误示例:直接调用可能为空指针
void Plugin::ProcessDataWrong() {
mProcessedCounter->Add(1); // 危险:可能为空指针
}
避免频繁创建指标对象:
// 正确:在初始化时创建一次
class Plugin {
CounterPtr mCounter; // 成员变量,只创建一次
public:
void Init() {
mCounter = mMetricsRecordRef.CreateCounter(METRIC_NAME);
mMetricsRecordRef.Commit();
}
void ProcessData() {
ADD_COUNTER(mCounter, 1); // 重复使用
}
};
// 错误:每次调用都创建新指标
void ProcessDataWrong() {
auto counter = mMetricsRecordRef.CreateCounter(METRIC_NAME); // 错误:频繁创建
counter->Add(1);
}
避免告警风暴:
// 正确:使用限流机制避免告警风暴
class AlarmLimiter {
private:
std::map<AlarmType, time_t> mLastAlarmTime;
static const int ALARM_INTERVAL_SEC = 60; // 60秒内不重复发送相同告警
public:
void SendAlarmWithLimit(AlarmType type, const std::string& message) {
time_t now = time(nullptr);
auto it = mLastAlarmTime.find(type);
if (it == mLastAlarmTime.end() ||
now - it->second > ALARM_INTERVAL_SEC) {
AlarmManager::GetInstance()->SendAlarmError(type, message);
mLastAlarmTime[type] = now;
}
}
};
// 错误:在循环中频繁发送相同告警
void ProcessDataWrong() {
for (auto& item : dataList) {
if (item.hasError) {
// 错误:可能产生大量重复告警
AlarmManager::GetInstance()->SendAlarmError(
PROCESS_DATA_FAIL_ALARM,
"数据处理失败"
);
}
}
}