python应用程序的工具库。在Redis的支持下暴露给普罗米修斯

instrumentor的Python项目详细描述


仪器

python应用程序的工具库。由Redis提供支持并向普罗米修斯公开

--进行中的工作--
--文档作为设计文档--

关于乐器

在构建多用途amr解决方案时,我们希望添加有效的 度量处理以公开我们的度量以供普罗米修斯使用。

我们找不到一个现有的解决办法来以一种可取的方式做到这一点。有 例如,django prometheus,但是 本质上,它们要求您将大多数django堆栈切换到它们自己的类 这样就有了内置的监控。它还使用 python prometheus客户端 做得不错,但在多进程或 部署在多个服务器上。它还要求每个进程启动自己的进程 普罗米修斯可以抓取的http服务器。所以如果你有一个可以扩展的应用程序 自动跟踪应该是 由于每个实例只保留其on进程的数据,因此被删除。

我们还有几个小服务处理来自不同 队列,我们也希望在不单独启动的情况下对它们进行检测 每个小工作都有网络服务器。

我们也想给芹菜的工作装上仪器,但因为我们无法控制 准确地说,我们认为集中的方法是有效的。

因此,我们希望将instrumentor设计为一个度量工具,它可以用于 使用共享存储作为度量的不同类型的应用程序,因此 我们可以将所有的指标放在同一个位置,并让我们控制如何公开它们。

设计

由于普罗米修斯的数据几乎是一个计数器的集合,随着时间的推移,我们可以建模 我们所有的指标都是通过使用普罗米修斯按照期望的间隔刮取的计数器。 在分布式环境中跟踪计数器的最佳方法是redis

所以所有的度量都被发送到redis,我们可以选择公开web应用程序度量。 在每个web应用程序中,通过将redis中的数据转换为适当的prometheus格式。 我们还可以创建一个单独的web应用程序,它只作为一个度量 检测应用程序的终结点。

因为我们在redis中也有一个预先确定的格式 编程语言可以使用相同的结构,我们有一个通用的方法 处理我们所有服务的应用程序日志。

命名空间

每个应用程序度量应该存在于单独的命名空间中。这使它成为可能 将多个应用程序度量存储在同一个redis实例中。它也能做到 如果您需要分离,可以方便地将应用程序度量移动到其他redis实例。

要创建名称空间,我们使用redis散列。

指标

所有度量类型的一般情况是,我们有一个计数器集合、一个名称和一个 说明。

通过为哈希中的密钥名定义特定格式,我们可以对 根据需要。

我们还需要保留每个度量上不同标签的信息。各 不同标签的组合应该创建一个单独的计数器。标签应该是 排序,使每个不同的标签组合仅生成一个计数器。例子 标签为{green,red,yellow}的度量应该增加与metric相同的计数器 使用标签{yellow,red,green}来减少计数器的数量并减少解析 需要.

为了简化解析并能够更容易地读取原始数据,我们还应该包括 提示密钥中的度量类型。

普罗米修斯度量的规则也应该适用。例如直方图和摘要是 只有几个带有预定义标签名称的计数器。这些标签名称应该也是 防止在其他类型上误用。

库将假设在定义 并不会对用户强制执行任何规则或检查。例如,不要使用 标签太多。每个标签在普罗米修斯中创建一个时间序列和一个计数器 在Redis中。

每个度量都应该有一个以描述结尾的键来保存 指标。需要某种形式的控制来不继续发送描述 每次更新时。

编码格式

要命名不同的值,我们应该使用用 分号的推荐分隔字符。

{度量名称}:{扩展名}:{标签}

标签应使用逗号分隔列表中的标签名称和标签文本进行编码

{标签名称}={标签值},{标签名称}={标签值}"

metric api_http_请求示例:

api_http_requests_total::method="POST",handler="/messages"

计数器

计数器是表示单个递增计数器的累积度量,其 值只能在重新启动时增加或重置为零。

HTTP请求示例

api_http_requests_total::                                         -> 32   # counter without labels
api_http_requests_total::method="POST",handler="/messages"        -> 12  # counter matching the labels
api_http_requests_total:description::                             ->  "Total HTTP Requets to API"
api_http_requests_total:type::                                    -> "counter"

仪表

普罗米修斯量表是一个可以增减的值。

温度示例

temperature_celcius::                                     -> 32   # counter without labels
temperature_celcius::location="MainOffice",sensor="34"    -> 12  # counter matching the labels
temperature_celcius:descri ption:                         -> "Total HTTP Requets to API"
temperature_celcius:type:                                 -> "gauge"

直方图

直方图对观察结果进行采样(通常是请求持续时间或响应之类的 并在可配置的存储桶中进行计数。它还提供了所有 观测值。普罗米修斯柱状图是累积柱状图所以所有的观察 将添加适合其他存储桶的内容。

您需要预先定义您的桶大小。

其他数据格式示例

http_request_duration_seconds:bucket:le="0.05"    ->  24054
http_request_duration_seconds:bucket:le="0.1"     ->  33444
http_request_duration_seconds:bucket:le="0.2"     ->  100392
http_request_duration_seconds:bucket:le="0.5"     ->  129389
http_request_duration_seconds:bucket:le="1"       ->  133988
http_request_duration_seconds:bucket:le="+Inf"    ->  144320
http_request_duration_seconds:sum:                 ->  53423
http_request_duration_seconds:count:               ->  144320 
http_request_duration_seconds:description:         ->  "Duration of HTTP requests"
http_request_duration_seconds:type:                ->  "histogram"

为了保存一些字节,扩展名用它们开头的字母编码。 description=d,sum=s,count=c,type=t,bucket=b,类型值也是 缩短:计数器=C,仪表=G,直方图=H,摘要=S

摘要

类似于直方图,但不使用存储桶,而是指定百分位数。

您需要提供一个最大值来计算百分比。

大于最大值的值应设置为1?

添加计数器,该计数器将为超过最大值的每个值增加。

rpc_duration_seconds::quantile:="0.01"      -> 3102
rpc_duration_seconds::quantile="0.05"       -> 3272
rpc_duration_seconds::quantile="0.5"        -> 4773
rpc_duration_seconds::quantile="0.9"        -> 9001
rpc_duration_seconds::quantile="0.99"       -> 76656
rpc_duration_seconds:sum:                   -> 1.7560473e+07
rpc_duration_seconds:count:                 -> 2693
rpc_duration_seconds:description:           -> "Duration of RPC" 
rpc_duration_seconds:type:                  ->  "summary"

与redis的交互

通过将eager标志设置为true,将直接发送所有度量更新,而不是 在调用.store()时的单个时间点。与…沟通 采用高效的redis流水线。

高级API

我们试着按照普罗米修斯的指示 开发客户机库。

收藏家注册

用于管理应用程序中的度量的主类。你将登记每个指标 在CollectorRegistry中,它将处理到Redis的所有通信。


reg = CollectorRegistry(redis_host='localhost', 
                        redis_port='6372', 
                        redis_db=0,
                        namespace='myapp' 
                        eager=False)


http_requests_total = Counter(.....)

reg.register(http_requests_total)
reg.unregister(http_requests_total)  # incase it is needed...

指标


http_requests_total = Counter(name='http_requests_total', 
                              description='Total amount of http requests', 
                              allowed_labels={'code', 'method', 'path'})


http_requests_total.inc()   # increment counter by 1
http_request_total.inc(3)   # increment counter by 3

http_requests_total.inc(labels={"code": "200"})

temperature_celcius = Gauge(name='temperature_celcius',
                            description='Temperature in celcius',
                            allowed_labels={'location', 'sensor'},
                            start_value=2)

temperature_celcius.inc()
temperature_celcius.inc(3)
temperature_celcius.dec()
temperature_celcius.dec(3)
termperature_celcius.set(5)

response_time_seconds = Histogram(name='response_time_seconds', 
                                  description='Response time in seconds',
                                  allowed_labels={'path', 'method'},
                                  buckets={0.05, 0.2, 0.3, 0.7, 0.9, 2})


response_time_seconds = LinearHistogram(name='response_time_seconds', 
                                        description='Response time in seconds',
                                        allowed_labels={'path', 'method'},
                                        start=0.5, width=20, count=10)

response_time_seconds = ExponentialHistogram(name='response_time_seconds', 
                                             description='Response time in seconds',
                                             allowed_labels={'path', 'method'},
                                             start=0.5, factor=2, count=10)                            


response_time_seconds.observe(34)


api_http_requests_total::method="POST",handler="/messages"
0

仪表化

api_http_requests_total::method="POST",handler="/messages"
1

主要用例是计数或计时。

我们提供了一个简单的decorator,可用于计算方法调用。

它可用于计数器和仪表。

api_http_requests_total::method="POST",handler="/messages"
2

也可以使用常规decorator并提供度量作为输入参数。

api_http_requests_total::method="POST",handler="/messages"
3

计时通过metric实例上的decorator或general decorator/context manager完成。

api_http_requests_total::method="POST",handler="/messages"
4

其他特殊的测试用例可以使用度量上的正常函数来构建。

检测django

在 负载平衡器/反向代理。

我们主要想在外部应用程序中插入一些内容。

注册表应该在它自己的模块中,并导入到\uu in it\uu中,以便由 默认设置(类似于芹菜的设置)

通过在寄存器上创建一个调用transfer()的中间件类 当响应返回时,我们可以使用管道和 更新所有受影响的指标探索.

仪器瓶

类似于Django。

注册表可能作为扩展名,因此可以保存在全局应用程序上下文中。

transfer()在请求后使用烧瓶运行装饰器。

检测芹菜任务

通过创建一个可以包装普通任务decorator的新decorator,这是可能的 在运行任务时添加检测功能。 任务在注册表上运行calltransfer()之后。 还可以添加芹菜特有的指标作为任务执行时间, 内存消耗等

说明

因为redis中的格式是预定义的,所以可以用 任何语言。包含在库中的是一个非常简单的exposition客户端。 然后可以在例如django视图中返回来自客户端的结果。 客户端只知道它应该收集的名称空间,并使用 redis中的hgetall命令。

度量可以在您正在检测的web应用程序中公开,或者 可以设置一个单独的webapp,用于演示,也可以公开 多个命名空间(应用程序)。这样,scraping就与应用程序分离了 并且可以相应地缩放。

更改日志

格式基于保持更改日志:https://keepachangelog.com/en/1.0.0/,本项目遵循语义版本控制:https://semver.org/spec/v2.0.html。未发布

添加

更改

已弃用

删除

已修复

安全性

v0.0.1(2019-08-20)

计数器、量表和汇总表的初步实施

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Room SQLite如何创建SELECT返回1对象?   java将多个XML元素添加到同一个类中   具有固定数量子项的java CardView   用于在聊天应用程序中加载消息的java JavaFx ListView   java Firebase实时数据库和身份验证库版本不兼容   java修复HashMap中的ClassCastException   java自定义侦听器/接口在Android中不起作用   java如何只更改TextView的背景alpha而不是整个视图?   switch语句Java逻辑错误第十位小数未显示   java如何将ListAdapter中创建的视图添加到数组   我的应用程序中的java ANR问题   在Java中完全打开枚举会产生“缺少返回语句”错误   java如果链表中存储的对象不可克隆,如何创建链表的深度副本?   java Android:将网站表读入表/列表视图