Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578

Вывод ProjectName

27.03.2024, 13:53. Показов 834. Ответов 14

Студворк — интернет-сервис помощи студентам
Ка сделать чтобы в сообщение автоматически проставлялось имя проекта?
Сейчас я сделал это принудительно.

Текущий Вывод
2024-03-27 13:31:53.193 +03:00 [INF] SerilogTestWinForm01 | Message
2024-03-27 13:31:53.322 +03:00 [INF] SerilogTestWinForm01.Service| CreateLoggerMessage



github: https://github.com/jhon65496/OutputProjectName

Проект: SerilogTestWinForm01
SerilogTestWinForm01.csproj
XML
1
2
3
4
5
6
...
<ProjectReference Include="..\LoggingSerilog\LoggingSerilog.csproj">
...
 
<ProjectReference Include="..\SerilogTestWinForm01.Service\SerilogTestWinForm01.Service.csproj">
...

Form1.cs
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Json;
 
using LoggingSerilog;
using SerilogTestWinForm01.Service;
 
public partial class Form1 : Form
{
    ILogger _lg;
    ProductService productService;
 
    public Form1()
    {
        InitializeComponent();
 
        Logger1 lg = new Logger1();
        _lg = lg.CreateLogger2();
 
        productService = new ProductService(_lg);
 
        CreateLoggerMessage();
    }
 
    public void CreateLoggerMessage()
    {
            _lg.Information($"SerilogTestWinForm01 | Message");
 
        productService.CreateLoggerMessage();
    }
}

Проект: SerilogTestWinForm01.Service
ProductService
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ProductService
{
    private readonly ILogger _log;
 
    public ProductService(ILogger log)
    {
        _log = log;       
    }
 
 
    public void CreateLoggerMessage()
    {
        _log.Information("SerilogTestWinForm01.Service | CreateLoggerMessage");
    }
 
}
Проект: LoggingSerilog
Logger1
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//---
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Json;
 
public class Logger1
{
    public ILogger CreateLogger2()
    {
            
        Log.Logger = new LoggerConfiguration()                         
                    .WriteTo.File("all-28-Test.logs",
                                    rollingInterval: RollingInterval.Minute)
 
                    // set default minimum level
                    .MinimumLevel.Debug()
                    .CreateLogger();
 
        ILogger lg = Log.Logger;
        
        return lg;            
    }
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.03.2024, 13:53
Ответы с готовыми решениями:

Ошибка 'projectname.Form1.Dispose(bool)': no suitable method found to override
При запуске проекта выдает ошибку Dispose.. namespace Incercarea4 { partial class Form1 { /// &lt;summary&gt; ...

программа которая создает список группы(фамилия, имя, дата рождения,оценки матем,информатика,физика) вывод всего списка,вывод отличников,вывод двоиечн
программа которая создает список группы(фамилия, имя, дата рождения,оценки матем,информатика,физика) вывод всего списка,вывод...

Осуществить вывод значений аргумента и функции, сопровождая вывод наименованиями переменных
Вычислить значение функции, заданной в таблице. Осуществить вывод значений аргумента и функции, сопровождая вывод наименованиями...

14
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
27.03.2024, 20:20
dev3214, вообще я реализовывал это ручками, читая ApplicationName из конфигурации Serilog-а.
Поскольку имя проекта и формальное имя приложения отличались друг от друга.

В вашем же случае можно попробовать использовать LogContext для добавления динамических свойств.
При инициализации Logger-а добавить свойство ApplicationName в LogContext через рефлексию.

Добавлено через 1 минуту
А можно написать свой Enricher, как было показано в примере с UTC.

Добавлено через 5 минут
На основе вашего примера с UTC:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using Serilog;
using Serilog.Core;
using Serilog.Events;
 
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console(outputTemplate: "{Timestamp:u} | {ProjectName} | [{Level:u3}] {Message:lj}{NewLine}")
    .MinimumLevel.Debug()    
    .Enrich.With<ProjectNameEnricher>()
    .CreateLogger();
 
string message = "`Parameter logging result`";
 
// logging                        
Log.Information("Some `Information`. Parameter logging -- {message}", message);
 
class ProjectNameEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
        logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", typeof(Program).Assembly.GetName().Name));
    }
}
Bash
1
2024-03-27 16:51:30Z | ConsoleApp3.SerilogDateTemplate | [INF] Some `Information`. Parameter logging -- `Parameter logging result`
Добавлено через 1 минуту
Цитата Сообщение от IamRain Посмотреть сообщение
В вашем же случае можно попробовать использовать LogContext для добавления динамических свойств.
Собственно, Enricher-ы этим и занимаются, поэтому правильный способ - работать с ними.

Добавлено через 5 минут
По-хорошему лучше закэшировать имя проекта:
C#
1
2
3
4
5
6
7
8
9
10
class ProjectNameEnricher : ILogEventEnricher
{
    private string? projectName;
    
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
        projectName ??= typeof(Program).Assembly.GetName().Name;
        logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", projectName));
    }
}
Добавлено через 12 минут
А можно сделать eager init при создании Enricher-а:
C#
1
2
3
4
5
6
7
8
9
class ProjectNameEnricher : ILogEventEnricher
{
    private readonly string projectName = typeof(Program).Assembly.GetName().Name;
    
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
        logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", projectName));
    }
}
Я бы остановился на этом варианте, так как логирование может быть довольно интенсивным, и это уже идет преждевременная оптимизация, которая зло.
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
27.03.2024, 20:54  [ТС]
IamRain,
Program не определяется.
Я использую NET Framework 4.8.
C#
1
typeof(Program).Assembly.GetName().Name)

