postgresql-extensions-logging-and-exceptions/

Хотелось бы продолжить рассказ о расширениях PostgreSQL и поговорить о логировании и исключениях. Рассматривать их нужно вместе, поскольку в PostgreSQL это связанные механизмы. Хотя ранее мы уже и использовали макрос elog() , тема была затронута лишь поверхностно.

Большую часть того, что нужно знать о логировании и исключениях, можно почерпнуть из файла src/include/utils/elog.h в исходном коде PostgreSQL.

В простейшем случае логирование осуществляется при помощи elog():

int64 now = ( int64 ) GetCurrentTransactionStartTimestamp ( ) ;
elog ( NOTICE , «Transaction start timestamp: %lld» , ( long long ) now ) ;

Форматирование практически такое же, как в обычном printf(), но с некоторыми отличиями. Например, можно написать %m , и это будет аналогично строке, возвращаемой strerror(errno) . Дополнительных аргументов для %m передавать не нужно. Для форматирования 64-х битных чисел можно воспользоваться %lld или %llu . Чтобы это правильно работало, соответствующие аргументы нужно явно преобразовать в long long или unsigned long long соответственно. Все подробности касаемо форматированного вывода в PostgreSQL можно найти в файле src/port/snprintf.c .

Есть разные уровни логирования — DEBUG5…DEBUG1, INFO, NOTICE, WARNING, ERROR, FATAL, PANIC и другие. Они ведут себя по-разному. Например, NOTICE отображается в пользовательской сессии, но по-умолчанию не пишется в лог-файл. ERROR бросает исключение (о них ниже) и отменяет исполнение текущей транзакции. FATAL приводит к завершению работы текущего процесса, а PANIC останавливает работу всей СУБД. Подробнее о всех существующих уровнях логирования можно прочитать в elog.h.

Отображаемый уровень логирования бывает удобно изменить в рамках сессии, например, для отладки. Сделать это можно так:

SET client_min_messages TO debug1;

Что пишется в лог-файл определяется настройками, описанными в разделе Error Reporting and Logging документации.

Макрос elog() определен, как обвязка над ereport():

#define elog(elevel, …)  
ereport(elevel, errmsg_internal(__VA_ARGS__))

В новом коде рекомендуется использовать именно ereport(). Типичный пример:

const char * arg = TextDatumGetCString ( PG_GETARG_DATUM ( 0 ) ) ;
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( «Invalid argument » %s «» «» arg )
errhint ( «»This is a hint message.»» ) ) ) ;

Указывать errhint() не обязательно. Хотя использовать elog() и не рекомендуется в новом кодеиногда он полезен. Например

Похожая запись

EnglishRussianUkrainian