Привязка приложения log4net к условному выбору свойств для определенного поля

У меня есть общий проект ведения журнала, который использует log4net для записи событий журнала. Поскольку это обычный проект, он настроен нестандартно: почти все настраивается через код C #.

Теперь у меня есть приложение AdoNet, настроенное таким образом, что включает в себя регистрацию метода, вызвавшего событие журнала. Он создается как часть инициализации журнала и определяется следующим образом:

appender.AddParameter(new AdoNetAppenderParameter()
{
    ParameterName = "@Method",
    DbType = DbType.String,
    Size = 255,
    Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%method")) as IRawLayout
});

Поскольку я привязываю к свойству log4net %method, это автоматически извлечет имя метода, вызвавшего событие регистрации, и отправит его в базу данных в параметре с именем @Method, который в конечном итоге будет вставлен в таблицу базы данных со столбцом с именем Method.

Однако я добавляю некоторые новые функции для глобальной обработки исключений и их регистрации. Когда исключение всплывает из любого места в верхнюю часть стека вызовов, оно будет передано этому новому глобальному методу, чтобы его можно было зарегистрировать. У меня есть доступ к исключению, поэтому я могу видеть контроллер и метод, вызвавшие это исключение. Я мог бы легко добавить это как настраиваемое свойство log4net (сопоставленное с чем-то вроде %property{ExceptionMethod}). Моя проблема заключается в переопределении (или перезаписи) свойства %method log4net моим собственным настраиваемым свойством.

Итак, как я могу настроить log4net на условный выбор между %method и %property{ExceptionMethod} при отправке данных через приложение AdoNet для регистрации этой информации в столбце Метод моей таблицы базы данных журналов? Это вообще возможно?


person Ellesedil    schedule 20.02.2015    source источник


Ответы (2)


Не зная точно, как вы конфигурируете и используете log4net, сложно написать код, который впишется в вашу существующую структуру: хотя в этом примере создаются два приложения, одно из которых использует %method, а другое использует %property{ExceptionMethod}, и назначает их разным регистраторам:

public abstract class BaseAppender : AdoNetAppender
{
    protected BaseAppender()
    {
        // Add common parameters, set connection strings etc

        // e.g.
        this.AddParameter(new AdoNetAppenderParameter
        {
            ParameterName = "@log_level",
            DbType = DbType.String,
            Size = 50,
            Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%level")) as IRawLayout
        });

        // Then ask each subclass to add the extra parameters
        this.AddExtraParameters();
    }

    protected abstract void AddExtraParameters();
}

public class RuntimeAppender : BaseAppender
{
    protected override void AddExtraParameters()
    {
        this.AddParameter(new AdoNetAppenderParameter
        {
            ParameterName = "@Method",
            DbType = DbType.String,
            Size = 255,
            Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%method")) as IRawLayout
        });
    }
}

public class UnhandledExceptionAppender : BaseAppender
{
    protected override void AddExtraParameters()
    {
        this.AddParameter(new AdoNetAppenderParameter
        {
            ParameterName = "@Method",
            DbType = DbType.String,
            Size = 255,
            Layout =
                new RawLayoutConverter().ConvertFrom(new PatternLayout("%property{ExceptionMethod}")) as IRawLayout
        });
    }
}

public sealed class RuntimeLogger : Logger
{
    public RuntimeLogger(string name)
        : base(name)
    {
        this.Appenders.Add(new RuntimeAppender());
        this.Level = Level.Error; // etc
    }
}

public sealed class UnhandledExceptionLogger : Logger
{
    public UnhandledExceptionLogger(string name)
        : base(name)
    {
        this.Appenders.Add(new UnhandledExceptionAppender());
        this.Level = Level.Error; // etc
    }
}

Затем во время выполнения вы выбираете, что использовать:

public class ExceptionHandler
{
    public void HandleException(Exception ex)
    {
        string exceptionMethod = "set exception method here" ; 
        GlobalContext.Properties["ExceptionMethod"] = exceptionMethod;

        var logger = new UnhandledExceptionLogger("Logger Name Goes Here");
        logger.Log(Level.Error, "Message", ex);
    }
}

