首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

Go 监控告警入门 Opentelemetry

编程知识
2024年08月16日 08:10

前言

Opentelemetry

分布式链路跟踪( Distributed Tracing )的概念最早是由 Google 提出来的,发展至今技术已经比较成熟,也是有一些协议标准可以参考。目前在 Tracing 技术这块比较有影响力的是两大开源技术框架:Netflix 公司开源的 OpenTracing 和 Google 开源的 OpenCensus。两大框架都拥有比较高的开发者群体。为形成统一的技术标准,两大框架最终磨合成立了 OpenTelemetry 项目,简称 otel。otel 有链路追踪和监控告警两大块,关于监控告警,可以查看另一篇文章:Go 链路追踪入门 Opentelemetry

Prometheus

Prometheus 源自 SoundCloud,拥有一整套开源系统监控和警报工具包,是支持 OpenTelemetry 的系统之一,是 CNCF 的第二个项目。

Grafana

Grafana 是一个开源的分析和可视化平台,它允许你查询、可视化和警报来自各种数据源的数据。它提供了一个用户友好的界面,用于创建和共享仪表板、图表和警报。Grafana 支持广泛的数据源,其中就包括 Prometheus

基础概念

这里为了简单入门,尽量简单的介绍一些抽象概念,结合着代码理解,如果不能理解也没关系,代码写着写着自然就明白了:

Meter Provider
用于接口化管理全局的 Meter 创建,相当于全局的监控指标管理工厂。

Meter
用于接口化创建并管理全局的 Instrument,不同的 Meter 可以看做是不同的程序组件。

Instrument
用于管理不同组件下的各个不同类型的指标,例如 http.server.request.total

Measurements
对应指标上报的具体的 DataPoint 指标数据,是一系列的数值项。

Metric Reader
用于实现对指标的数据流读取,内部定义了具体操作指标的数据结构。OpenTelemetry 官方社区提供了多种灵活的 Reader 实现,例如 PeridRader、ManualReader 等。

Metric Exporter
Exporter 用于暴露本地指标到对应的第三方厂商,例如:Promtheus、Zipkin 等。

指标类型

OpenTelemetry metrics 有许多不同指标类型,可以把它想象成类似于 int, float 这种的变量类型:

Counter:只增不减的指标,比如 http 请求总数,字节大小;

Asynchronous Counter:异步 Counter;

UpDownCounter:可增可减的指标,比如 http 活动连接数;

Asynchronous UpDownCounter:异步 Counter;

Gauge:可增可减的指标,瞬时计量的值,比如 CPU 使用,它是异步的;

Histogram:分组聚合指标,这个较为难以理解一些,可以移步此处查看,当然,后文也会有一个详细的例子来使用它。

实战:采集指标

废话了一堆,终于可以实战了。我们先以 http 请求总数为例来走一遍整个采集指标流程。安装扩展:

go get github.com/prometheus/client_golang
go get go.opentelemetry.io/otel/exporters/prometheus
go get go.opentelemetry.io/otel/metric
go get go.opentelemetry.io/otel/sdk/metric

打开 main.go,编写以下代码:

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"

	"github.com/prometheus/client_golang/prometheus/promhttp"
	"go.opentelemetry.io/otel/exporters/prometheus"
	api "go.opentelemetry.io/otel/metric"
	"go.opentelemetry.io/otel/sdk/metric"
)

const meterName = "oldme_prometheus_testing"

var (
	requestHelloCounter api.Int64Counter
)

func main() {
	ctx := context.Background()

	// 创建 prometheus 导出器
	exporter, err := prometheus.New()
	if err != nil {
		log.Fatal(err)
	}

	// 创建 meter
	provider := metric.NewMeterProvider(metric.WithReader(exporter))
	meter := provider.Meter(meterName)

	// 创建 counter 指标类型
	requestHelloCounter, err = meter.Int64Counter("requests_hello_total")
	if err != nil {
		log.Fatal(err)
	}

	go serveMetrics()

	ctx, _ = signal.NotifyContext(ctx, os.Interrupt)
	<-ctx.Done()
}