Можно так?
C#
1
string projectName = Assembly.GetCallingAssembly().GetName().Name;
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
27.03.2024, 21:00
Цитата Сообщение от dev3214 Посмотреть сообщение
string projectName = Assembly.GetCallingAssembly().GetName(). Name;
Только не Calling а EntryAssembly тогда уж:
C#
1
private readonly string projectName = Assembly.GetEntryAssembly().GetName().Name;
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
27.03.2024, 21:11  [ТС]
IamRain,
Не совсем получается...

Получаю вывод
2024-03-27 18:07:01Z | SerilogTestWinForm01 | [INF] MyName--SerilogTestWinForm01 | Message
2024-03-27 18:07:01Z | SerilogTestWinForm01 | [INF] MyName--SerilogTestWinForm01.Service | CreateLoggerMessage



Ожидаю вывод
2024-03-27 18:07:01Z | SerilogTestWinForm01 | [INF] MyName--SerilogTestWinForm01 | Message
2024-03-27 18:07:01Z | SerilogTestWinForm01.Service | [INF] MyName--SerilogTestWinForm01.Service | CreateLoggerMessage


Проект: https://github.com/jhon65496/O... ree/02ImRn


Сделал так.
Проект: LoggingSerilog
Файл: Logger1.cs

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Json;
 
namespace LoggingSerilog
{
    public class Logger1
    {
        public ILogger CreateLogger2()
        {
             
            Log.Logger = new LoggerConfiguration()                         
                        .WriteTo.File("all-28-Test.logs",
                                        outputTemplate: "{Timestamp:u} | {ProjectName} | [{Level:u3}] {Message:lj}{NewLine}"                                        )
 
                        // set default minimum level
                        .MinimumLevel.Debug()
                        .Enrich.With<ProjectNameEnricher>()
                        .CreateLogger();
 
            ILogger lg = Log.Logger;
            
            return lg;            
        }
    }
 
