Журналирование (логирование) результатов операций в СУБД
Журналирование результатов операций в СУБД необходимо в двух случаях.
-
Чтобы обеспечить журналирование операций внутри транзакции, т.е. запись в журнале (лог)е формируется только в случае реального изменения основной операцией базы данных;
-
Чтобы обеспечить внутри приложения возможность просмотра истории работы с объектом или истории общих операций, например вход в приложение.
Структура таблицы журналирования
/** Логирование */
CREATE TABLE Log
(
id VARCHAR(50) NOT NULL PRIMARY KEY,
/** Тип действия: login, logout, update_user_info, create_qt, create_mt, finish_qt, finish_mt, change_roles, login_on_behalf */
type VARCHAR(30) NOT NULL,
/** Дополнительное описание события */
description TEXT,
/** Идентификатор объекта, с которым происходит событие */
object_id VARCHAR(100),
/** Базовый инициатор операции */
originator_sid VARCHAR(100) NOT NULL,
/** Пользователь, от имени которого и с правами которого выполняется действие */
user_sid VARCHAR(100) NOT NULL,
/** Дата и время совершения действия */
timestamp DATETIME NOT NULL DEFAULT GETDATE(),
/** Успешность операции */
result BIT DEFAULT TRUE
);
Процедура логирования
public static void writeDbLog(@NotNull CallContext context, @NotNull UserInfo userInfo, @NotNull Action action,
@NotNull String objectId, String description, @NotNull boolean result) {
try (LogCursor logCursor = new LogCursor(context)) {
logCursor
.setId(UUID.randomUUID().toString())
.setType(action.label)
.setOriginatorSid(userInfo.getSid())
.setUserSid(userInfo.getSid())
.setOriginatorSid(userInfo.getOriginatorSid())
.setObjectId(objectId)
.setDescription(description)
.setTimestamp(new Date())
.setResult(result)
.insert();
log.info(description);
} catch (CelestaException e) {
log.error(e);
}
}
Примеры видов действий
public enum Action {
LOGIN("Login"),
LOGOUT("Logout"),
UPDATE_USER_INFO("Update user info"),
DELETE_USER_INFO("Delete user info"),
CHANGE_ROLES("Change roles"),
LOGIN_ON_BEHALF("Login on behalf"),
public final String label;
Action(String label) {
this.label = label;
}
}
Вызов журналирования
if (userCursor.tryUpdate()) {
Logger.writeDbLog(context, userInfo, Action.UPDATE_USER_INFO, (userSid != null ? userSid : userInfo.getSid()), "Обновление данных пользователя", true);
return getUser(context, userInfo, (userSid != null ? userSid : userInfo.getSid()));
} else {
throw new St2ApiException("Could not update user data");
}