func serveMetrics() {
	log.Printf("serving metrics at localhost:2223/metrics")
	http.Handle("/metrics", promhttp.Handler())

	http.Handle("/index", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 记录 counter 指标
		requestHelloCounter.Add(r.Context(), 1)

		_, _ = w.Write([]byte("Hello, Otel!"))
	}))

	err := http.ListenAndServe(":2223", nil) //nolint:gosec // Ignoring G114: Use of net/http serve function that has no support for setting timeouts.
	if err != nil {
		fmt.Printf("error serving http: %v", err)
		return
	}
}

在我们的代码中,我们定义一个名字为 requests_hello_totalInt64Counter 指标类型,Int64Counter 代表这是一个只增不减的 int64 数值,用作记录请求总数正好合适。运行我们的程序,如果不出错的话,访问 http://localhost:2223/index 可以看到 Hello, Otel!。并且我们访问 http://localhost:2223/metrics 可以看到指标数据:

这里数据还没有进行可视化,我们先把流程走通,多访问几次 http://localhost:2223/index 可以看到 requests_hello_total 会增加:

Histogram

接下来我们采集一下 Histogram 指标,统计在 0.1, 0.2, 0.5, 1, 2, 5 秒以内的 http 请求数,在 main.go 中加上相关代码,可以直接复制过去:

package main

import (
	"context"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"time"

	"github.com/prometheus/client_golang/prometheus/promhttp"
	"go.opentelemetry.io/otel/exporters/prometheus"
	api "go.opentelemetry.io/otel/metric"
	"go.opentelemetry.io/otel/sdk/metric"
)

const meterName = "oldme_prometheus_testing"

var (
	requestHelloCounter      api.Int64Counter
	requestDurationHistogram api.Float64Histogram
)

func main() {
	ctx := context.Background()

	// 创建 prometheus 导出器
	exporter, err := prometheus.New()
	if err != nil {
		log.Fatal(err)
	}

	// 创建 meter
	provider := metric.NewMeterProvider(metric.WithReader(exporter))
	meter := provider.Meter(meterName)

	// 创建 counter 指标类型
	requestHelloCounter, err = meter.Int64Counter("requests_hello_total")
	if err != nil {
		log.Fatal(err)
	}

	// 创建 Histogram 指标类型
	requestDurationHistogram, err = meter.Float64Histogram(
		"request_hello_duration_seconds",
		api.WithDescription("记录 Hello 请求的耗时统计"),
		api.WithExplicitBucketBoundaries(0.1, 0.2, 0.5, 1, 2, 5),
	)
	if err != nil {
		log.Fatal(err)
	}

	go serveMetrics()
	go goroutineMock()

	ctx, _ = signal.NotifyContext(ctx, os.Interrupt)
	<-ctx.Done()
}

func serveMetrics() {
	log.Printf("serving metrics at localhost:2223/metrics")
	http.Handle("/metrics", promhttp.Handler())

	http.Handle("/index", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 记录 counter 指标
		requestHelloCounter.Add(r.Context(), 1)

		// 计算请求处理时间
		startTime := time.Now()
		// 模拟请求处理时间
		time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
		defer func() {
			duration := time.Since(startTime).Seconds()
			requestDurationHistogram.Record(r.Context(), duration)
		}()

		_, _ = w.Write([]byte("Hello, Otel!"))
	}))

	err := http.ListenAndServe(":2223", nil) //nolint:gosec // Ignoring G114: Use of net/http serve function that has no support for setting timeouts.
	if err != nil {
		fmt.Printf("error serving http: %v", err)
		return
	}
}

// 随机模拟若干个协程
func goroutineMock() {
	for {
		go func() {
			// 等待若干秒
			var s = time.Duration(rand.Intn(10))
			time.Sleep(s * time.Second)
		}()
		time.Sleep(1 * time.Millisecond)
	}
}

走到这里,代码层面结束了,已经成功一半了,代码开源在 Github。之后我们就可以安装 Prometheus 服务端和 Grafana 来进行数据可视化。

安装 Prometheus

Prometheus 有多种安装方式,我这里依旧采用 Docker 安装,当然,你也可以使用其他方式安装,具体安装方式可以参考其他文章,后续 Grafana 同理,不在赘述,在 Prometheus.yml 中填写 targets 我们的地址:

scrape_configs:
  - job_name: "prometheus"

    static_configs:
      - targets: ["localhost:2223"]

Prometheus 会自动去 {{target}}/metrics 中拉取我们的指标。之后在浏览器打开 Promethues 的地址,例如我的是:http://localhost:9090,如果全部正常的话可以在 status:targets 中看见我们的指标:

