2009-10-14 2 views
5

log4net nie zastępuje mojej nazwy logowania prawidłowym wprowadzeniem PatternString. Chcę, aby mój dziennik byćLog4Net nie może znaleźć właściwości% username, gdy nadam nazwę plikowi w moim appenderze

Logs \ RRRRMMDD \ MSMQcore_ [nazwa_użytkownika] .log

Kiedy użyć właściwości %username, mam domeny w ścieżce, która dodaje inny folder zadnie tam . Chcę tylko nazwę użytkownika.

Logs \ RRRRMMDD \ MSMQcore_ [domena] \ [nazwa_użytkownika] .log

Każdy użytkownik ma przykład wkładając "username" w nazwie pliku appender za? Próbowałem kilku rzeczy, wciąż drapię się po głowie.

<appender name="core_Appender" type="log4net.Appender.RollingFileAppender" > 
<!-- <file type="log4net.Util.PatternString" value="Logs/%date{yyyyMMdd}/MSMQcore_%identity.log" /> --> 
<!-- <file type="log4net.Util.PatternString" value="Logs/%date{yyyyMMdd}/MSMQcore_%property{user}.log" /> --> 
<file type="log4net.Util.PatternString" value="Logs/%date{yyyyMMdd}/MSMQcore_%username.log" /> 
</appender> 
+0

Można to uzyskać poprzez wzorzec dodatku w Log4Net w wersji 1.2.11. Zobacz stackoverflow.com/a/26277219/203371 –

Odpowiedz

9

Korzystanie zmienną środowiskową wzór działa dla mnie:

<file type="log4net.Util.PatternString" value="Logs\\%env{USERNAME}.txt" /> 

Aktualizacja: jeśli zmienna środowiskowa LOGIN nie jest opcją, instacji PatternString może być alternatywą. Oto prosta realizacja:

public class MyPatternString : PatternString 
{ 
    public MyPatternString() 
    { 
     AddConverter("usernameonly", typeof(UserNameOnlyConverter)); 
    }  
} 

public class UserNameOnlyConverter : PatternConverter 
{ 
    override protected void Convert(TextWriter writer, object state) 
    { 
     var windowsIdentity = WindowsIdentity.GetCurrent(); 
     if (windowsIdentity != null && windowsIdentity.Name != null) 
     { 
      var name = windowsIdentity.Name.Split('\\')[1]; 
      writer.Write(name); 
     } 
    } 
} 

Nowe ustawienie będzie wyglądać następująco:

<file type="MyPatternString" value="Logs\\%usernameonly.txt" /> 

Aktualizacja 2: odpowiedzieć dlaczego% identyczności i% własność {user} nie praca:

% wzorca tożsamości podnosi właściwość tożsamości w bieżącym wątku. Ta właściwość jest w moich testach zerowych i prawdopodobnie jest tak, dopóki nie przypisze się określona tożsamość systemu Windows do uruchomionego wątku. To nie zadziała w kontekście aplikacji, ponieważ nie będziesz wiedział, który wątek będzie wykonywał faktyczne dołączanie.

Wzór właściwości% pobiera właściwości z klas GlobalContext i ThreadContext. Domyślnie w GlobalContext jest rejestrowana tylko nazwa log4net: HostName (LoggingEvent.HostNameProperty). Więc dopóki aktywnie nie zarejestrujesz właściwości w tych kontekstach, nie możesz ich użyć ze wzorcem właściwości%. Ponownie, wątekContext jest bezużyteczny w kontekście appender, ponieważ nie masz możliwości dowiedzieć się, który wątek będzie robił załączanie.

To powiedziawszy, rejestrowanie właściwości o nazwie nazwa użytkownika w kolekcji GlobalContext.Properties, gdzieś w procedurze uruchamiania aplikacji może sprawi, że właściwość% {username} będzie działać zgodnie z oczekiwaniami.

+0

Peter, dzięki ... to również zadziałało dla mnie. Na szczęście ustawiono zmienną środowiskową. Nadal nie jestem pewien, dlaczego inne wersje nie działały. być może PatternString analizuje tylko ciąg w jednym przejściu? tvm, Craig – Craig

+0

Dzięki za pęczek. To jest niesamowite. – Stephen

+0

Craig, myślę, że dzwonienie do AddConvertera zbyt wcześnie w kodzie mogło być częścią problemu. Zobacz poniżej moją odpowiedź na to, co zadziałało dla mnie. – Kit

3

