当前位置: 首页 > 工具软件 > Analog PHP > 使用案例 >

使用MongoDB和Analog进行错误记录

田冥夜
2023-12-01

With the hype around document databases continuing to grow, and around MongoDB in particular, we get a lot of questions about how people should move their applications over to using it. The advice is usually the same – especially for existing applications – take one step at a time. With that said, we’d like to show off what we consider to be an excellent place to start: using MongoDB for error logging.

随着围绕文档数据库,尤其是围绕MongoDB的炒作持续增长,我们对人们应该如何将其应用程序转移到使用它方面提出了很多疑问。 建议通常是相同的-尤其是对于现有应用程序-一次只采取一个步骤。 话虽如此,我们想炫耀我们认为是一个很好的起点:使用MongoDB进行错误记录。

MongoDB is an excellent fit for logging (and of course other things as well) for many reasons. For one, it is very VERY fast for writing data. It can perform writes asynchronously; your application wont hang because your logging routines are blocked. This allows you to centralize your logs which makes it easier to querying against them to find issues. Also, its query interface is easy to work with and is very flexible. You can query against any of the field names or perform aggregate functions either with map/reduce or MongoDB 2.2’s upcoming aggregation framework.

由于许多原因,MongoDB非常适合记录日志(当然还有其他东西)。 一方面,写入数据非常快。 它可以异步执行写操作; 您的应用程序不会挂起,因为您的日志记录例程已被阻止。 这使您可以集中化日志,从而更轻松地查询日志以发现问题。 而且,其查询界面易于使用且非常灵活。 您可以查询任何字段名称,也可以使用map / reduce或MongoDB 2.2即将推出的聚合框架执行聚合功能。

This article will show how you can use existing code to add a logging library to your code and log errors to MongoDB. You’ll also see how to query MongoDB from the command line and how to filter those queries to find the information you are interested in.

本文将展示如何使用现有代码将日志记录库添加到代码中并将错误记录到MongoDB。 您还将看到如何从命令行查询MongoDB,以及如何过滤这些查询以查找您感兴趣的信息。

设置记录仪 (Setting Up The Logger)

Before writing a MongoDB logging class for PHP, we took a quick look to see what else was out there already and found a nice micrologging tool on GitHub called Analog. In the interest of not reinventing the wheel, we’ll use this in our examples.

在为PHP编写MongoDB日志记录类之前,我们快速浏览了一下那里是否还有其他东西,并在GitHub上找到了一个不错的微日志记录工具,称为Analog 。 为了不重新发明轮子,我们将在示例中使用它。

What we really liked about Analog is the simplicity of its code and the number of things you can log to! It’s designed to be extensible, so you should be able to easily build on in to anything specific you may need for your own project.

我们真正喜欢Analog的地方在于其代码的简单性和可登录的事物数量! 它的设计具有可扩展性,因此您应该能够轻松构建自己项目中可能需要的任何特定内容。

The logger is fairly self-contained, so all you’ll need to do to make its functionality available is to include its main file Analog.php. This takes care of the autoloading and namespace registration needed for it to find its dependencies. Since it uses spl_autoload_register(), it will happily co-exist alongside any other autoloading arrangements you already have in place.

记录器是完全独立的,因此您需要做的就是使其功能可用,包括其主文件Analog.php 。 这照顾了它查找依赖项所需的自动加载和名称空间注册。 由于它使用spl_autoload_register() ,它将很高兴与您已经存在的任何其他自动加载安排共存。

To start using the logger, you’ll need to intialize the logging handler you want to use and then pass it to the main logging class. There are some examples included with the project which makes it easy to see what you need for a specific platform. For MongoDB, we have the following:

要开始使用记录器,您需要初始化要使用的记录处理程序,然后将其传递给主记录类。 该项目包含一些示例,可以轻松查看特定平台的需求。 对于MongoDB,我们具有以下内容:

<?php
Analog::handler(AnalogHandlerMongo::init(
	"localhost:27017",
	"testing",
	"log"));

All we have to do here is to point Analog at our MongoDB installation (ours is on the same machine as the web server and uses the default port), tell it to use the testing database, and write to the log collection. With this included somewhere at the top of our script, probably along with various other bootstrapping tasks, we’re ready to go.

我们要做的就是将Analog指向我们的MongoDB安装(我们与Web服务器位于同一台计算机上,并使用默认端口),告诉它使用testing数据库,然后写入log集合。 在脚本顶部的某个位置(包括其他一些引导任务)中,我们已经准备就绪。

记录错误 (Logging Errors)

