关于Sentry(转)
原文:http://blog.csdn.net/largetalk/article/details/8640854
1. Sentry介绍及使用
Sentry is a realtime event logging and aggregation platform. At its core it specializes in monitoring errors and extracting all the information needed to do a proper post-mortem without any of the hassle of the standard user feedback loop.
Sentry 是一个实时事件日志记录和汇集的平台。其专注于错误监控以及提取一切事后处理所需信息而不依赖于麻烦的用户反馈。
1.1 Sentry介绍
无论测试如何完善的程序,bug总是免不了会存在的,有些bug不是每次都会出现,测试时运行好好的代码可能在某个用户使用时就歇菜了,可是当程序在用户面前崩溃时,你是看不到错误的,当然你会说:”Hey, 我有记日志呢”。 但是说实话,程序每天每时都在产生大量的日志,而且分布在各个服务器上,并且如果你有多个服务在维护的话,日志的数量之多你是看不过来的吧。等到某天某个用户实在受不了了,打电话来咆哮的时候,你再去找日志你又会发现日志其实没什么用:缺少上下文,不知道用户什么操作导致的异常,异常太多(从不看日志的缘故)不知如何下手 等等。
Sentry就是来帮我们解决这个问题的,它是一款精致的Django应用,目的在于帮助开发人员从散落在多个不同服务器上毫无头绪的日志文件里发掘活跃的异常,继而找到潜在的臭虫。
Sentry是一个日志平台, 它分为客户端和服务端,客户端(目前客户端有Python, PHP,C#, Ruby等多种语言)就嵌入在你的应用程序中间,程序出现异常就向服务端发送消息,服务端将消息记录到数据库中并提供一个web节目方便查看。Sentry由python编写,源码开放,性能卓越,易于扩展,目前著名的用户有Disqus, Path, mozilla, Pinterest等。
1.3 Sentry权限介绍
Sentry目前用户类型有四种: 超级管理员, 管理员,普通用户和System agents. 超级用户只能通过命令行来创建,其他用户可以自己注册或由其他用户邀请注册加入,然后由超级管理员或管理员分配项目和权限。为了更好支持团队协助以及信息安全,新版本Sentry(5.4.2)经过了重新设计,重新设计后的Sentry以Team为中心组织权限。所谓Team就是一个团队,一些用户组织在一起对某些项目有操作权限的组织。一个项目只能属于一个Team, 一个用户却可以属于多个Team, 并可在不同Team中扮演不同角色, 如用户A在Team X是管理员而在Team Y中是System agents. Sentry对用户角色的指定只能到Team级别,不能到Project级别, 所以将某个用户加入到某个Team之后,这个用户就对所有所有属于这个Team下所有project有了相同的权限。
Sentry的如此设计虽说不够细致,但我们使用时只要遵照现实世界的情况来划分Team和project即可。比如我们目前有一个团队,这个团队负责两个项目,我们在Sentry上就建立一个Team A和属于这个Team的project a和project b. 当在使用过程中我们发现project b的等级较高,不能让所有人都可以看到信息,我们可以建立一个虚拟Team B,然后将project b的team 改Team B, 然后再给Team B添加用户和相应权限即可. Sentry对team的owner, project的owner, project属于的team 等等实体关系的修改都极为简单,没有副作用。
下面简单介绍下Sentry中各个类型用户的权限。
- 超级管理员: 能创建各种用户, team和project只能由超级管理员创建。项目的一些设置比如改变Owner, 数据公开可见与否(设为public的数据可以通过url不登陆也能查看)以及客户端domain限制的设定。另外还有管理项目的api key(客户端只有得到此api key才能向Sentry发送消息)的权限等等。
- 管理员: 能创建用户, team和项目设定中除改变owner之外的权限, 可以对项目中具体数据做resolve, bookmark, public/public和remove操作。
- 普通用户: 无Team界面,只能对项目中具体数据做resolve, bookmark, public/unpublic和remove操作。
- System agents: 无Team界面,只能对项目中具体数据做bookmark, unpublic和remove操作。
此外,还需知晓Sntry中team和project的Onwer概念,只有是team或project的owner(除超级管理员外)才能更改其owner, 一旦成为team或project的Owner,则获得对此team或project如同超级管理员般的权限。
Sentry的权限和实体设置基本可以满足现实的需求:
- 如果一个团队负责多个项目,可以通过一个Team多个项目方式来实现。
- 如果一个人参与多个团队, 可以将该用户添加到多个team中去。
- 一个team或project设置相应的Owner,则可以由此人负责该team或project内的活动。(唯一的缺点是team owner不可以创建project)
- 一个team或项目的分工应该是有一个管理者来设定项目的基本设定,管理api key, 并将api key分发给项目开发者,项目开发者以普通用户身份登陆Sentry查看错误和resolve错误, 运维以System agents身份登陆Sentry查看系统运行状态。
1.4 Sentry性能
有些人担心Sentry会影响程序性能,所以我搭建了一个Sentry服务器做了下测试。
我一共使用了两台机器(机器是HP ProLLiant DL360 G4p)作为服务器, 一台安装了Sentry和Mysql, 一台安装了memcache和redis, 然后在sentry.conf.py里将QUEUE和CACHE都打开。使用supervisor启了三个服务
sentry start http
sentry start udp
sentry celeryd -B
首先测试下直接插入消息的效率如何:
from raven import Client
from timeit import timeit
try:
import cProfile as profile
except ImportError:
import profile
from pstats import Stats client = Client('udp://11c5f6e203cb4b228b2dcac3df29dad2:55adfa2e6d8c4fd799694d8dcde372c3@172.16.97.11:9001/2') def do_capture_msg2():
for i in range(1000):
client.captureMessage(str(i) + 'hello world! from do_capture_msg2') def test(f, number=1000):
time = timeit(f, number=number)
st = Stats(profile.Profile().runctx('f()', globals(), locals()))
print("funcation_name msec rps tcalls funcs")
print("%-11s %6.0f %6.0f %7d %6d" % (f.__name__, 1000 * time, number / time, st.total_calls, len(st.stats))) test(do_capture_msg2, number=10)
测试结果:
funcation_name msec rps tcalls funcs
do_capture_msg2 4093 2 287004 101
我一共提交了10000个消息,共耗时4093ms, 每次消息耗时很少,这里有两个需要注意的地方,一个是我使用的是udp接口,如果使用http接口,这个耗时会增加不少。对于udp的传输非可靠性,我认为在内网环境内应该是基本可靠的,在测试过程中,未发现消息遗漏的情况。另一个需要注意的地方是由于我的服务器性能不高,这10000个消息并不是在这4s中内就被处理完了,而是被记录到任务队列了,所以在服务器可以看到,客户端的请求完成之后,服务器的cpu使用率还需要一段时间才能降下来。
普通消息的提交处理非常快,那对于异常消息又如何:
def do_capture_exc():
try:
1 / 0
except ZeroDivisionError:
client.captureException() test(do_capture_exc, number=1000)
测试结果:
funcation_name msec rps tcalls funcs
do_capture_exc 1061 942 1029 121
略慢,但我估计异常的抛出和捕获才是元凶
下面结合应用程序来测试性能,创建一个django程序,添加一个非常简单的view响应函数:
def sentry(request):
t = random.randint(1, 10)
time.sleep(t/1000.0)
u = User.objects.all()[0]
return HttpResponse('user %s say hello world from django: %sms '%(u.username, t))
启动脚本是:
#!/bin/bash
gunicorn_django -k gevent -w 8 --worker-connections 3000 -b 0.0.0.0:8001 -D
ab测试结果是:
ab -n 1000 -c 100 http://172.16.97.12:8001/
Server Software: gunicorn/0.17.2
Server Hostname: 172.16.97.12
Server Port: 8001 Document Path: /sentry
Document Length: 45 bytes Concurrency Level: 100
Time taken for tests: 2.298 seconds
Complete requests: 1000
Failed requests: 90
(Connect: 0, Receive: 0, Length: 90, Exceptions: 0)
Write errors: 0
Total transferred: 185090 bytes
HTML transferred: 45090 bytes
Requests per second: 435.11 [#/sec] (mean)
Time per request: 229.827 [ms] (mean)
Time per request: 2.298 [ms] (mean, across all concurrent requests)
Transfer rate: 78.65 [Kbytes/sec] received Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.7 0 9
Processing: 16 219 149.6 180 823
Waiting: 16 219 149.6 180 823
Total: 16 219 149.9 180 825
将view函数改为如下:
def sentry(request):
t = random.randint(1, 10)
time.sleep(t/1000.0)
u = User.objects.all()[0]
client.captureMessage('user %s say hello world from django: %sms '%(u.username, t))
return HttpResponse('user %s say hello world from django: %sms '%(u.username, t))
ab测试结果如下:
ab -n 1000 -c 100 http://172.16.97.12:8001/sentry Server Software: gunicorn/0.17.2
Server Hostname: 172.16.97.12
Server Port: 8001 Document Path: /sentry
Document Length: 45 bytes Concurrency Level: 100
Time taken for tests: 3.175 seconds
Complete requests: 1000
Failed requests: 90
(Connect: 0, Receive: 0, Length: 90, Exceptions: 0)
Write errors: 0
Total transferred: 185090 bytes
HTML transferred: 45090 bytes
Requests per second: 314.95 [#/sec] (mean)
Time per request: 317.510 [ms] (mean)
Time per request: 3.175 [ms] (mean, across all concurrent requests)
Transfer rate: 56.93 [Kbytes/sec] received Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 8
Processing: 17 301 225.2 241 1308
Waiting: 17 301 225.2 241 1307
Total: 17 302 225.5 241 1310
1000次请求运行时间从2.298s变为3.175s, rps从435.11降为314.95
1.5 总结
虽然从上面测试看起来,程序效率下降了大概1/4左右,但测试毕竟和实际应用有一些差距,实际运行的应用有更复杂的逻辑,更多的运算和更多的io操作,所以实际上sentry的影响会很小,而带来的好处则很多,并且,Sentry是一个平台级的服务,一旦构建好,所有应用都可以使用受益。
当然,Sentry和log不是相互重叠的东西,他们各有用处,不能把Sentry当做log来使用,大量的网络操作对应用程序来说还是会有影响的。而且有了Sentry后log还是需要的,Sentry在服务器网络异常时会失效,并且业务逻辑的跟踪等等也离不开log。
关于Sentry(转)的更多相关文章
- 通过Cloudera在hadoop生态圈中安装Sentry服务。
写在张文章时,差点辣死我了.把sentry数据库密码搞掉了,导致hive,impala,hue都挂了.此事要引以为戒,以后要小心操作了. 安装Sentry服务 a) 在c ...
- 为CDH 5.7集群添加Kerberos身份验证及Sentry权限控制
转载请注明出处:http://www.cnblogs.com/xiaodf/ 4. 为CDH 5集群添加Kerberos身份验证 4.1 安装sentry1.点击“操作”,“添加服务”:2.选择sen ...
- 搭建sentry(一个分布式日志聚合系统)
简介: Sentry 是一个实时的事件日志和聚合平台,基于 Django 构建. Sentry 可以帮助你将 Python 程序的所有 exception 自动记录下来,然后在一个好用的 UI 上呈现 ...
- Python 实时日志平台 Sentry
原文地址:http://www.oschina.net/p/sentry Sentry 是一个实时的事件日志和聚合平台,基于 Django 构建. Sentry 可以帮助你将 Python 程序的所有 ...
- 使用开源软件sentry来收集日志
原文地址:http://luxuryzh.iteye.com/blog/1980364 对于一个已经上线的系统,存在未知的bug或者运行时发生异常是很常见的事情,随之而来的几点需求产生了: 1.系统发 ...
- Sentry Server 日志记录分析服务
原文地址:http://blog.shanbay.com/archives/998 或许你不太会喜欢异常,特别是那些发生后继而沉默在应用日志里那些,你不知道从何开始,因为它们看起来并非那么平易近人,但 ...
- 安装配置sentry服务
环境 系统环境:Centos6.7 Hadoop版本:CDH5.10 jdk版本:jdk7 注:本文并未集成kerberos组件 安装Sentry Server 选择安装hive的节点进行安装测试: ...
- hive集成sentry
1.安装配置sentry 详细步骤见上一篇安装配置sentry 2.配置hive 2.1 Hive-server2集成Sentry 在 /etc/hive/conf/hive-site.xml中添加: ...
- Centos7通过Docker安装Sentry(哨兵)
Docker介绍 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制, ...
- hive集成sentry的sql使用语法
Sentry权限控制通过Beeline(Hiveserver2 SQL 命令行接口)输入Grant 和 Revoke语句来配置.语法跟现在的一些主流的关系数据库很相似.需要注意的是:当sentry服务 ...
随机推荐
- Pwnium CTF2014 – MatterOfCombination writeup
这道题是虽然只有75分,但是做出来的队伍却很少,我们队伍也没有做出来,这次是看到了0xAWES0ME 的解题思路后才有了这篇文章.原文地址可以点击看这里,英文的. 题目就是一张图片: 在网上可以找到这 ...
- Linux 下用 valgrind 查找内存泄漏小例子
1.安装 valgrind yum install valgrind 2.测试用例 main.cpp #include <iostream> using namespace std; st ...
- Mysql系列二:Mysql 开发标准规范
原文链接:http://www.cnblogs.com/liulei-LL/p/7729983.html 一.表设计 1. 库名.表名.字段名使用小写字母,“_”分割. 2. 库名.表名.字段名不超过 ...
- 【QT】QPixmap和QImage在QLabel显示一张图像
#include <QPixmap> void Dialog::on_Button1_clicked() { QPixmap img; img.load("1.bmp" ...
- dedecms调用日期格式化形式大全
dedecms特有常用的日期格式化函数MyDate() 代码:[field:pubdate function="MyDate('Y-m-d',@me)" /] 样式:2013-08 ...
- mysql按月查询
SELECT DATE_FORMAT(GenerateTime, '%m') as month, SUM(GenerateCount) AS count FROM identitycodetask ' ...
- C#自定义Winform无边框窗体
C#自定义Winform无边框窗体 在实际项目中,WinForm窗体或者控件不能满足要求,所以就需要自己设计窗体等,当然设计界面可以用的东西很多,例如WPF.或者一些第三方的库等.本例中将采用WinF ...
- kettle spoon中“表输入”到“表输出”的乱码问题
数据库中的数据在不同的数据库中转换来装换去,由于不同库可能使用了不同的字符集,所以可能导致结果数据乱码问题.此次是在一个作业中跑数据,跑完数据前台数据显示出现乱码,检查了作业中的多有中间过程表,包括表 ...
- 使用mui.js实现下拉刷新
闲聊: 最近因公司项目需求,小颖需要写一些html5页面,方便公司IOS和Android给APP中嵌套使用,其中需要实现拉下刷新功能,其实就是调用了一下mui.js就可以啦嘻嘻,下面跟着小颖一起来看看 ...
- [IOI 2000]POJ 1160 Post Office
Post Office Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22278 Accepted: 12034 Descrip ...