记录到数据库而不是日志文件

Posted

技术标签:

【中文标题】记录到数据库而不是日志文件【英文标题】:Log to database instead of log files 【发布时间】:2010-11-12 17:48:00 【问题描述】:

我有兴趣将所有 Rails 应用程序日志记录发送到数据库(mysql 或 MongoDB),作为日志文件的补充或替代。有几个原因,其中大部分与日志文件分析有关。我们已经在使用 Google Analytics,但是我们想做的很多事情在 Analytics 中并不可行。

此外,我想通过查看日志对问题进行“实时”调查。筛选日志文件是一种乏味的方法,我想比日志文件(容易)允许的更好的搜索和过滤。

最后,我经常想检查一些更接近网站访问者行为的东西:例如跟踪通过网站的路径,这样我就可以看到用户在发生错误之前查看的最后一页是什么。鉴于我们有多个应用服务器,单独的日志文件让这非常痛苦。如果所有数据都在数据库中,那么我可以很容易地看到给定访问者的正确页面顺序。我知道 Syslog 将是解决这个特定问题(单个日志文件/存储库)的一种方法,但我想将它与我与数据库搜索相关联的更好的搜索能力结合起来。

我想知道人们推荐什么来解决这个问题。您是直接登录到数据库,还是将日志文件转储到数据库中(但是您的方法是什么,以便它本质上是实时的/与日志文件本身一样最新)?

我目前正在确定我希望此日志记录的级别,因为我看到的另一件事是编写一个小型 Rack 过滤器来记录所有请求。这会错过正常 Rails 日志转储的所有额外输出(缓存命中和未命中的所有 SQL 和输出等),但它会实现我目标的很大一部分,并且似乎具有不干扰的优势系统中的任何其他内容。

无论如何,我不是在寻找一个正确的答案,而是更多地讨论和了解其他人在同样的情况下可能会做什么。

【问题讨论】:

只是好奇,Rails 应用程序日志记录有什么特别之处?是否类似于 Web 访问日志注册请求?还是您的意思是实际的应用程序逻辑? 参见下面的 cmets:我对应用程序级别的日志记录更感兴趣,但这不是完全必需的,但我也不想记录由网络服务器。我们使用 Hoptoad 进行异常记录/通知,这是一个很好的解决方案。我的问题实际上是对其他人实施的解决此或类似需求的要求/调查。 作为对此的更新,最近我一直在尝试使用 Papertrail。他们有一个非常简单的设置,可以将您的日志文件(Rails、nginx 或任何类型的日志文件)实时导入他们的系统,然后进行全文搜索。它看起来很有希望。他们仍处于私人测试阶段,但肯定有希望。 Loggly 也有潜力,但我发现它很慢,而且我无法正确地将多行日志消息输入其中(可能只是我做错了,但我在他们的支持论坛上也没有得到任何答复) . Graylog2 和 logstash 看起来也可以。 【参考方案1】:

如果您想更改默认的日志记录行为,只需创建一个响应所有 Rails 记录器方法的自定义记录器对象:

添加 调试、警告、错误、信息、致命、未知

http://github.com/rails/rails/blob/9d7aae710384fb5f04129c35b86c5ea5fb9d83a9/activesupport/lib/active_support/buffered_logger.rb

因为它是你的记录器,你可以决定实现你的个人逻辑。 您可以随时写入数据库,写入标准输出。

然后,为您要自定义的每个基类替换默认记录器。

ActiveRecord::Base.logger = YouLogger.new

您可以轻松创建一个名为 logger.rb 的初始化程序文件,并在其中写入所有自定义配置。这样,在 Rails 启动时,logger 将立即被替换。

【讨论】:

谢谢。我应该提到我知道该选项,但对其他人也有很好的说明。大多数情况下,我很好奇其他人是如何做到这一点的,他们做了什么选择等等。例如,如果你这样做,速度/性能有什么问题 - 你如何保持数据库连接等等(如果你是的话),或者什么不是。 这正是我一直在寻找的,除了ActiveRecord::Base.logger(我使用 Mongoid 而不是数据库的活动记录)之外,还有哪些其他记录器可以替换? 如果这可能对某人有所帮助,在 Rails 4 中我所要做的就是在初始化程序中替换 Rails.logger【参考方案2】:

克里斯,

我认为 Dima 的评论在这里很重要。您是否对 (1) 在数据库中拥有访问日志(实时),或者 (2) 您对 Rails/应用程序特定的日志记录更感兴趣?

对于 (1),使用 Apache(至少),您可以使用管道日志记录到数据库。

http://httpd.apache.org/docs/1.3/logs.html#piped

我编写了一个在后台运行的程序,等待输入,它解析并记录到 Postgres 数据库。我的 httpd.conf 文件使用 CustomLog 指令连接到该程序。

这设置起来相对简单,并为您提供了能够在数据库中分析日志的所有明显优势。它对我来说效果很好,尤其是在跟踪用户在错误之前所做的事情时。但是,您必须防止 sql 注入、缓冲区溢出和日志记录程序中的其他安全问题。

对于 (2),我不是 Rails 开发人员,所以我只能谈论一般方法。如果您想记录环境变量、应用程序数据或非常有选择性的信息,您可以考虑编写一个 Web 服务器模块。根据您的具体需求,您还可以在日志程序中结合使用条件日志指令和过滤。