At this point we can use the logging functionality anywhere we want it in our application. To log an error, simply do:

此时,我们可以在应用程序中任何需要的地方使用日志记录功能。 要记录错误,只需执行以下操作:

<?php
Analog::log("Oh noes! Something went wrong!");

To see what’s in the database, open the mongo shell.

要查看数据库中的内容,请打开mongo shell。

lorna@taygete:~$ mongo
type "help" for help
> use testing
> db.log.find();
{ "_id" : ObjectId("4f268e9dd8562fc817000000"), "machine" : "localhost", "date" : "2012-02-29 11:11:16", "level" : 3, "message" : "Oh noes! Something went wrong!" }

As you can see this gives us the error message, the severity, the date and time that the error was created, and the machine from which it came. The machine identifier comes from $_SERVER["SERVER_ADDR"] if set, otherwise “localhost” is used.

如您所见,这将向我们提供错误消息,严重性,创建错误的日期和时间以及产生错误的计算机。 机器标识符来自$_SERVER["SERVER_ADDR"]如果已设置),否则使用“ localhost”。

记录级别 (Logging Levels)

The Analog library comes with a great set of constants that you can use to set the level of each error. Here’s a snippet from the class to showing them:

模拟库带有大量常量,可用于设置每个错误的级别。 这是课堂上的片段以展示它们:

<?php
...
class Analog {
    /**
     * List of severity levels.
     */
    const URGENT   = 0; // It's an emergency
    const ALERT    = 1; // Immediate action required
    const CRITICAL = 2; // Critical conditions
    const ERROR    = 3; // An error occurred
    const WARNING  = 4; // Something unexpected happening
    const NOTICE   = 5; // Something worth noting
    const INFO     = 6; // Information, not an error
    const DEBUG    = 7; // Debugging messages
...

The default is level 3 to denote an error. To log an error of any other level, pass the desired level as a second parameter to the log() method:

默认值为3级,表示错误。 要记录任何其他级别的错误,请将所需级别作为第二个参数传递给log()方法:

<?php
Analog::log("FYI, a log entry", Analog::INFO);

Looking in the database now, we can how our log messages collection will grow.

现在查看数据库,我们可以了解日志消息收集的增长方式。

> db.log.find();
{ "_id" : ObjectId("4f268e9dd8562fc817000000"), "machine" : "localhost", "date" : "2012-02-29 11:11:16", "level" : 3, "message" : "Oh noes! Something went wrong!" }
{ "_id" : ObjectId("4f268e9dd8562fc817000001"), "machine" : "localhost", "date" : "2012-02-29 12:35:41", "level" : 6, "message" : "FYI, a log entry" }

Although (as with all logs) in a real application we’ll be building up a large set of data, using a database means we can easily generate summary information or filter the data to find only the important entries.

尽管在真实的应用程序中(与所有日志一样),我们将建立大量数据,但是使用数据库意味着我们可以轻松地生成摘要信息或过滤数据以仅查找重要条目。

过滤和汇总MongoDB日志 (Filtering And Summarizing MongoDB Logs)

Using database storage means the ability to search results, and MongoDB is designed to be easy for developers to use even with large datasets. The days of grep’ing enormous flat-file logs are over! We can very easily filter the data to show only what we’re interested in.

使用数据库存储意味着可以搜索结果,MongoDB的设计目的是使开发人员即使对于大型数据集也易于使用。 复制大量平面文件日志的时代已经结束! 我们可以很容易地过滤数据以仅显示我们感兴趣的内容。

> db.log.find({level: 3});
{ "_id" : ObjectId("4f268e9dd8562fc817000000"), "machine" : "localhost", "date" : "2012-02-29 11:11:16", "level" : 3, "message" : "Oh noes! Something went wrong!" }

There are some higher-level entries also in the database since we have many different levels of logging. To show everything of error severity and above (a lower error level constant), we can query with the operator $lte:

由于我们有许多不同级别的日志记录,因此数据库中也存在一些更高级别的条目。 为了显示所有错误严重性及以上(错误级别常数较低)的所有内容,我们可以使用运算符$lte进行查询:

> db.log.find({level: {$lte: 3}});
{ "_id" : ObjectId("4f268e9dd8562fc817000000"), "machine" : "localhost", "date" : "2012-02-29 11:11:16", "level" : 3, "message" : "Oh noes! Something went wrong!" }
{ "_id" : ObjectId("4f26aaafd8562fcb27000009"), "machine" : "localhost", "date" : "2012-02-29 13:01:04", "level" : 0, "message" : "To the lifeboats!" }

We can also look for date ranges, for example, using a $gt comparison to pull the most recent few log entries from my database:

我们还可以查找日期范围,例如,使用$gt比较从我的数据库中提取最近的几个日志条目:

> db.log.find({date: {$gt: "2012-02-29 14:35:30"}});
{ "_id" : ObjectId("4f26aaafd8562fcb2700000a"), "machine" : "localhost", "date" : "2012-02-29 14:35:31", "level" : 4, "message" : "Empty variable $a on line 127" }
{ "_id" : ObjectId("4f26aaafd8562fcb2700000b"), "machine" : "localhost", "date" : "2012-02-29 14:35:35", "level" : 4, "message" : "Empty variable $a on line 93" }
{ "_id" : ObjectId("4f26aaafd8562fcb2700000c"), "machine" : "localhost", "date" : "2012-02-29 14:35:40", "level" : 4, "message" : "Empty variable $a on line 277" }
{ "_id" : ObjectId("4f26aaafd8562fcb2700000d"), "machine" : "localhost", "date" : "2012-02-29 14:35:45", "level" : 6, "message" : "FYI, it seems to be snowing" }

If you commonly query data on a particular field, you can speed up your queries by adding an index. For example, if you frequently query on level and date you can create a compound index:

如果您通常在特定字段上查询数据,则可以通过添加索引来加快查询速度。 例如,如果您经常查询level和日期,则可以创建一个复合索引:

> db.log.ensureIndex({ date : -1, level : 1 } );

The above line will create a single index if it doesn’t already exist. There’s a couple things worth noting here, however. First, we placed date first as it will have the largest variation and therefore the index will do the most good. We also created date as a reverse index as we commonly want to query for the most recent entries. Secondly, we added level as part of the index. This compound index will make any query on date and any query on date and level more efficient. It will not be able to be used for queries on just level and not date.

上面的行将创建一个索引(如果尚不存在)。 但是,这里有两点值得注意。 首先,我们将date放在第一位,因为它变化最大,因此索引将发挥最大作用。 我们还希望将date创建为反向索引,因为我们通常要查询最新的条目。 其次,我们将level添加为索引的一部分。 该复合索引将使对日期的任何查询以及对datelevel任何查询都更加高效。 它不能仅用于level查询,而不能用于date查询。

Sometimes you’ll want to look for overall trends in your logs, so you’ll group how many of a particular error happens. In this example, we’ve grouped the error set by the error level to show how many there are of each:

有时,您可能希望在日志中查找整体趋势,因此可以对发生特定错误的次数进行分组。 在此示例中,我们按错误级别对错误集进行了分组,以显示每个错误集的数量:

> db.log.group({key: {level: true}, initial: {count: 0}, reduce: function (obj, prev){prev.count++}});
[
    {
        "level" : 3,
        "count" : 1
    },
    {
        "level" : 6,
        "count" : 4
    },
    {
        "level" : 4,
        "count" : 8
    },
    {
        "level" : 0,
        "count" : 1
    }
]

You can use the group() function to count errors per day, or from a particular machine, as you so choose. Do take care though as this approach is only useful on small data sets. If you have over 10,000 results then you’ll want to use map/reduce to generate the results.

您可以选择使用group()函数每天或从特定计算机上计数错误。 请务必小心,因为这种方法仅对小型数据集有用。 如果结果超过10,000,则需要使用map / reduce生成结果。

摘要 (Summary)

It makes sense to start small when looking at adding MongoDB to an existing application, and logging is an ideal candidate. Different types of errors can include different types of information and you can also save the current object or any other information to MongoDB since it has a flexible schema. Any new technology can be a bit of a learning curve but hopefully the command line examples help you to get quite close to what you are working on. Implementing just one piece of functionality in something new can be a great way to get your feet wet – hope you enjoy MongoDB as much as we do!

在考虑将MongoDB添加到现有应用程序时,从小处着手是有意义的,并且日志记录是理想的选择。 不同类型的错误可能包含不同类型的信息,您还可以将当前对象或任何其他信息保存到MongoDB,因为它具有灵活的架构。 任何新技术都可能有点学习困难,但希望命令行示例可以帮助您非常接近所从事的工作。 在新事物中仅实现一项功能可能是使您立足的好方法–希望您能像我们一样享受MongoDB!

Image via mama-art / Shutterstock

图片来自mama-art / Shutterstock

翻译自: https://www.sitepoint.com/error-logging-with-mongodb-and-analog/

 类似资料: