【Sentry使用】自定义transaction

44 篇文章 0 订阅
9 篇文章 1 订阅

在使用Sentry时,你会发现有两种颜色的柱形图,一个是紫色的,在上面;一个是灰色的,在下面。这两类柱形图分别代表error和transaction,而在Python脚本环境下,不会自动进行transaction的记录,也就是说只会在出现异常时进行记录,而正常情况不会。
在这里插入图片描述
这时就要了解一下Sentry的transaction创建逻辑

  • 自动
  • 手动

首先是自动
在这里插入图片描述
在使用一些框架的情况下会自动创建,官方给出了这些框架的列表

  • 基于WSGI的web框架,比如Django、Flask、Pyramid、Falcon、Bottle等
  • Celery
  • AIOHTTP web 应用
  • Redis Queue

spans就是在一个transaction中对下列类型操作的记录

  • 使用SQLAlchemy或者Django ORM对数据库进行检索
  • 使用requests或者stdlib进行HTTP请求
  • Spawn方式创建的子进程
  • Redis操作

以下面的一个爬虫transaction为例,可以看到spans记录的有http请求以及db操作,而数据处理的部分则是没有记录,显示为‘Missing instrumentation’
在这里插入图片描述
如何将这些‘Missing instrumentation’变为自定义的呢?

from sentry_sdk import Hub

def process_item(item):
    transaction = Hub.current.scope.transaction
    # omitted code...
    with transaction.start_child(op="http", description="GET /") as span:
        response = my_custom_http_library.request("GET", "/")
        span.set_tag("http.status_code", response.status_code)
        span.set_data("http.foobarsessionid", get_foobar_sessionid())

参考:https://sentry-docs-git-sentry-ruby-40.sentry.dev/platforms/python/performance/#:~:text=op%20and%20description.-,Python,-Copied
如果想在span中创建span

from sentry_sdk import Hub

def process_item(item):
    parent_span = Hub.current.scope.span
    # omitted code...
    with parent_span.start_child(op="http", description="GET /") as span:
        response = my_custom_http_library.request("GET", "/")
        span.set_tag("http.status_code", response.status_code)
        span.set_data("http.foobarsessionid", get_foobar_sessionid())

参考:https://sentry-docs-git-sentry-ruby-40.sentry.dev/platforms/python/performance/#:~:text=tree%20of%20spans%3A-,Python,-Copied

那么如何手动创建transaction呢?
其实,上图中的transaction就是通过手动创建的

from sentry_sdk import start_transaction

while True:
  item = get_from_queue()

  with start_transaction(op="task", name=item.get_transaction_name()):
      # process_item may create more spans internally (see next examples)
      process_item(item)

这种就适合于那种没有使用框架的Python脚本使用

参考:
https://docs.sentry.io/platforms/python/performance/instrumentation/automatic-instrumentation/
https://docs.sentry.io/platforms/python/performance/instrumentation/custom-instrumentation/


根据官方说明
status用来计算failure_rate,而failure_rate表示不成功事务的百分比。 Sentry 将状态不是“ok”、“cancelled”和“unknown”的事务视为失败。
我们看到,所有自定义transaction的状态都是unknown
在这里插入图片描述
如果想将其改为’ok’,可以将status参数设置为’ok’

with start_transaction(op='xxxx', name='xxxx', status='ok') as transaction:
    ...
    ...

在这里插入图片描述
参考:https://develop.sentry.dev/sdk/event-payloads/span/


首先是希望在多进程中使用,根据官方说明写出了如下代码:

# main.py
from sentry_sdk import start_transaction
from multiprocessing import Process
import zhuo
import long

with start_transaction(op='xxxx', name='xxxx', status='ok') as transaction:
    p1 = Process(target=zhuo.main)
    p2 = Process(target=long.main)
    p1.start()
    p2.start()
    p1.join()
    p2.join()
# zhuo.py
import sentry_sdk

transaction = sentry_sdk.Hub.current.scope.transaction

def main():
    with transaction.start_child(op="zhuo"):
        ...
        ...
# long.py
import sentry_sdk

transaction = sentry_sdk.Hub.current.scope.transaction

def main():
    with transaction.start_child(op="long"):
        ...
        ...

但是报错

AttributeError: 'NoneType' object has no attribute 'start_child'

也就是说

transaction = sentry_sdk.Hub.current.scope.transaction

总是为None
所以就将代码改为如下:

# main.py
from sentry_sdk import start_transaction
from multiprocessing import Process
import zhuo
import long