Odpowiedź Piotra prawie pracował dla mnie; zdecydowanie postawił mnie na właściwej drodze, ponieważ potrzebowałem podobnego rozwiązania.Co miałem zrobić, to podklasa PatternConverter:

public class ConfigurationSettingsConverter : PatternConverter 
{ 
    protected override void Convert(TextWriter writer, object state) 
    { 
     // use Option as a key to get a configuration value... 
     if (Option != null) 
      writer.Write(ConfigUtils.Setting[Option]); 
    } 
} 

i dodać tego konwertera w ActivateOptions ręcznym podklasy PatternString:

public class ConfigurationSettingsPatternString : PatternString 
{ 
    public ConfigurationSettingsPatternString() 
    {} 

    public ConfigurationSettingsPatternString(string pattern): base(pattern) 
    {} 

    public override void ActivateOptions() 
    { 
     AddConverter("cs", typeof(ConfigurationSettingsConverter)); 
     base.ActivateOptions(); 
    } 
} 

początkowo próbował to zrobić w konstruktorze jak Piotr odpowiedział: ale konwerter nie został zwrócony z podstawowego wywołania ciągu wzorca, aby przeanalizować ciąg źródłowy. Miałem też zarejestrować konwerter typu (nie należy mylić z PatternConverter) gdziekolwiek w ścieżce kodu przed log4net została skonfigurowana:

ConverterRegistry.AddConverter(
    // type we want to convert to (from string)... 
    typeof(ConfigurationSettingsPatternString), 
    // the type of the type converter that will do the conversion... 
    typeof(ConfigurationSettingsPatternStringConverter)); 

Nie robi to zapobiega log4net z możliwości przekształcenia wartość atrybutu w węźle FileAppender 'file do ConfigurationSettingsPatternString. Na przykład, w tej konfiguracji fragmentu

<file 
    type="Some.Name.Space.ConfigurationSettingsPatternString, Some.Assembly" 
    value="some\path\MyLog.%cs{SomeKey}.log" /> 

%cs.{SomeKey} nie rozszerzył się i log4net zgłasza wyjątek. Oto kod dla przetwornika typu:

public class ConfigurationSettingsPatternStringConverter : IConvertTo, IConvertFrom 
{ 
    public bool CanConvertFrom(Type sourceType) 
    { 
     return sourceType == typeof(string); 
    } 

    public bool CanConvertTo(Type targetType) 
    { 
     return typeof(string).IsAssignableFrom(targetType); 
    } 

    public object ConvertFrom(object source) 
    { 
     var pattern = source as string; 
     if (pattern == null) 
      throw ConversionNotSupportedException.Create(typeof(ConfigurationSettingsPatternString), source); 
     return new ConfigurationSettingsPatternString(pattern); 
    } 

    public object ConvertTo(object source, Type targetType) 
    { 
     var pattern = source as PatternString; 
     if (pattern == null || !CanConvertTo(targetType)) 
      throw ConversionNotSupportedException.Create(targetType, source); 
     return pattern.Format(); 
    } 
} 

Ten okazuje się działać dobrze dla systemu Windows wielu usług udostępnianych w ramach tego samego pliku wykonywalnego (na przykład można dodać % ServiceName wzór jak nazwa pliku w celu oddzielenia dzienniki służb

+0

Dziękuję bardzo, to działa dla mnie. – Vince

1

Używanie nazwy użytkownika «%» działa na mnie..

<parameter> 
    <parameterName value="@identity" /> 
    <dbType value="String" /> 
    <size value="255" /> 
    <layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="%username" /> 
    </layout> 
</parameter> 

Ale potem znowu jestem w kontekście standardowej aplikacji WinForms, a nie aplikacja ASP.NET nie wiem, czy jest to czego szukasz . nie jest już wymagane Zastosowanie atrybutu

[TypeConverter("namespace.ConfigurationSettingsPatternStringConverter")] 
public class ConfigurationSettingsPatternString : PatternString 
{ 

i wezwanie do

ConverterRegistry.AddConverter(
// type we want to convert to (from string)... 
typeof(ConfigurationSettingsPatternString), 
// the type of the type converter that will do the conversion... 
typeof(ConfigurationSettingsPatternStringConverter)); 

:

0
<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="Running on ${COMPUTERNAME}/${USERNAME} %newline %logger %date%newline Thread ID=[%thread]%newline %-5level - %message%newline" /> 
</layout> 

To zadziałało dobrze dla mnie.

Powiązane problemy