Promethues 的首页查询 requests_hello_total 指标可以看到可视化的图表:

安装 Grafana

我的 Grafana 安装好了,登录进去后是这样的(我更改后默认颜色):

Data source 中添加 Prometheus 服务器,然后在 Dashboard 中添加我们想要监控的指标,即可看到更美观的图表:

From:https://www.cnblogs.com/oldme/p/18360846
本文地址: http://www.shuzixingkong.net/article/1146
0评论
提交 加载更多评论
其他文章 ZPL Viewer工具网站
新上线的ZPL Viewer网站(地址:[https://zplpreview.com/](https://zplpreview.com/))支持zpl预览,pdf、html、图片转zpl
Java异常 小白版
什么是异常 在程序运行时打断正常程序流程的任何不正常的情况称为错误或异常。异常包括用户造成的异常和 系统造成的异常。 例如:网络连接中断、操作符越界、加载的类找不到 异常产生的原因和分类 1. 异常产生的原因 在Java中异常产生,主要是有三种原因: 编写程序代码中的错误产生的异常,比如数组越界、空
Java异常 小白版
数据结构基本概念和术语
概论 1.1 基本概念和术语 1.1.1 基本概念 计算机处理的的是数值性数据,当计算机处理用户信息表中的数据的时候,需要弄清3个问题 1.数据的逻辑结构 数据之间存在怎样的内在联系,数据中,有且只有一个是首节点/尾结点,其他节点有且只有一个相邻的位于它之前和之后的结点 2.数据的存储结构 数据在计
数据结构基本概念和术语 数据结构基本概念和术语 数据结构基本概念和术语
一种很变态但有效的DDD建模沟通方式
本文书接上回《这就是为什么你学不会DDD》,关注公众号(老肖想当外语大佬)获取信息: 最新文章更新; DDD框架源码(.NET、Java双平台); 加群畅聊,建模分析、技术实现交流; 视频和直播在B站。 https://mp.weixin.qq.com/s/TJEtclwcJydiE58pjWpXX
一种很变态但有效的DDD建模沟通方式 一种很变态但有效的DDD建模沟通方式 一种很变态但有效的DDD建模沟通方式
SMCA:港中文提出注意力图校准的DETR加速方案 | ICCV 2021
为了加速DETR收敛,论文提出了简单而有效的Spatially Modulated Co-Attention(SMCA)机制,通过在初始边界框位置给予较高的协同注意力响应值的约束来构建DETR的回归感知协同注意力。此外,将SMCA扩展为多头注意力和尺度选择注意力后,对比DETR可以实现更好的性能(1
SMCA:港中文提出注意力图校准的DETR加速方案 | ICCV 2021 SMCA:港中文提出注意力图校准的DETR加速方案 | ICCV 2021 SMCA:港中文提出注意力图校准的DETR加速方案 | ICCV 2021
如何快速自学开源项目?试试我的诀窍
在讲解项目的过程中,我发现很多同学并不清楚如何快速学习项目、以及如何快速阅读源码。今天这篇文章,我就带大家领悟这些技能,以后再自学项目会轻松很多~
如何快速自学开源项目?试试我的诀窍 如何快速自学开源项目?试试我的诀窍 如何快速自学开源项目?试试我的诀窍
首次在WebAPI中写单元测试
xUnit 这次我使用的是xUnit测试框架,而不是VS自带的MSTest框架。在添加新建项目时选择xUnit测试项目就行了。 目前只体验到了一个差别,即xUnit可以使用特性向测试方法传参,而不用在测试方法中一个赋值语句一个个去定义参数,这是比较方便的。 单元测试有一个好处,就是一次性可以获得所测
首次在WebAPI中写单元测试 首次在WebAPI中写单元测试
.NET 轻量化定时任务调度 FreeScheduler
前言 在平时项目开发中,定时任务调度是一项重要的功能,广泛应用于后台作业、计划任务和自动化脚本等模块。 FreeScheduler 是一款轻量级且功能强大的定时任务调度库,它支持临时的延时任务和重复循环任务(可持久化),能够按秒、每天/每周/每月固定时间或自定义间隔执行(CRON 表达式)。 此外
.NET 轻量化定时任务调度 FreeScheduler .NET 轻量化定时任务调度 FreeScheduler .NET 轻量化定时任务调度 FreeScheduler