    class ProjectNameEnricher : ILogEventEnricher
    {
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
        {
            // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", typeof(Program).Assembly.GetName().Name));
            // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", Assembly.GetCallingAssembly().GetName().Name));
            logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", Assembly.GetEntryAssembly().GetName().Name));
            // 
        }
    }
}
0
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,591
Записей в блоге: 2
27.03.2024, 21:47
Цитата Сообщение от dev3214 Посмотреть сообщение
Не совсем получается...
Получаю вывод
2024-03-27 18:07:01Z | SerilogTestWinForm01 | [INF] MyName--SerilogTestWinForm01 | Message
2024-03-27 18:07:01Z | SerilogTestWinForm01 | [INF] MyName--SerilogTestWinForm01.Service | CreateLoggerMessage
Ожидаю вывод
2024-03-27 18:07:01Z | SerilogTestWinForm01 | [INF] MyName--SerilogTestWinForm01 | Message
2024-03-27 18:07:01Z | SerilogTestWinForm01.Service | [INF] MyName--SerilogTestWinForm01.Service | CreateLoggerMessage
Документацию почитайте тогда и выберите что вы хотите.
* Assembly.GetEntryAssembly
* Assembly.GetExecutingAssembly
* Assembly.GetCallingAssembly

Но помните что при различных использованиях, будет и разных контекст. IamRain вам дал Assembly.GetEntryAssembly() так как он всегда (ну не всегда всегда) будет один - по имени всего приложения. В остальных случая это будет разным от источника вызова.
Если вы хотите логировать классы, вызывающие логирование, то и используйте подход микрософта. Логгер создаётся с конкретным типом ILogger<HomeController> или же вы сначала вручную создаёте логгер и вводите там нужный тэг. В вашем случае это может выглядеть так:
C#
1
_lg = lg.CreateLogger2("ProductService");
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
27.03.2024, 22:01  [ТС]
Цитата Сообщение от HF Посмотреть сообщение
Документацию почитайте тогда и выберите что вы хотите.
* Assembly.GetEntryAssembly
* Assembly.GetExecutingAssembly
* Assembly.GetCallingAssembly
Использовал Assembly.GetExecutingAssembly.
Тоже не подходит..
Вывод

2024-03-27 18:56:13Z | LoggingSerilog | [INF] MyName--SerilogTestWinForm01 | Message
2024-03-27 18:56:13Z | LoggingSerilog | [INF] MyName--SerilogTestWinForm01.Service | CreateLoggerMessage


Цитата Сообщение от HF Посмотреть сообщение
Если вы хотите логировать классы, вызывающие логирование, то и используйте подход микрософта. Логгер создаётся с конкретным типом ILogger<HomeController> или же вы сначала вручную создаёте логгер и вводите там нужный тэг.
"Если вы хотите логировать классы" - что вы имеете ввиду?
Логер будет выводить члены, где прописана строка логирования?

Я пробовал такое...
Нашёл пример с использованием [CallerMemberName], [CallerFilePath], [CallerLineNumber].
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
27.03.2024, 23:10
Лучший ответ Сообщение было отмечено dev3214 как решение

Решение

Цитата Сообщение от dev3214 Посмотреть сообщение
"Если вы хотите логировать классы" - что вы имеете ввиду?
Будет известно, кто является источником события, то есть в каком типе произвелось логирование. Это специальный property, называется SourceContext. Serilog умеет это интегрировать с Microsoft-овский интерфейсом ILogger<T>, где T - как раз и будет SourceContext-ом.

Добавлено через 16 минут
Без DI это бы выглядело примерно так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using Microsoft.Extensions.Logging;
using Serilog;
 
var  foo = new Foo();
foo.Bar();
 
class Foo
{
    private readonly ILogger<Foo> _logger;
    public Foo()
    {
        _logger = LogExtensions.LoggingInstance<Foo>();
    }
 
    public void Bar()
    {
        _logger.LogInformation("Doing Bar() here");
    }
}
 
