Как я могу изменить расположение файла программно?
Я совершенно новичок в Log4net.
Мне удалось что-то сделать, добавив файл конфигурации и простое ведение журнала.
Я жестко задать значение "C:templog.txt" но этого недостаточно.
журналы должны идти в специальные папки
path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
и этот путь изменяется в зависимости от того, используете ли Вы Windows Server 2008 или Windows XP или Vista и т. д...
как я могу просто изменить расположение файла в log4net программно?
вот что я сделал:
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="C:templog.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%-5p%d{yyyy-MM-dd hh:mm:ss} – %m%n" />
</layout>
</appender>
</log4net>
class Program
{
protected static readonly ILog log = LogManager.GetLogger(typeof(Program));
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
log.Warn("Log something");
path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
// How can I change where I log stuff?
}
}
просто нужно выяснить, как я могу изменить, чтобы войти вещи, где я хочу.
какие предложения?
Большое спасибо
10 ответов:
log4net может справиться с этим для вас. Любое свойство appender типа string может быть отформатировано, в данном случае, с помощью log4net.Утиль.PatternString обработчик вариант. PatternString даже поддерживает SpecialFolder перечисление, которое включает следующую элегантную конфигурацию:
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" > <file type="log4net.Util.PatternString" value="%envFolderPath{CommonApplicationData}\test.txt" /> ... </appender>вот модульный тест, который доказывает пудинг:
[Test] public void Load() { XmlConfigurator.Configure(); var fileAppender = LogManager.GetRepository() .GetAppenders().First(appender => appender is RollingFileAppender); var expectedFile = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.CommonApplicationData), "test.txt"); Assert.That(fileAppender, Is.Not.Null & Has.Property("File").EqualTo(expectedFile)); }следующий тест проверяет, что log4net фактически записывает на диск (что в основном делает это тест" интеграция", а не единичный тест, но мы оставим это на данный момент):
[Test] public void Log4net_WritesToDisk() { var expectedFile = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.CommonApplicationData), "test.txt"); if (File.Exists(expectedFile)) File.Delete(expectedFile); XmlConfigurator.Configure(); var log = LogManager.GetLogger(typeof (ConfigTest)); log.Info("Message from test"); LogManager.Shutdown(); Assert.That(File.ReadAllText(expectedFile), Text.Contains("Message from test")); }NB: я настоятельно рекомендую использовать синтаксис компактного свойства, показанный в приведенном выше примере. Удаление всех этих "
Я нашел мутацию этого кода в паутине:
XmlConfigurator.Configure(); log4net.Repository.Hierarchy.Hierarchy h = (log4net.Repository.Hierarchy.Hierarchy) LogManager.GetRepository(); foreach (IAppender a in h.Root.Appenders) { if (a is FileAppender) { FileAppender fa = (FileAppender)a; // Programmatically set this to the desired location here string logFileLocation = @"C:\MySpecialFolder\MyFile.log"; // Uncomment the lines below if you want to retain the base file name // and change the folder name... //FileInfo fileInfo = new FileInfo(fa.File); //logFileLocation = string.Format(@"C:\MySpecialFolder\{0}", fileInfo.Name); fa.File = logFileLocation; fa.ActivateOptions(); break; } }это работает для меня. Наше приложение должно поместить файл журнала в папку, содержащую номер версии приложения на основе AssemblyInfo.cs-файл.
вы должны быть в состоянии установить logFileLocation программно (например, вы можете использовать сервер.MapPath (), если это веб-приложение) в соответствии с вашими потребностями.
выглядит так:Петровская Не работает для Log4net v1.2.10.0. Описан альтернативный метод здесь.
в основном метод заключается в реализации пользовательского преобразователя шаблонов для файла конфигурации log4net.
Сначала добавьте этот класс в свой проект:
public class SpecialFolderPatternConverter : log4net.Util.PatternConverter { override protected void Convert(System.IO.TextWriter writer, object state) { Environment.SpecialFolder specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), base.Option, true); writer.Write(Environment.GetFolderPath(specialFolder)); } }затем установите параметр File вашего FileAppender следующим образом:
<file type="log4net.Util.PatternString"> <converter> <name value="folder" /> <type value="MyAppName.SpecialFolderPatternConverter,MyAppName" /> </converter> <conversionPattern value="%folder{CommonApplicationData}\SomeOtherFolder\log.txt" /> </file>в основном
%folderговорит ему, чтобы посмотреть на конвертер называетсяfolderчто указывает на класс SpecialFolderPatternConverter. Затем он вызываетConvertв этом классе, передавая значение перечисления CommonApplicationData (или что-то еще).
Как насчет простого:
XmlConfigurator.LogFullFilename = @"c:\ProgramData\MyApp\Myapp.log";почему так сложно сделать действительно простую вещь?
это сработало для меня:
<log4net> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> .. <file value="${APPDATA}\MyApp\MyApp Client\logs\Log.txt"/> .. </log4net>Если вам нужно написать в специальные папки, я нашел помощь здесь (2-й и 3-й пример).
Edit:
чтобы ответить OP.. Это работает для области "все пользователи":
... <file value="${ALLUSERSPROFILE}\MyApp\MyApp Client\logs\Log.txt"/> ...что обычно "C:\ProgramData" в более новых версиях Windows.
Смотрите эти тоже:
Как указать общую папку данных приложения для log4net? == https://stackoverflow.com/a/1889591/503621 и комментарии
&
https://superuser.com/q/405097/47628
https://stackoverflow.com/a/5550502/503621
чтобы также изменить путь журнала ошибок (на основе ответа JackAce):
private static void SetLogPath(string path, string errorPath) { XmlConfigurator.Configure(); log4net.Repository.Hierarchy.Hierarchy h = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository(); foreach (var a in h.Root.Appenders) { if (a is log4net.Appender.FileAppender) { if (a.Name.Equals("LogFileAppender")) { log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a; string logFileLocation = path; fa.File = logFileLocation; fa.ActivateOptions(); } else if (a.Name.Equals("ErrorFileAppender")) { log4net.Appender.FileAppender fa = (log4net.Appender.FileAppender)a; string logFileLocation = errorPath; fa.File = logFileLocation; fa.ActivateOptions(); } } } }
в качестве альтернативы для выполнения этого программно, вы можете использовать переменные среды и настраиваемые шаблоны в файле конфигурации. смотрите этот ответ на аналогичный вопрос.
посмотрите на "PatternString для конфигурации на основе шаблонов" в в такой как log4net В1.2.10 заметки о выпуске.
также, если вы думаете о записи в каталог, такой как Enviroment.SpecialFolder.CommonApplicationData вам нужно рассмотрим:
будут ли все экземпляры вашего приложения для всех пользователей иметь доступ на запись в файл журнала? Например, я не верю, что не администраторы смогут писать в Enviroment.SpecialFolder.CommonApplicationData.
конфликт, если несколько экземпляров вашего приложения (для одного и того же или разных пользователей) пытаются использовать один и тот же файл. Вы можете использовать "минимальную модель блокировки" (см. http://logging.apache.org/log4net/release/config-examples.html чтобы разрешить нескольким процессам записывать в один и тот же файл журнала, но, вероятно, это повлияет на производительность. Или вы можете дать каждому процессу другой файл журнала, например, включив идентификатор процесса в имя файла с помощью настраиваемого шаблона.
Если вам нужно развернуть в неизвестных системах, и вы хотите использовать простое решение от Philipp M даже с различными специальными папками, вы можете получить специальный путь к папке, который вы хотите, и установить пользовательскую переменную env перед загрузкой конфигурации log4net.
string localData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); Environment.SetEnvironmentVariable("MY_FOLDER_DATA", localData); XmlConfigurator.Configure( ...... просто чтобы убедиться, что переменная env существует и имеет нужное значение.
отличный вариант использования для LINQs
OfType<T>:/// <summary> /// Applies a transformation to the filenames of all FileAppenders. /// </summary> public static void ChangeLogFile(Func<string,string> transformPath) { // iterate over all FileAppenders foreach (var fileAppender in LogManager.GetRepository().GetAppenders().OfType<FileAppender>()) { // apply transformation to the filename fileAppender.File = transformPath(fileAppender.File); // notify the logging subsystem of the configuration change fileAppender.ActivateOptions(); } }если имя файла в приложении.config-это
log.txtэто изменит вывод журнала наlogs/some_name_log.txt:ChangeLogFile(path => Path.Combine("logs", $"some_name_{Path.GetFileName(path)}"));чтобы ответить на исходную проблему OPs, которая будет:
ChangeLogFile(path => Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), path));
в текущей версии Log4Net (2.0.8.0) вы можете просто использовать
<file value="${ProgramData}\myFolder\LogFiles\" />наC:\ProgramData\..и${LocalAppData}наC:\Users\user\AppData\Local\
Comments