public class RuntimeLogging
{
    public void LogSomething(Exception ex)
    {
        var logger = new RuntimeLogger("Logger Name Goes Here");
        logger.Log(Level.Error, "Message", ex);
    }
}   
person stuartd    schedule 24.02.2015
comment
Это, конечно, возможно. Что бы это ни стоило, я решил просто добавить второй столбец, сопоставленный с %property{ExceptionMethod} (хотя я его переименовал). Но если бы я действительно хотел избежать второго столбца метода, который содержал бы много null записей, я бы, вероятно, воспользовался этим решением. - person Ellesedil; 24.02.2015

В зависимости от ваших потребностей вам может быть проще реализовать AdoNetAppender полностью в коде.

Есть по крайней мере один способ сделать это, который я нашел в моем предыдущем ответе здесь.

person InteXX    schedule 24.02.2015
comment
Пожалуйста, не копируйте код другого ответа. Также это не отвечает на вопрос. - person stuartd; 24.02.2015
comment
@stuartd: Хм, я скопировал его только для того, чтобы быть полезным ... так что OP (и другие читатели) могли сэкономить немного времени, не просматривая. Не одобряют ли такого рода помощь? Если я отредактирую код, чтобы удалить его, это вдохновит вас на то, чтобы вернуть отрицательный голос? ;-) ОП: Итак, как можно условно выбрать log4net ... Мой ответ точно отвечает на этот вопрос. Напишите код для условного выбора рисунка. Вы уверены, что я не ответил на вопрос? - person InteXX; 24.02.2015
comment
Он не отвечает на вопрос, потому что OP должен использовать разные значения параметров method во время выполнения - ваш код загружает один DBAppender, у которого вообще нет параметра метода. Также обратите внимание, что OP заявил, что почти все [в конфигурации log4net] уже установлено через код C #. - person stuartd; 24.02.2015
comment
@stuartd: Боже правый, это не так! Я почти уверен, что мой код можно реорганизовать для выполнения этой задачи, но мне пришлось бы протестировать его, прежде чем утверждать, что он работает (естественно). Так как насчет того, чтобы изменить / проголосовать против? - person InteXX; 24.02.2015
comment
@stuartd: Спасибо :-) Я был на Meta, читал о отрицательных голосах ... Думаю, многим новичкам (например, мне) трудно не воспринимать их слишком лично. Полагаю, все это часть обучения ТАК. - person InteXX; 24.02.2015
comment
@stuartd: Ваш комментарий к OP - это решение, и я бы этим занялся. Мне любопытно; почему бы не добавить его сюда в качестве ответа? - person InteXX; 24.02.2015
comment
@stuartd: Теперь это я могу понять! Хорошо, я оставлю вас работать ... спасибо за вашу помощь. - person InteXX; 24.02.2015
comment
Как уже упоминалось, я уже делаю это. Кроме того, в этом ответе не рассматривается, как выбрать одно свойство над другим во время выполнения. - person Ellesedil; 24.02.2015
comment
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - person David says Reinstate Monica; 24.02.2015
comment
Это не дает ответа на вопрос. Чтобы критиковать или запрашивать разъяснения у автора, оставьте комментарий под его сообщением. - person Jonathan Nixon; 24.02.2015
comment
@DavidGrinberg: Спасибо за указатель - я знал об этом, но по подсказке Стюарта я все равно решил отредактировать его до ответа только для ссылки, поскольку ссылка указывает на другую страницу в SO. Ссылки на страницы SO должны быть в порядке, да? - person InteXX; 24.02.2015
comment
@Guthwulf: Спасибо - как вы можете видеть в этих комментариях, я сначала подумал, что это так, но после подсказки Стюарта я присмотрелся и увидел, что это не так. Вы считаете, что мне следует удалить ответ и эту ветку комментариев? - person InteXX; 24.02.2015
comment
@Ellesedil: Похоже, Стюарт нашел это для вас; вы захотите пойти с его ответом. После некоторого обсуждения с ним я понял, что мой код вам не подойдет. В конце концов, я бы сделал то же самое, что и он. - person InteXX; 25.02.2015