public static class LogExtensions
{
    public static ILogger<T> LoggingInstance<T>()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console(outputTemplate: "{Timestamp:u} | {ProjectName} | {SourceContext} | [{Level:u3}] {Message:lj}{NewLine}")
            .MinimumLevel.Debug()
            .Enrich.With<UtcTimestampEnricher>()
            .Enrich.With<ProjectNameEnricher>()
            .CreateLogger();
 
        ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);
        return factory.CreateLogger<T>();
    }
}
Добавлено через 43 секунды
Bash
1
2024-03-27 19:57:44Z | ConsoleApp1.SerilogAppName | Foo | [INF] Doing Bar() here
Добавлено через 1 минуту
Цитата Сообщение от IamRain Посмотреть сообщение
как раз и будет SourceContext-ом.
Этот SourceContext еще называют категорией логирования.
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
28.03.2024, 13:02  [ТС]
IamRain,
Не получается.

https://github.com/jhon65496/O... ree/08ImRn

Вывод. Только один проект.

2024-03-28 09:56:13Z | SerilogTestWinForm01 | SerilogTestWinForm01.Form1 | [INF] MyNameForm1 | `CreateLoggerMessageForm1()`



Установил:
- Microsoft.Extensions.Logging;
- Serilog.Extensions.Logging.

Проект: LoggingSerilog
Класс: LogExtensions.cs
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using Microsoft.Extensions.Logging;
using Serilog.Core;
using Serilog.Events;
using System.Reflection;
 
namespace LoggingSerilog
{
    public class LogExtensions
    {
        public static ILogger<T> LoggingInstance<T>()
        {
            Log.Logger = new LoggerConfiguration()
                .WriteTo.File("all-28-08ImRn-Test.logs",
                                outputTemplate: "{Timestamp:u} | {ProjectName} " +
                                                "| {SourceContext} | [{Level:u3}] " +
                                                "{Message:lj} {NewLine}")
                .MinimumLevel.Debug()
                // --- --- --- --- --- --- ---
                // .Enrich.With<UtcTimestampEnricher>()
                .Enrich.With<ProjectNameEnricher>()
                // --- --- --- --- --- --- ---
                .CreateLogger();
 
            ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);
            return factory.CreateLogger<T>();
        }
 
    }
 
    class ProjectNameEnricher : ILogEventEnricher
    {
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
        {
            // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", typeof(Program).Assembly.GetName().Name));            
            // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", Assembly.GetCallingAssembly().GetName().Name));
            logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", Assembly.GetEntryAssembly().GetName().Name));
        }
    }
}


Проект: SerilogTestWinForm01
Класс: Form1

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using Serilog;
using Serilog.Events;
 
// using LoggingSerilog3;
using LoggingSerilog;
using SerilogTestWinForm01.Service;
using Microsoft.Extensions.Logging;
using Serilog.Core;
 
namespace SerilogTestWinForm01
{
    public partial class Form1 : Form
    {
        // ILogger _lg;
        private readonly ILogger<Form1> _logger;
        ProductService productService;
 
        public Form1()
        {
            InitializeComponent();
 
            _logger = LogExtensions.LoggingInstance<Form1>();
 
            productService = new ProductService();
 
            CreateLoggerMessageForm1();
            CreateLoggerMessageProductService();
        }
 
        public void CreateLoggerMessageForm1()
        {
            _logger.LogInformation($"MyNameForm1 | `CreateLoggerMessageForm1()`");
        }
     
        public void CreateLoggerMessageProductService()
        {
            productService.CreateLoggerMessageProductService();
        }
    }
}

Проект: SerilogTestWinForm01.Service
Класс: ProductService
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 
using Serilog;
using Microsoft.Extensions.Logging;
using LoggingSerilog;
 
 
namespace SerilogTestWinForm01.Service
{
    public class ProductService
    {
        private readonly ILogger<ProductService> _logger;
 
