Skip to content
cccskills
FreePublished on GitHub

observability

实现日志 / 指标 / 追踪三大支柱时使用。覆盖 OpenTelemetry / Prometheus / Grafana / Jaeger / Datadog / Sentry 集成。融合 Google SRE 三支柱 + 结构化日志 + Trace Context 传播。

The English summary is being prepared. Showing the original description.

See how to install

Files included (2)

  • SKILL.md13.1 KB
  • templates/observability-checklist.md4.6 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

可观测性(Observability)

参考来源:Google《Site Reliability Engineering》、《Distributed Systems Observability》(Cindy Sridharan)、OpenTelemetry 官方文档、Honeycomb 高基数追踪、Stripe 可观测性实践。

适用场景

  • 接入日志 / 指标 / 追踪(三大支柱)
  • 排查线上问题
  • 性能监控
  • SLO / SLI 度量
  • 错误跟踪(Sentry / Datadog Errors)
  • 业务指标埋点

核心原则

1. 三大支柱缺一不可
   日志(Logs):发生了什么
   指标(Metrics):当前状态
   追踪(Traces):请求路径

2. 结构化日志
   不用纯文本,用 JSON / key-value

3. Trace ID 贯穿全链路
   从入口生成,所有日志 / 调用都带

4. 关键业务指标必埋
   订单数 / 支付成功率 / 注册量

5. 用 OpenTelemetry 标准
   厂商无关,可切换后端

6. 不日志输出 PII / Token
   用 [REDACTED] 占位

7. 采样率合理
   全采样压垮系统,1% 又看不清

8. 告警 ≠ 监控
   监控全采集,告警仅必报

三大支柱

1. 日志(Logs)

作用:发生了什么的离散事件
适合:排查具体问题

特点:
  - 结构化(JSON)
  - 含 trace_id
  - 不输出敏感信息
  - 分级(DEBUG/INFO/WARN/ERROR)

2. 指标(Metrics)

作用:当前状态的数值聚合
适合:监控告警

类型:
  - Counter(累加,如请求数)
  - Gauge(瞬时,如内存使用)
  - Histogram(分布,如响应时间 P99)
  - Summary(quantile)

四个黄金信号(Google SRE):
  Latency(延迟)
  Traffic(流量)
  Errors(错误率)
  Saturation(饱和度)

3. 追踪(Traces)

作用:请求经过哪些服务
适合:分布式系统排查、性能定位

概念:
  Trace:一次完整请求
  Span:trace 中的一段(一个服务一个 span)
  Parent / Child:调用关系

结构化日志

Spring Boot

// logback-spring.xml 配置 JSON 格式
<configuration>
  <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
      <includeMdcKeyName>traceId</includeMdcKeyName>
      <includeMdcKeyName>spanId</includeMdcKeyName>
      <includeMdcKeyName>userId</includeMdcKeyName>
    </encoder>
  </appender>
</configuration>
// 用法
@Slf4j
@RestController
public class OrderController {
  @PostMapping("/orders")
  public Order create(@RequestBody CreateOrderRequest req) {
    MDC.put("userId", String.valueOf(req.getUserId()));
    
    log.info("Creating order, items={}", req.getItems().size());
    
    try {
      Order order = orderService.create(req);
      log.info("Order created, orderId={}, amount={}", order.getId(), order.getTotal());
      return order;
    } catch (Exception e) {
      log.error("Failed to create order", e);
      throw e;
    } finally {
      MDC.clear();
    }
  }
}

NestJS

// 用 nestjs-pino 或 winston
import { Logger as PinoLogger } from 'nestjs-pino';

@Injectable()
export class OrderService {
  constructor(private logger: PinoLogger) {}
  
  async create(dto: CreateOrderDto, user: User) {
    this.logger.info({ userId: user.id, items: dto.items.length }, 'Creating order');
    
    try {
      const order = await this.repo.create(dto);
      this.logger.info({ orderId: order.id, amount: order.total }, 'Order created');
      return order;
    } catch (err) {
      this.logger.error({ err, userId: user.id }, 'Failed to create order');
      throw err;
    }
  }
}

Python

import structlog

logger = structlog.get_logger()

def create_order(dto, user):
    log = logger.bind(user_id=user.id, items=len(dto.items))
    log.info('creating_order')
    
    try:
        order = repo.create(dto)
        log.info('order_created', order_id=order.id, amount=order.total)
        return order
    except Exception as e:
        log.error('order_creation_failed', error=str(e))
        raise

Go

import "go.uber.org/zap"

logger, _ := zap.NewProduction()

func CreateOrder(ctx context.Context, dto CreateOrderDto, user User) (*Order, error) {
    log := logger.With(
        zap.Int64("user_id", user.ID),
        zap.Int("items", len(dto.Items)),
        zap.String("trace_id", trace.GetTraceID(ctx)),
    )
    log.Info("creating_order")
    
    order, err := repo.Create(dto)
    if err != nil {
        log.Error("order_creation_failed", zap.Error(err))
        return nil, err
    }
    log.Info("order_created", zap.Int64("order_id", order.ID))
    return order, nil
}