with start_transaction(op='xxxx', name='xxxx', status='ok') as transaction:
    p1 = Process(target=zhuo.main, args=(transaction, ))
    p2 = Process(target=long.main, args=(transaction, ))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
# zhuo.py
import sentry_sdk

def main(transaction: sentry_sdk.tracing.Transaction):
    with transaction.start_child(op="zhuo"):
        ...
        ...
# long.py
import sentry_sdk

transaction = sentry_sdk.Hub.current.scope.transaction

def main(transaction: sentry_sdk.tracing.Transaction):
    with transaction.start_child(op="long"):
        ...
        ...

但这时又报错

Traceback (most recent call last):
  File "main.py", line 6, in <module>
    process.start()
  File "/usr/local/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/process.py", line 121, in start
    self._popen = self._Popen(self)
  File "/usr/local/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "/usr/local/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/context.py", line 284, in _Popen
    return Popen(process_obj)
  File "/usr/local/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 32, in __init__
    super().__init__(process_obj)
  File "/usr/local/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_fork.py", line 19, in __init__
    self._launch(process_obj)
  File "/usr/local/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 47, in _launch
    reduction.dump(process_obj, fp)
  File "/usr/local/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_thread.RLock' object

原因是transaction无法被pickle序列化,解决思路是将transaction的构建放在目标函数中,这里只传Python自身的数据类型。但问题是transaction无法重新构建,每个进程必须要传入同一个transaction对象,故暂时无法解决。

参考:
https://blog.csdn.net/weixin_43064185/article/details/103213823
https://stackoverflow.com/questions/44144584/typeerror-cant-pickle-thread-lock-objects

多进程不行就改为多线程试试

# main.py
from sentry_sdk import start_transaction
from threading import Thread
import zhuo
import long

with start_transaction(op='xxxx', name='xxxx', status='ok') as transaction:
    p1 = Thread(target=zhuo.main, args=(transaction, ))
    p2 = Thread(target=long.main, args=(transaction, ))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
# zhuo.py
import sentry_sdk

def main(transaction: sentry_sdk.tracing.Transaction):
    with transaction.start_child(op="zhuo"):
        ...
        ...
# long.py
import sentry_sdk

transaction = sentry_sdk.Hub.current.scope.transaction

def main(transaction: sentry_sdk.tracing.Transaction):
    with transaction.start_child(op="long"):
        ...
        ...

一切正常了

transaction = sentry_sdk.Hub.current.scope.transaction

依旧为None
可以看到zhuo与long中的所有http请求以及数据库操作均被记录下来
所以这种方式仅适用于调试阶段,如果数据量过大,可能造成sentry服务器崩溃
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sentry和Ranger是CDH中常用的细粒度授权管理工具,下面分别介绍它们的使用方法: 1. Sentry使用 (1)安装和配置Sentry 首先需要在CDH集群中安装和配置Sentry服务。具体安装和配置步骤可以参考CDH文档中的说明。 (2)创建角色和授权 可以使用Sentry提供的命令行工具或Web界面来创建角色和授权。例如,以下命令可以创建一个名为“finance_analyst”的角色,并将其授权访问表“my_table”: ``` $ sentry --command create-role --role finance_analyst $ sentry --command grant --role finance_analyst --privilege "server=server1->db=my_database->table=my_table->action=select" ``` (3)验证授权 创建角色和授权之后,可以使用授权用户的身份来验证授权是否生效。例如,可以使用以下命令来验证用户“user1”是否可以访问表“my_table”: ``` $ beeline -u jdbc:hive2://localhost:10000 -n user1 -e "select * from my_table" ``` 2. Ranger的使用 (1)安装和配置Ranger 首先需要在CDH集群中安装和配置Ranger服务。具体安装和配置步骤可以参考CDH文档中的说明。 (2)创建策略和条件 可以使用Ranger提供的Web界面来创建策略和条件。例如,可以创建一个策略,仅允许特定用户访问表“my_table”。在创建策略时,可以指定访问条件,例如“user=user1”。 (3)验证授权 创建策略之后,可以使用授权用户的身份来验证授权是否生效。例如,可以使用以下命令来验证用户“user1”是否可以访问表“my_table”: ``` $ beeline -u jdbc:hive2://localhost:10000 -n user1 -e "select * from my_table" ``` 综上所述,Sentry和Ranger的使用方法都比较简单,可以根据实际需求选择合适的工具来管理Hive数据表的访问权限。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值