        public ProductService()
        {
            _logger = _logger = LogExtensions.LoggingInstance<ProductService>();
        }
 
 
        public void CreateLoggerMessageProductService()
        {
            Thread.Sleep(1000);
 
            _logger.LogInformation($"MyNameSerilogTestWinForm01.Service | CreateLoggerMessageProductService()");
        }
 
    }
}
0
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,591
Записей в блоге: 2
28.03.2024, 13:37
Цитата Сообщение от dev3214 Посмотреть сообщение
Не получается.
Потому что:
- в коде всё ещё остался "Assembly.GetEntryAssembly().GetName().N ame"
- Logger<T> не использует это T для имени вызываемого типа

Добавлено через 1 минуту
На вскидку, если я правильно понял, то проще сделать так ("на коленке" напишу)

вместо:
C#
1
2
3
4
5
6
7
        public static ILogger<T> LoggingInstance<T>()
        {
            Log.Logger = new LoggerConfiguration()
                .WriteTo.File("all-28-08ImRn-Test.logs",
                                outputTemplate: "{Timestamp:u} | {ProjectName} " +
                                                "| {SourceContext} | [{Level:u3}] " +
                                                "{Message:lj} {NewLine}")
сделать:
C#
1
2
3
4
5
6
7
        public static ILogger<T> LoggingInstance<T>()
        {
            Log.Logger = new LoggerConfiguration()
                .WriteTo.File("all-28-08ImRn-Test.logs",
                                outputTemplate: "{Timestamp:u} | {typeof(T).Name} " +
                                                "| {SourceContext} | [{Level:u3}] " +
                                                "{Message:lj} {NewLine}")
ну а этот ProjectNameEnricher вообще не нужен
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
28.03.2024, 14:08  [ТС]
HF,

https://github.com/jhon65496/O... /tree/10HF

Выводит только `SerilogTestWinForm01.Form1` второй проект не отображает.
```
2024-03-28 11:06:41Z | {typeof(T).Name} | SerilogTestWinForm01.Form1 | [INF] MyNameForm1 | `CreateLoggerMessageForm1()`
```
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class LogExtensions
    {
        public static ILogger<T> LoggingInstance<T>()
        {
            Log.Logger = new LoggerConfiguration()
                .WriteTo.File("all-28-08ImRn-Test.logs",
                                outputTemplate: "{Timestamp:u} | {typeof(T).Name} " +
                                                "| {SourceContext} | [{Level:u3}] " +
                                                "{Message:lj} {NewLine}")
                .MinimumLevel.Debug()
                // --- --- --- --- --- --- ---
                // .Enrich.With<UtcTimestampEnricher>()
                // .Enrich.With<ProjectNameEnricher>()
                // --- --- --- --- --- --- ---
                .CreateLogger();
 
            ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);
            return factory.CreateLogger<T>();
        }
 
    }
0
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,591
Записей в блоге: 2
28.03.2024, 15:42
Цитата Сообщение от dev3214 Посмотреть сообщение
{typeof(T).Name}
Упс. Я ж не знал что оно не так работает. Вы же видите что значение не записалось. Тут я не могу сразу сказать как быстро сделать, потому что нельзя поставить $ у маски outputTemplate - боюсь сломаются остальные параметры. Значит вам надо научиться перебрасывать Т.

Окей.. другой вариант. Обновляем только 20 и 36 строку, прокидывая Т в ваш Enricher.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using Microsoft.Extensions.Logging;
using Serilog.Core;
using Serilog.Events;
using System.Reflection;
 
namespace LoggingSerilog
{
    public class LogExtensions
    {
        public static ILogger<T> LoggingInstance<T>()
        {
            Log.Logger = new LoggerConfiguration()
                .WriteTo.File("all-28-08ImRn-Test.logs",
                                outputTemplate: "{Timestamp:u} | {ProjectName} " +
                                                "| {SourceContext} | [{Level:u3}] " +
                                                "{Message:lj} {NewLine}")
                .MinimumLevel.Debug()
                // --- --- --- --- --- --- ---
                // .Enrich.With<UtcTimestampEnricher>()
                .Enrich.With<ProjectNameEnricher<T>>()
                // --- --- --- --- --- --- ---
                .CreateLogger();
 
            ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);
            return factory.CreateLogger<T>();
        }
 
    }
 
    class ProjectNameEnricher<T> : ILogEventEnricher
    {
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
        {
            // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", typeof(Program).Assembly.GetName().Name));            
            // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", Assembly.GetCallingAssembly().GetName().Name));
            logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", typeof(T).Name));
        }
    }
}
Добавлено через 1 минуту
А!! ещё быстрее исправление:

C#
1
2
3
                                outputTemplate: "{Timestamp:u} | " + typeof(T).Name +
                                                " | {SourceContext} | [{Level:u3}] " +
                                                "{Message:lj} {NewLine}")
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
28.03.2024, 17:23  [ТС]
Цитата Сообщение от HF Посмотреть сообщение
Упс. Я ж не знал что оно не так работает. Вы же видите что значение не записалось. Тут я не могу сразу сказать как быстро сделать, потому что нельзя поставить $ у маски outputTemplate - боюсь сломаются остальные параметры. Значит вам надо научиться перебрасывать Т.
Окей.. другой вариант. Обновляем только 20 и 36 строку, прокидывая Т в ваш Enricher.

Вывод. Одно сообщение, а не два.

2024-03-28 14:13:03Z | Form1 | SerilogTestWinForm01.Form1 | [INF] MyNameForm1 | `CreateLoggerMessageForm1()`


При отладке в проекте SerilogTestWinForm01.Service в классе ProductService проходит метод public void CreateLoggerMessageProductService(), но в файл ничего не записывает.

Проект: https://github.com/jhon65496/O... /tree/12HF

LogExtensions
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 public class LogExtensions
{
    public static ILogger<T> LoggingInstance<T>()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.File("all-28-12HF-Test.logs",
                            outputTemplate: "{Timestamp:u} | " + typeof(T).Name  +
                                            " | {SourceContext} | [{Level:u3}] " +
                                            "{Message:lj} {NewLine}")
            .MinimumLevel.Debug()
            // --- --- --- --- --- --- ---
            // .Enrich.With<UtcTimestampEnricher>()
            // .Enrich.With<ProjectNameEnricher>()
                .Enrich.With<ProjectNameEnricher<T>>()
            // --- --- --- --- --- --- ---
            .CreateLogger();
 
        ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);
        return factory.CreateLogger<T>();
    }
 
}
 
class ProjectNameEnricher<T> : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
        // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", typeof(Program).Assembly.GetName().Name));            
        // logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", Assembly.GetCallingAssembly().GetName().Name));
        logEvent.AddPropertyIfAbsent(pf.CreateProperty("ProjectName", typeof(T).Name));
    }
}
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
28.03.2024, 20:54
Лучший ответ Сообщение было отмечено dev3214 как решение

Решение

Цитата Сообщение от dev3214 Посмотреть сообщение
Не получается.
Странно, а у меня получается. 3 проекта.
Либа с расширением для своего логгера на базе Serilog-а:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using Microsoft.Extensions.Logging;
using Serilog;
 
namespace AppName.Extensions;
 
public static class LogExtensions
{
    static LogExtensions()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console(outputTemplate: "{Timestamp:u} | {ProjectName} | {SourceContext} | [{Level:u3}] {Message:lj}{NewLine}")
            .MinimumLevel.Debug()
            .Enrich.With<ProjectNameEnricher>()
            .CreateLogger();
    }
    
    public static ILogger<T> LoggingInstance<T>()
    {
        ILoggerFactory factory = new LoggerFactory().AddSerilog(Log.Logger);
        return factory.CreateLogger<T>();
    }
}
И два проекта с двумя разными классами-примерами:
ConsoleApp1.SerilogAppName:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using AppName.Extensions;
using Microsoft.Extensions.Logging;
 
var  foo = new Foo();
foo.Bar();
 
class Foo
{
    private readonly ILogger<Foo> _logger;
    public Foo()
    {
        _logger = LogExtensions.LoggingInstance<Foo>();
    }
 
