С ростом ажиотажа вокруг баз данных документов, и в частности вокруг MongoDB, у нас возникает много вопросов о том, как люди должны перенести свои приложения на его использование. Совет обычно один и тот же — особенно для существующих приложений — делайте один шаг за раз. С учетом вышесказанного мы хотели бы продемонстрировать то, что мы считаем отличным местом для начала: использование MongoDB для регистрации ошибок.
MongoDB отлично подходит для ведения журналов (и, конечно, других вещей) по многим причинам. С одной стороны, это очень ОЧЕНЬ быстро для записи данных. Он может выполнять записи асинхронно; Ваше приложение не зависнет, потому что ваши процедуры регистрации заблокированы. Это позволяет вам централизовать ваши журналы, что облегчает поиск по ним проблем. Кроме того, с его интерфейсом запросов легко работать и он очень гибкий. Вы можете выполнять запросы к любым именам полей или выполнять агрегатные функции либо с помощью карты / редукции, либо будущей структуры агрегации MongoDB 2.2.
Эта статья покажет, как вы можете использовать существующий код, чтобы добавить библиотеку журналов в ваш код и регистрировать ошибки в MongoDB. Вы также узнаете, как запрашивать MongoDB из командной строки и как фильтровать эти запросы, чтобы найти интересующую вас информацию.
Настройка Logger
Прежде чем написать класс ведения логов MongoDB для PHP, мы быстро взглянули на то, что там уже было, и нашли на GitHub хороший инструмент для микролога под названием Analog . Чтобы не изобретать велосипед, мы будем использовать это в наших примерах.
Что нам действительно понравилось в Analog, так это простота его кода и количество вещей, в которые вы можете войти! Он разработан для расширения, поэтому вы сможете легко встраивать в себя все, что вам может понадобиться для вашего собственного проекта.
Регистратор достаточно Analog.php
, поэтому все, что вам нужно сделать, чтобы сделать его доступным, это включить его основной файл Analog.php
. Это заботится о автозагрузке и регистрации пространства имен, необходимых для поиска зависимостей. Так как он использует spl_autoload_register()
, он будет счастливо сосуществовать с любыми другими механизмами автозагрузки, которые у вас уже есть.
Чтобы начать использовать регистратор, вам нужно инициализировать обработчик журналирования, который вы хотите использовать, и затем передать его основному классу журналирования. Есть несколько примеров, включенных в проект, которые позволяют легко увидеть, что вам нужно для конкретной платформы. Для MongoDB у нас есть следующее:
<?php Analog::handler(AnalogHandlerMongo::init( "localhost:27017", "testing", "log"));
Все, что нам нужно сделать, это указать Analog на нашу установку MongoDB (наша находится на той же машине, что и веб-сервер и использует порт по умолчанию), указать ему использовать testing
базу данных и записать в коллекцию log
. С этим, который включен где-то в верхней части нашего скрипта, возможно, наряду с различными другими задачами начальной загрузки, мы готовы к работе.
Ошибки регистрации
На данный момент мы можем использовать функциональность регистрации в любом месте, где мы хотим, в нашем приложении. Чтобы зарегистрировать ошибку, просто выполните:
<?php Analog::log("Oh noes! Something went wrong!");
Чтобы увидеть, что находится в базе данных, откройте оболочку Монго.
Лорна @ Тайгет: ~ $ Монго типа "помощь" для помощи > использовать тестирование > db.log.find (); {"_id": ObjectId ("4f268e9dd8562fc817000000"), "machine": "localhost", "date": "2012-02-29 11:11:16", "level": 3, "message": "Oh noes ! Что-то пошло не так!" }
Как видите, это дает нам сообщение об ошибке, серьезность, дату и время создания ошибки и машину, с которой она возникла. Идентификатор машины берется из $_SERVER["SERVER_ADDR"]
если он установлен, в противном случае используется «localhost».
Уровни регистрации
Аналоговая библиотека поставляется с большим набором констант, которые вы можете использовать для установки уровня каждой ошибки. Вот фрагмент из класса, показывающий их:
<?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 ...
По умолчанию используется уровень 3 для обозначения ошибки. Чтобы записать ошибку любого другого уровня, передайте нужный уровень в качестве второго параметра методу log()
:
<?php Analog::log("FYI, a log entry", Analog::INFO);
Теперь, посмотрев в базу данных, мы узнаем, как будет расти наша коллекция сообщений журнала.
> db.log.find (); {"_id": ObjectId ("4f268e9dd8562fc817000000"), "machine": "localhost", "date": "2012-02-29 11:11:16", "level": 3, "message": "Oh noes ! Что-то пошло не так!" } {"_id": ObjectId ("4f268e9dd8562fc817000001"), "machine": "localhost", "date": "2012-02-29 12:35:41", "level": 6, "message": "FYI, запись в журнале "}
Хотя (как и во всех журналах) в реальном приложении мы будем создавать большой набор данных, используя базу данных, мы можем легко генерировать сводную информацию или фильтровать данные, чтобы найти только важные записи.
Фильтрация и суммирование журналов MongoDB
Использование хранилища базы данных означает возможность поиска результатов, а MongoDB разработан для удобства использования разработчиками даже с большими наборами данных. Дни grep’ing огромных журналов плоских файлов прошли! Мы можем очень легко отфильтровать данные, чтобы показать только то, что нам интересно.
> db.log.find ({level: 3}); {"_id": ObjectId ("4f268e9dd8562fc817000000"), "machine": "localhost", "date": "2012-02-29 11:11:16", "level": 3, "message": "Oh noes ! Что-то пошло не так!" }
В базе данных также есть записи более высокого уровня, поскольку у нас много разных уровней ведения журнала. Чтобы показать все с серьезностью ошибки и выше (более низкая константа уровня ошибки), мы можем запросить с оператором $lte
:
> db.log.find ({level: {$ lte: 3}}); {"_id": ObjectId ("4f268e9dd8562fc817000000"), "machine": "localhost", "date": "2012-02-29 11:11:16", "level": 3, "message": "Oh noes ! Что-то пошло не так!" } {"_id": ObjectId ("4f26aaafd8562fcb27000009"), "machine": "localhost", "date": "2012-02-29 13:01:04", "level": 0, "message": "К спасательные шлюпки!» }
Мы также можем искать диапазоны дат, например, используя сравнение $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": "Пустая переменная $ a на линии 127 "} {"_id": ObjectId ("4f26aaafd8562fcb2700000b"), "machine": "localhost", "date": "2012-02-29 14:35:35", "level": 4, "message": "Пустая переменная $ a на линии 93 "} {"_id": ObjectId ("4f26aaafd8562fcb2700000c"), "machine": "localhost", "date": "2012-02-29 14:35:40", "level": 4, "message": "Пустая переменная $ a на линии 277 "} {"_id": ObjectId ("4f26aaafd8562fcb2700000d"), "machine": "localhost", "date": "2012-02-29 14:35:45", "level": 6, "message": "FYI, кажется, идет снег "}
Если вы обычно запрашиваете данные в определенном поле, вы можете ускорить свои запросы, добавив индекс. Например, если вы часто делаете запрос по level
и дате, вы можете создать составной индекс:
> db.log.ensureIndex ({дата: -1, уровень: 1});
Приведенная выше строка создаст один индекс, если он еще не существует. Однако здесь стоит отметить пару вещей. Во-первых, мы поместили date
первой, так как она будет иметь наибольшее отклонение, и, следовательно, индекс будет наиболее полезен. Мы также создали date
в качестве обратного индекса, поскольку мы обычно запрашиваем самые последние записи. Во-вторых, мы добавили level
как часть индекса. Этот составной индекс сделает любой запрос по дате и любой запрос по date
и level
более эффективным. Он не сможет использоваться для запросов только на level
а не на date
.
Иногда вам захочется посмотреть общие тенденции в ваших журналах, поэтому вы сгруппируете, сколько именно ошибок происходит. В этом примере мы сгруппировали ошибку, установленную по уровню ошибки, чтобы показать, сколько их каждого:
> db.log.group ({ключ: {уровень: истина}, начальный: {количество: 0}, уменьшить: функция (объект, пред.) {пред. счет ++}}); [ { "Уровень 3, "считать": 1 }, { «уровень»: 6, "считать": 4 }, { «уровень»: 4, "считать": 8 }, { «уровень»: 0, "считать": 1 } ]
Вы можете использовать функцию group()
для подсчета ошибок за день или с определенного компьютера, как вы пожелаете. Будьте осторожны, так как этот подход полезен только для небольших наборов данных. Если у вас есть более 10000 результатов, вы можете использовать карту / уменьшить для получения результатов.
Резюме
Имеет смысл начать с малого, если посмотреть на добавление MongoDB в существующее приложение, и ведение журнала является идеальным кандидатом. Различные типы ошибок могут включать в себя различные типы информации, и вы также можете сохранить текущий объект или любую другую информацию в MongoDB, поскольку она имеет гибкую схему. Любая новая технология может быть чем-то вроде кривой обучения, но, надеюсь, примеры командной строки помогут вам довольно близко подойти к тому, над чем вы работаете. Внедрение всего лишь одной функциональности во что-то новое может стать отличным способом намочить ноги — надеюсь, вам понравится MongoDB так же, как и нам!
Изображение с помощью mama-art / Shutterstock