Sentry: 错误日志集中管理

Sentry是个很好用的错误日志服务器,可以将程序错误的详细情况集中捕获,并提供一个很漂亮的Web界面来浏览错误。 Sentry本身是用python写的,但它支持python、php、ruby、iOS等多种语言。

要使用Sentry,你需要一台服务器来运行Sentry服务器,然后需要在代码中插入Sentry客户端的代码。服务器安装方法如下:

$ sudo pip install sentry

目前(2013/1/22)安装过程中可能会发生找不到某些依赖的情况,比如无法安装Django-1.4.3等, 可能需要手工下载Django-1.4.3的代码、编译安装后再重新执行上述命令。

我遇到的另一个问题是,代码使用的是django-1.3,而sentry要求django-1.4,而且我打算在应用服务器上运行sentry, 所以不得不使用virtualenv来安装sentry。

装好之后需要使用以下命令建立配置文件:

$ mkdir ~/.sentry
$ sentry init ~/.sentry/sentry.conf.py

然后打开~/.sentry/sentry.conf.py,按照需要修改。我在SENTRY_WEB_OPTIONS中加了一项daemon: True, 使sentry以daemon模式运行。

然后启动sentry服务器即可。

$ sentry start

执行该命令会让你输入管理帐号和密码。

用浏览器访问 http://localhost:9000/,即可看到sentry的Web界面。登录之后建立一个项目,然后即可配置客户端。 对于使用django框架的项目,客户端可以如下配置:

$ sudo pip install raven       # 如果项目和sentry位于不同服务器,可能需要安装raven

打开django的settings.py,加入:

SENTRY_DSN = 'xxxxxxx'         # 在sentry的Web界面中建立项目后即可查看
                               # for django的配置文档,从中可以找到`SENTRY_DSN`的值
INSTALLED_APPS = {
    ....
    'raven.contrib.django',    # 加入这一行
    ....
}

这样django项目中产生的异常就都会集中到sentry服务器上了。

如果不想自己搭建sentry服务器,还可以使用官方提供的服务,价格也不算太高。

robotframework + selenium实现网站自动测试

本文参考:How to use RobotFramework with the Selenium Library

先来介绍下背景。Selenium是个强大的自动化测试工具,可以手工编写或自动录制测试脚本,可以手工执行,也可以自动执行。而robotframework是个通用的自动化测试框架。 robotframework-seleniumlibrary是robotframework的一个测试库,它可以集成Selenium,并提供一套简单易懂的语法用于书写测试用例(好处就是测试人员不用学任何编程语言也能写测试用例了)。

用这套工具能实现:

  • 无需学习编程语言即可编写测试脚本
  • 自动点击网站链接、输入文字、点击按钮、验证结果
  • 可以放在cron里每日自动执行
  • 自动生成测试报告
  • 对于fail的测试用例,保存输出结果并截图

下面是配置方法。操作系统用的是Ubuntu 12.04。

Continue reading

[iOS]制作native-like的webapp时的一些要点

当用户tap一个页面元素时,iOS会在元素周围显示橙色的外框,以表明该元素被tap了。如果你想自己实现tap时的响应效果,可以用以下方法“去除”这个高亮效果。(来源)

-webkit-tap-highlight-color: rgba(0,0,0,0);  

禁止用户选择页面文字:(来源)

-webkit-user-select: none;

如果你响应onclick事件,会发现click事件有大约半秒的延迟,这是因为iOS需要等待一段时间来判断用户是点击还是拖动。如想去掉这个延迟,可以用ontouchstart代替onclick:(来源)

$(".button").bind("touchstart", handler);

但这样在桌面浏览器中鼠标点击操作就不要用了。没关系,可以做一下判断。

if ('ontouchstart' in window) {
    // mobile version
    $(".button").bind("touchstart", handler);
} else {
    // desktop version
    $(".button").bind("click", handler);
}

禁止用户拖动页面:(来源

document.ontouchstart = function(e){ 
    e.preventDefault(); 
}

一些其他的信息:这里

Posted in web

Tags: , , ,

Permalink 1 Comment

cufon,在网页上画出特殊字体

设计师们有时会使用特殊字体让网页更好看,但浏览器通常只支持Arial、Helvetica等通用字体。那么通常的解决办法就是将特殊字体做成图片。如果要动态生成文字内容怎么办?那也许只有使用CSS3的@font-face功能了……等下!其实还有cufon这个工具,可以帮我们在网页上”画”出特殊字体。

cufon的原理是将TTF字体转换成JavaScript代码,然后在需要特殊字体的地方创建一个<canvas>元素,将字体画出来。效果如下:

cufon的效果

使用方法也很简单,只需访问cufon,点击Download下载cufon-yui.js(目前版本为1.09i)。再点击Generator,上传你的字体文件,即可得到转换后的js文件(假设文件名为yourfont.font.js)。

然后在代码里引入这两个js文件,再写一点简单的代码:

<head>
<script src="cufon-yui.js"></script>
<script src="yourfont.font.js"></script>
<script>
Cufon.replace('h1', { color: '#333', textShadow: '2px 2px #ddd' });
</script>
</head>

这样h1的内容就被替换成了所需的字体。

更详细的讨论可以参考使用Cufon渲染网页字体

将Google Web Fonts保存成TTF

Google Web Fonts上有许多精美的字体,不过只能通过网页引用。有时页面设计需要使用这些字体,那么怎样才能把它们保存成TTF呢?

首先,访问Google Web Fonts,找到所需的字体。可以利用左侧的Search功能迅速找到字体。

搜索字体

然后点字体下面的”Quick-use”链接。

Quick-use

在Quick-Use界面找到第三步”3. Add this code to your website:”,复制代码中的链接,然后开个新的浏览器窗口,打开这个链接:

打开CSS链接

链接打开后就会看到下面的代码:

@font-face {
  font-family: 'Electrolize';
  font-style: normal;
  font-weight: 400;
  src: local('Electrolize'), local('Electrolize-Regular'), url(http://themes.googleusercontent.com/static/fonts/electrolize/v2/DDy9sgU2U7S4xAwH5thnJ7rIa-7acMAeDBVuclsi6Gc.woff) format('woff');
}

最后的url()中的链接就是字体文件,将它粘贴到新的浏览器窗口中即可下载。

如果字体文件扩展名为woff,那么需要将其转换为TTF。去Google搜索”woff to ttf”能找到很多这种工具,如Convert woff to otf

Posted in web

Tags: , ,

Permalink 2 Comments

使用django+celery+RabbitMQ实现异步执行

RabbitMQ大家应该不陌生,著名的消息队列嘛。可惜我最近才听说它的大名,了解之后不禁惊呼,世界上居然还有这种东西! 立刻觉得手里有了锤子,就看什么都是钉子了,主网站不愿意干的操作统统扔给RabbitMQ去做吧 :D

言归正传,先介绍一下这篇文章的应用场景吧。我们知道大型网站的性能非常重要,然而有时不得不做一些相当耗时的操作。 比如SNS网站的“新鲜事儿”系统,我发帖之后,会给所有关注我的人推送一条通知。乍一看没什么难的,发帖之后找出关注我的人, 然后生成相应的消息记录就行了。但问题是,100个人关注我,就要执行100条INSERT查询,更要命的是,Web服务器是同步的, 这100条查询执行完成之前,用户是看不到结果的。

怎么办呢,这时就轮到消息队列上场了。发帖之后只需给队列发送一条消息, 告诉队列“我发帖子了”,然后把发帖的结果返回给用户。 这时另一个叫做worker的进程会取出这条消息并执行那100条INSERT查询。这样,推送通知的操作在后台异步执行, 用户就能立即看到发帖结果。更精彩的是,可以运行多个worker实现分布式,多繁重的任务都不在话下了。

好了,来看看今天的主角:

  • django:web框架,其实只能算作配角了;
  • RabbitMQ:消息队列系统,负责存储消息;
  • celery:worker进程,同时提供在webapp中创建任务的功能。

django-celery-rabbitmq-intro-1.png

Continue reading

[CakePHP]如何关闭API页面的调试信息

注:本文使用的CakePHP版本为 1.2.3.8166。

使用CakePHP开发时,免不了要将调试级别设置为2, 这样页面上会显示出执行的SQL语句及结果,很方便。 但在做API页面时就比较麻烦。一般API页面的输出结果是XML或者JSON格式, 如果后面多了些调试信息,客户端就无法正确解析了。

解决方法很简单,只要在API的action函数中改写调试等级即可:

function api_index() {
  ...
  Configure::write('debug', 0);
}

不过,每个action都要写这么一行,太麻烦了。能不能想个办法,自动地关闭所有API页面的调试信息? Continue reading

Posted in web

Tags: , ,

Permalink 5 Comments

《创建高可用性的Web内容》勘误表

谢谢fcicq指出书中的一些错误。也请其他读者在发现错误后告诉我,如果这本书有幸重印,我会在重印时改正这些错误的。给大家阅读带来不便,真是对不起。

P3,倒数第2段第3行: 用户想把音量调低,但我却没有把它设置到一个较高的音量,以便用户能通过软件来控制它。 修改为: 音箱的音量太小了,我根本没想到应该把音量调大些,这样用户才能通过软件来控制音量。

P5,最后两行: 以及如何进行高可用性的开发。 修改为: 以及如何开始符合高可用性的开发。

P37,“试一试”的第一行: 什么沟通障碍可能会阻碍项目创建高可用性? 修改为: 什么样的沟通障碍可能会阻碍项目创建高可用性?

P57,第2段第4行 请习惯这个思维。 修改为: 拥有这种想法很重要。

如何在下载文件名中使用UTF-8编码

通过把Content-Type设置为application/octet-stream, 可以把动态生成的内容当作文件来下载,相信这个大家都会。 那么用Content-Disposition设置下载的文件名, 这个也有不少人知道吧。 基本上,下载程序都是这么写的:

< ?php
$filename = "document.txt";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $filename);

print "Hello!";
?>

这样用浏览器打开之后,就可以下载document.doc。

但是,如果$filename是UTF-8编码的,有些浏览器就无法正常处理了。 比如把上面那个程序稍稍改一下:

< ?php
$filename = "中文 文件名.txt";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $filename);

print "Hello!";
?>

把程序保存成UTF-8编码再访问,IE6下载的文件名就会乱码。 FF3下下载的文件名就只有“中文”两个字。Opera 9下一切正常。

Continue reading

Posted in web

Tags:

Permalink 2 Comments

Web通信分析工具

在抓虾上看到一篇Web开发分析工具的文章(链接就免了),怎么远没有我用的东西好用呢? 还是介绍介绍我用的吧。由于平常开发只用FireFox,完成后再去调试IE, 所以这些工具绝大部分是针对FireFox的。

如果把Web通信从上到下分为许多层——XMLHttpRequest层,HTTP层,TCP层, 那么这些工具可以分别抓取每个层的通信数据进行分析,结合使用极其强大。

2008/12/31:另外可以参考daniel同学的Web开发常用工具一文,相信会大有帮助哦。

Continue reading

Posted in web

Tags: , ,

Permalink 9 Comments

分类目录

文章归档