腾讯mini项目-【指标监控服务重构】2023-07-20

今日已办

Trace

otelzap :opentelemetry-go-extra/otelzap at main · uptrace/opentelemetry-go-extra (github.com)

sh 复制代码
go get github.com/uptrace/opentelemetry-go-extra/otelzap

声明 Tracer ,一个应用创建一个 Tracer (需要从venus中来传来的trace_id构造

go 复制代码
var consumerTracer = otel.Tracer("profile-consumer",
		trace.WithInstrumentationAttributes(attribute.String("profile.work", "consumer")))

处理异常,日志记录 & Span 记录错误 & 设置状态

go 复制代码
func handlerErr(span trace.Span, ctx context.Context, msg string, err error) {
    // otelzap 集成zap
	otelzap.L().Ctx(ctx).Error(msg, zap.Error(err))
	span.RecordError(err)
	span.SetStatus(codes.Error, msg)
}

在每一个Handler中使用同一个 Tracer 创建Span

go 复制代码
func (profileCtx *ProfileContext) UnpackKafkaMessage(ctx context.Context) (needBreak bool, tpsStatus string, contextErr error) {
	var span trace.Span
    // 根Span,类型为内部
	profileCtx.Ctx, span = consumerTracer.Start(profileCtx.Ctx, "UnpackKafkaMessage",
		trace.WithNewRoot(), trace.WithSpanKind(trace.SpanKindInternal))
	defer span.End()
	if contextErr = json.Unmarshal(profileCtx.msg.Value, &profileCtx.Event); contextErr != nil {
		profileCtx.Status = state.StatusUnmarshalError
		handlerErr(span, profileCtx.Ctx, "unmarshal error", contextErr)
		return
	}
    // 设置属性
	if span.IsRecording() {
		span.SetAttributes(
			attribute.String("event.id", profileCtx.Event.ID),
		)
	}
	log.Logger.Info("[UnpackKafkaItem] unpack kafka item success", zap.Any("event", profileCtx.Event))
	return
}

Metric

根据组员 张锐添 提供的可用性方案和代码实现

  1. 设置metric PeriodicReader的上报间隔
  2. 创建新的 MeterProvider
  3. 使用 Int64ObservableGauge 在每个测量收集周期,异步记录一次 StatusAlive的 瞬时值
go 复制代码
func InitAvailabilityObserver() func() {

	ctx := context.Background()

	res, err := createResource(ctx)
	handleErr(err, "failed to create resource")

	otelAgentAddr := config.Profile.GetString("otelclient.otelExporterOtlpEndpoint")
	metricExp := createMetricExp(err, ctx, otelAgentAddr)
	handleErr(err, "Failed to create the otelclient metric exporter")

	mp := sdkmetric.NewMeterProvider(
		sdkmetric.WithResource(res),
		sdkmetric.WithReader(
			sdkmetric.NewPeriodicReader(
				metricExp,
				sdkmetric.WithInterval(10*time.Second), // 10s上报一次
				sdkmetric.WithTimeout(2*time.Second),   // 设置超时
			),
		),
	)

	const (
		StatusAlive = iota // 可用状态
	)

	_, err = mp.Meter("profile-availability-meter").Int64ObservableGauge(
		"profile/alive_observer",
		// 每个测量值收集周期,异步记录一次瞬时 int64 测量值
		metric.WithInt64Callback(func(ctx context.Context, observer metric.Int64Observer) error {
			observer.Observe(
				StatusAlive,
				// metric.WithAttributes(attribute.String("", "")),
			)
			return nil
		}),
	)
	handleErr(err, "Failed to create the ObservableGauge")

	log.Logger.Info("init availabilityObserver success")

	return func() {
		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
		defer cancel()
		if err := mp.Shutdown(ctx); err != nil {
			otel.Handle(err)
		}
	}
}

在 SigNoz Web 的 Dashboards 配置 ClickHouse Query

sql 复制代码
SELECT
    toStartOfMinute(toTimeZone(toDateTime(timestamp_ms/1000), 'Asia/Shanghai')) AS minute,
    count(*)/6 AS result
FROM signoz_metrics.samples_v2
WHERE metric_name='profile_alive_observer' AND timestamp_ms >= 1000*toUnixTimestamp(toStartOfMinute(toTimeZone(now(), 'Asia/Shanghai') - INTERVAL 1 DAY))
GROUP BY minute
ORDER BY minute ASC

发现问题

请求 Venus 的 Post 接口,Profile 消费了两次,由于上报的json数据的data字段是数组(包含了多条数据)

使用 Int64Counter 记录消费总次数时(同步且递增),在服务重新启动后,测量值会重新从0开始

traefik 反向代理

yaml 复制代码
http:
  routers:
    frontend-router:
      rule: "PathPrefix(`/frontend`)"
      entrypoints:
        - web-entrypoint
      service: frontend-service
  services:
    frontend-service:
      loadBalancer:
        servers:
          - url: http://profile-frontend:3301

组会记录

  1. SRE报表- SLI SLO SLA (指标、具体范围或者限制, 协议)--- 具体以什么形式,可视化出来
  2. 服务(进程)的CPU、内存利用率等指标,shirou/gopsutil: psutil for golang (github.com)
  3. 重启服务,Counter计数器的值会从零开始计算
  4. traefik反向代理 :指定一个端口,前缀为'/'的请求都路由到frontend服务
  5. Log上报目标 - [郑兆隆]
  6. Grafana配置Ck的仪表盘
  7. Trace 收集到的 Span 的延时、错误率、吞吐量需要用指标 metric 来上报吗
  8. Profile的ToDo

明日待办

  1. 组长会议汇报项目进度和问题
相关推荐
charlie11451419142 分钟前
嵌入式C++工程实践第16篇:第四次重构 —— LED模板,从通用GPIO到专用抽象
c语言·开发语言·c++·驱动开发·嵌入式硬件·重构
ZC跨境爬虫4 小时前
3D 地球卫星轨道可视化平台开发 Day8(分步渲染200颗卫星+ 前端分页控制)
前端·python·3d·重构·html
升鲜宝供应链及收银系统源代码服务6 小时前
OMS 订单模块重构正式文档(一)---升鲜宝生鲜配送供应链管理系统
java·开发语言·重构·生鲜配送源代码·生鲜供应链源代码
你有医保你先上6 小时前
Elasticsearch Go 客户端
后端·elasticsearch·go
迷藏4948 小时前
# 发散创新:基于Selenium的自动化测试框架重构与实战优化在当今快速迭代的软件开
java·python·selenium·测试工具·重构
Vale36512 小时前
[Go]字符串 比较
go
快乐非自愿13 小时前
4月AI王炸:GPT-6、量子AI、具身智能,三大风口重构技术未来
人工智能·gpt·重构
一叶星殇15 小时前
.NET 11 全面前瞻:从运行时重构到 AI 原生平台的跃迁
重构
UIUV1 天前
Go语言入门到精通学习笔记
后端·go·编程语言
littleschemer1 天前
Go异步持久化如何防止炸服
go·map并发崩溃