OpenTelemetry 集成(统一标准)

Spring Boot

# application.yml
otel:
  service:
    name: order-service
  exporter:
    otlp:
      endpoint: http://otel-collector:4317
  traces:
    sampler: parentbased_traceidratio
    sampler-arg: 0.1  # 10% 采样
// 自动追踪(用 micrometer-tracing)
@RestController
public class OrderController {
  @Autowired
  private Tracer tracer;
  
  @PostMapping("/orders")
  public Order create(@RequestBody CreateOrderRequest req) {
    Span span = tracer.spanBuilder("createOrder")
      .setAttribute("user.id", req.getUserId())
      .startSpan();
    try (Scope scope = span.makeCurrent()) {
      return orderService.create(req);
    } finally {
      span.end();
    }
  }
}

NestJS

// 用 @opentelemetry/sdk-node
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: 'http://otel-collector:4318/v1/traces',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

Python

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(provider)

tracer = trace.get_tracer(__name__)

@app.post('/orders')
async def create_order(dto: CreateOrderDto, user: User = Depends(get_current_user)):
    with tracer.start_as_current_span('createOrder') as span:
        span.set_attribute('user.id', user.id)
        span.set_attribute('items.count', len(dto.items))
        return await order_service.create(dto, user)

关键指标(必埋)

通用指标

HTTP 层:
  http_requests_total{method, endpoint, status}        # Counter
  http_request_duration_seconds{method, endpoint}      # Histogram
  http_requests_in_flight                              # Gauge

DB 层:
  db_queries_total{operation, table}
  db_query_duration_seconds{operation, table}
  db_connections_active

Cache 层:
  cache_operations_total{operation, status}
  cache_hit_rate

Queue 层:
  queue_depth{queue_name}
  queue_processing_duration_seconds{queue_name}
  queue_failed_total{queue_name}

业务指标

orders_created_total                       # 订单数
payments_succeeded_total                   # 支付成功
payments_failed_total{reason}              # 支付失败(按原因)
user_signups_total{source}                 # 注册(按来源)
revenue_total{currency}                    # 收入

Spring Boot + Micrometer

@RestController
public class OrderController {
  @Autowired private MeterRegistry meterRegistry;
  
  @PostMapping("/orders")
  public Order create(@RequestBody CreateOrderRequest req) {
    Timer.Sample sample = Timer.start(meterRegistry);
    try {
      Order order = orderService.create(req);
      meterRegistry.counter("orders.created.total", 
        "user_type", req.getUserType()).increment();
      return order;
    } finally {
      sample.stop(meterRegistry.timer("orders.create.duration"));
    }
  }
}

NestJS + prom-client

import { Counter, Histogram } from 'prom-client';

const orderCreatedCounter = new Counter({
  name: 'orders_created_total',
  help: 'Total orders created',
  labelNames: ['user_type'],
});

const orderDuration = new Histogram({
  name: 'order_create_duration_seconds',
  help: 'Order creation duration',
  buckets: [0.1, 0.5, 1, 2, 5],
});

@Injectable()
export class OrderService {
  async create(dto: CreateOrderDto, user: User) {
    const end = orderDuration.startTimer();
    try {
      const order = await this.repo.create(dto);
      orderCreatedCounter.labels(user.type).inc();
      return order;
    } finally {
      end();
    }
  }
}

// 暴露 /metrics 端点(Prometheus 抓取)
@Controller()
export class MetricsController {
  @Get('metrics')
  async metrics(@Res() res: Response) {
    res.set('Content-Type', register.contentType);
    res.send(await register.metrics());
  }
}

Trace ID 传播

入口(API Gateway / Controller):
  生成 trace_id(如未有)
  注入 MDC / AsyncLocalStorage / context

下游调用:
  HTTP:传播 X-Request-Id / traceparent header
  消息队列:放进消息 metadata
  数据库:可选

日志:
  每行日志带 trace_id

监控:
  追踪图自动串联
// NestJS 中间件
@Injectable()
export class TraceMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    const traceId = req.headers['x-request-id'] || uuidv4();
    AsyncLocalStorage.run({ traceId }, () => {
      res.setHeader('X-Request-Id', traceId);
      next();
    });
  }
}

错误跟踪(Sentry)

import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1,  // 10% 性能追踪
  beforeSend(event) {
    // 过滤敏感信息
    if (event.request?.headers) {
      delete event.request.headers['authorization'];
      delete event.request.headers['cookie'];
    }
    return event;
  },
});

// 用法
try {
  await orderService.create(...);
} catch (err) {
  Sentry.captureException(err, {
    user: { id: user.id },
    extra: { orderId: order.id },
  });
  throw err;
}

健康检查端点

@Controller()
export class HealthController {
  @Get('health')
  async health() {
    return { status: 'ok', timestamp: Date.now() };
  }
  
  @Get('health/ready')  // K8s readiness
  async ready() {
    const checks = await Promise.all([
      this.checkDatabase(),
      this.checkRedis(),
    ]);
    if (checks.every(c => c.ok)) {
      return { status: 'ready', checks };
    }
    throw new ServiceUnavailableException({ status: 'not_ready', checks });
  }
  
  @Get('health/live')  // K8s liveness
  async live() {
    return { status: 'alive' };
  }
}

工作流程

1. 接入 OpenTelemetry SDK
   - 自动追踪 HTTP / DB / Redis / 消息队列

2. 配置结构化日志
   - JSON 格式
   - 含 trace_id / user_id

3. 埋点关键指标
   - HTTP 黄金信号
   - 业务指标
   - 资源使用

4. Trace ID 传播
   - 入口生成
   - 下游传递

5. 错误跟踪接入(Sentry)
   - 过滤敏感信息

6. 配置健康检查
   - liveness / readiness

7. 接入 APM 平台
   - Datadog / Prometheus + Grafana / 自建

8. 设计告警
   - SLO 偏离
   - 错误率突增
   - 延迟退化

配套模板

  • templates/observability-checklist.md — 三大支柱 + 关键指标 + Trace ID + Sentry + 健康检查 + 告警

质量自检

□ 日志结构化(JSON)
□ 日志含 trace_id
□ 日志不输出 PII / Token
□ 关键业务指标埋点
□ HTTP 黄金信号采集
□ Trace 串联全链路
□ OpenTelemetry 标准
□ 错误跟踪(Sentry)
□ 健康检查(liveness + readiness)
□ 采样率合理(不全采)
□ 监控覆盖率 > 80%
□ 告警基于 SLO 不基于 alert fatigue

常见坑

  1. 纯文本日志——无法搜索 / 聚合
  2. 不带 trace_id——分布式排错困难
  3. 日志输出密码 / Token——合规问题
  4. 指标 cardinality 爆炸——userId 当 label
  5. 全采样追踪——性能 / 存储压垮
  6. 不区分 INFO / DEBUG——日志爆炸
  7. 告警过多——alert fatigue,重要的被忽略
  8. 不监控业务指标——只盯技术指标,业务退化无感
  9. 采样率太低——关键链路追不到
  10. 不集成 OpenTelemetry——锁定厂商
  11. 错误日志不带堆栈——排查困难
  12. 指标命名不统一——查询难
  13. 不用结构化错误——Sentry 看不出聚合
  14. 健康检查 = 假死检查——liveness 检查 DB 拖死自己

与其他 skill 的协作

上游:
  api-implementation → 中间件埋点
  data-access → SQL 监控
  caching-strategy → 缓存监控
  async-jobs → 队列监控
  error-handling-resilience → 错误监控

下游:
  sre-ops 工作流 → 告警 / SLO

相关参考

  • 项目根 references/backend-tech-stack-guide.md — 可观测性方案

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

A/B 测试设计与分析时使用。适用于产品实验、功能验证、转化率优化。融合假设驱动 + 样本量计算 + 置信度判断。

The English summary is being prepared. Showing the original description.

zhaoxuya520/AI-Fullstack-Delivery-Workflow54Updated May 19, 2026

上线前业务方/产品方验收时使用。适用于功能交付确认、UAT、发布会签。融合 BDD Given-When-Then、Specification by Example、ATDD。

The English summary is being prepared. Showing the original description.

zhaoxuya520/AI-Fullstack-Delivery-Workflow54Updated May 19, 2026

设计无障碍可访问的界面时使用。适用于满足 WCAG 标准、键盘导航、屏幕阅读器支持。优先使用 WCAG 2.2 AA 级标准 + 键盘 + 焦点 + 对比度 + ARIA。

The English summary is being prepared. Showing the original description.

zhaoxuya520/AI-Fullstack-Delivery-Workflow54Updated May 19, 2026

实现可访问性(无障碍)时使用。覆盖 WCAG 2.2 AA / ARIA / 键盘导航 / 屏幕阅读器 / 颜色对比 / 焦点管理。融合 React Aria / Radix UI / Headless UI 实践 + axe-core 自动化测试。

The English summary is being prepared. Showing the original description.

zhaoxuya520/AI-Fullstack-Delivery-Workflow54Updated May 19, 2026

AI 模型部署时使用。适用于推理服务 / GPU / TensorRT / 监控 / 扩缩容。

The English summary is being prepared. Showing the original description.

zhaoxuya520/AI-Fullstack-Delivery-Workflow54Updated May 19, 2026

数据分析报告输出时使用。适用于业务分析报告、周报、专项分析、决策支持。融合洞察 + 建议 + 行动项。

The English summary is being prepared. Showing the original description.

zhaoxuya520/AI-Fullstack-Delivery-Workflow54Updated May 19, 2026

See all skills by zhaoxuya520

Report a problem with this skill