这真的取决于您是需要特定于 Rails 的解决方案还是更通用的 Web 服务器范围的解决方案。

【讨论】:

我们不使用 Apache(使用 Nginx),但这是一个好点。我追求更接近 Rails 日志的东西,因为我想要应用程序级别的日志记录,而不是 Web 服务器日志。我不关心对图像和 CSS 等的所有请求,我宁愿使用特定于应用程序的日志记录而不是 URL。这确实意味着我需要在 Rails 级别进行日志记录(因为即使在 Rack 级别它仍然只是 URL,尽管它会筛选出由 Nginx 提供的静态资产),但是为了速度等,我可能需要在机架级别进行。【参考方案3】:

我的公司一直在将一些结构化的流量信息直接记录到 MySQL 日志数据库中。该数据库在下游复制到另一个数据库。所有分析都运行最终的数据库复制。我们的网站维持了相当多的流量。到目前为止,它似乎没有任何重大问题。但是,我们的 IT 部门越来越担心当前设置的可扩展性,并建议我们将日志信息卸载到“适当的”日志文件中。然后将日志文件重新插入到相同的下游数据库表中。这让我想到了这个问题。 :)

以下是我看到的关于日志文件与日志数据库(关系)主题的一些优缺点:

日志文件快速、可靠且可扩展(至少我听说雅虎大量使用日志文件进行点击跟踪分析)。 日志文件易于系统管理员维护。 日志文件可以非常灵活,因为您几乎可以向其中写入任何内容。 日志文件需要大量解析,并且可能需要一种减少映射的设置类型以进行数据提取。 log-db 结构更接近您的应用程序,从而缩短了某些功能的周转时间。这可以是祝福,也可以是诅咒。从长远来看,这可能是一个诅咒,因为您很可能最终会得到一个高度耦合的应用程序和分析代码库。 log-db 可以减少日志记录噪音和冗余,因为日志文件仅在 log-db 使您能够进行更新和关联插入(如果您敢于进行标准化)的地方插入。 如果您使用数据库分区和/或多日志数据库(通过下游复制重新加入数据),log-db 也可以快速且可扩展

我认为在我的情况下需要对日志数据库进行一些压力测试。这样至少我知道我有多少净空。

最近,我一直在研究一些基于键值/文档的数据库,例如 Redis、Tokyo Cabinet 和 MongoDB。这些快速插入的数据库可能是最佳选择,因为它们在不同程度上提供了持久性、高(写入)吞吐量和查询能力。它们可以使数据提取过程比通过大量日志文件解析和减少映射更简单。

从长远来看,我认为拥有强大的分析数据仓库至关重要。将应用程序数据从分析数据中解放出来,反之亦然,这可能是一个巨大的胜利。


最后,我想指出 *** 上有许多类似/密切相关的问题,以防您想扩大讨论范围。

Storage of many log files Is writing server log files to a database a good idea? Using a SQL Server for application logging. Pros/Cons? Fast Search in Logs Separate production database for logging You Log to Your DB, Where Do You Log When Your DB is Down?

编辑:

rsyslog 看起来很有趣。它使您能够直接写入 MySQL。如果您使用的是 Ruby,则应该查看日志记录 gem。它提供多目标日志记录功能。这太好了。

【讨论】:

感谢以上。我自己一直在研究 MongoDB,这就是我现在所倾向于的。我需要解决的最重要的事情实际上是如何将数据输入其中。即我是否定期解析日志文件,从而使我的应用程序保持不变(这很好),但使事情变得相当困难(解析 Rails 日志输出可能会很痛苦(也许?)。或者,我是否编写自己的 Rails 记录器来发送到当前日志(所以我仍然会定期记录文件,以防 MongoDB 出现问题),以及写入 Mongo 或其他解决方案等。【参考方案4】:

由于到目前为止没有人接受任何答案,我会贡献我的贡献

我确实为 rsylog 开发了一个插件来将日志保存在文件中而不是在 mongodb 中

完整的源代码,来自 rsyslog + 插件在这里https://github.com/vpereira/rsyslogd-mongo

要编译它,您只需运行 ./configure --help 并查看可用选项。

【讨论】:

【参考方案5】:

最近我自己犯了登录数据库的错误,我觉得我可以提供一个非常好的理由来说明你不应该这样做:事务。假设你开始一个事务,在事务过程中记录一堆东西,最终你会遇到一个错误情况。您记录错误情况,哦,嘿。 ROLLBACK。突然间,您刚刚记录的所有内容都消失了,您不知道发生了什么或为什么。

尤其是在 Rails 的上下文中,像 AASM 这样真正有用的库会将一大堆东西包装在一个事务中,你可能会在你认为不会的地方结束事务,这也使得问题变得非常很难调试。

就我而言,我将内容记录到数据库的原因是我需要上下文相关的日志。本质上,我需要能够查找与特定数据库模型相关的所有日志条目。但是,正确的答案是将这些日志放在更适合日志数据的单独位置(在我的情况下,恰好是可查询的)。

【讨论】:

以上是关于记录到数据库而不是日志文件的主要内容,如果未能解决你的问题,请参考以下文章

日志文件的作用及功能

使用Fluentd进行日志记录 - 为什么json日志文件的输出显示为textpayload(而不是jsonpayload)?

优雅记录log4j日志

将日志消息存储在数据库表而不是文件中是好还是坏?

将 Node 的“永久”日志记录到 syslog

sqlserver的日志问题