    public void Bar()
    {
        _logger.LogInformation("Doing Bar() here");
    }
}
ConsoleApp3.SerilogDateTemplate:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using AppName.Extensions;
using Microsoft.Extensions.Logging;
 
var bar = new Bar();
bar.Buzz();
 
class Bar
{
    private readonly ILogger<Bar> _logger;
    public Bar()
    {
        _logger = LogExtensions.LoggingInstance<Bar>();
    }
 
    public void Buzz()
    {
        _logger.LogInformation("Doing Buzz() here");
    }
}
Добавлено через 1 минуту
Bash
1
2
2024-03-28 17:27:37Z | ConsoleApp1.SerilogAppName | Foo | [INF] Doing Bar() here
2024-03-28 17:28:05Z | ConsoleApp3.SerilogDateTemplate | Bar | [INF] Doing Buzz() here
Добавлено через 16 минут
Цитата Сообщение от dev3214 Посмотреть сообщение
logEvent.AddPropertyIfAbsent(pf.CreatePr operty("ProjectName", typeof(T).Name));
Складывается ощущение, что у вас каша в голове. То, что вы попросили - выводить имя проекта, было показано еще в ProjectNameEnricher. А вывод категории логирования (источника лога, используя SourceContext свойство) - это просто вам дали дополнительно.
1
5 / 5 / 0
Регистрация: 11.09.2021
Сообщений: 578
28.03.2024, 23:44  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
Странно, а у меня получается. 3 проекта.
Либа с расширением для своего логгера на базе Serilog-а:
Вроде работает..

Вывод:
Bash
1
2
2024-03-28 20:27:10Z | SerilogTestWinForm01 | SerilogTestWinForm01.Form1          | [INF] MyNameForm1 | `CreateLoggerMessageForm1()` 
2024-03-28 20:27:11Z | SerilogTestWinForm01 | SerilogTestWinForm01.Service.ProductService | [INF] MyNameSerilogTestWinForm01.Service | CreateLoggerMessageProductService()


Если вам не сложно, не могли бы подсказать ещё несколько вопросов:
1. Вывести только необходимое:
Сейчас:
...| SerilogTestWinForm01 | SerilogTestWinForm01.Form1 | ...
...| SerilogTestWinForm01 | SerilogTestWinForm01.Service.ProductServ ice | ...


Ожидание:
...| SerilogTestWinForm01| ...
...| SerilogTestWinForm01.Service| ...

Цель: отобразить только имя проекта, без лишней информации.

2. Как вывести в отдельные столбцы(параметры):
- имя класса где вызывается логер;
- имя члена(метода, класса) где вызывается логер;
- номер строки где вызывается логер.



Цель отобразить это всё в Ексель файле в разных столбцах.
Типа:
- Логер сохраняем в CSV;
- Подключаем CSV к Excel.
- Анализируем.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
28.03.2024, 23:44
Помогаю со студенческими работами здесь

Осуществить вывод значений аргумента и функции, сопровождая вывод наименованиями переменных
Вычислить значение функции, заданной в таблице. Осуществить вывод значений аргумента и функции, сопровождая вывод наименованиями...

Графика. Модули. Ввод, вывод матрицы, вывод элементов из центра по спирали...
Модуль включает подпрограммы обработки матриц: ввод матрицы, вывод матрицы в графическом режиме, вывод элементов матрицы из центра по...

Вывод списка успевающих студентов и вывод результатов сдачи экзамена по предмету
Добрый день, помогите, пожалуйста, с написанием программы. В файле &quot;students.txt&quot; содержится список студентов и оценок, полученных на...

Вывод списка успевающих студентов и вывод результатов сдачи экзамена по предмету
Добрый день, помогите, пожалуйста, с написанием программы.

Осуществить вывод значений аргумента и функции, сопровождая вывод наименованиями переменных
вычислить значение функции, заданной в таблице. Осуществить вывод значений аргумента и функции, сопровождая вывод наименованиями...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru