.NET Разработчик
6.56K subscribers
443 photos
4 videos
14 files
2.13K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 2322. #ЧтоНовенького
Запись Логов по Требованию с Буферизацией. Начало

Обычно нужны подробные логи, когда что-то идёт не так, но когда всё хорошо, зачем платить за хранение логов, которые никогда не проверяются. Хотя выборка логов (log sampling) помогает сократить их объём, сохраняя только часть, иногда нужен другой подход.

Буферизация логов в .NET 9 временно сохраняет логи в памяти и позволяет позже решить, записывать ли их. Буферизация даёт контекстный контроль над тем, какие логи сохраняются на основе фактических результатов выполнения.

Концепция
Буферизация логов представляет новый шаблон потока:
1. Код генерирует логи обычным образом,
2. Нужные логи сохраняются в памяти, а не пишутся немедленно,
3. Позже, на основе определённых условий, вы решаете:
- Очистить буфер и записать все захваченные логи,
- Дать времени жизни буфера истечь, фактически отбрасывая ненужные логи.
Так, например, вы можете буферизировать подробные логи для транзакции, сохраняя их только в случае сбоя транзакции и отбрасывая в случае её успеха.

Две стратегии буферизации
.NET 9 предоставляет две стратегии буферизации: глобальная и по запросу.

1. Глобальная буферизация
Хранит логи в кольцевых буферах, общих для всего приложения. Это подходит для буферизации логов, связанных с длительными процессами или фоновыми задачами. Для базовых сценариев включите буферизацию:
builder.Logging
.AddGlobalLogBuffer(LogLevel.Information);

Эта конфигурация буферизует все логи от уровня Information. Для более сложных сценариев определите конкретные правила:
builder.Logging.AddGlobalBuffer(o =>
{
// Буферизация логов уровня Information, категории "PaymentService"
o.Rules.Add(
new LogBufferingFilterRule(
categoryName: "PaymentService",
logLevel: LogLevel.Information));

o.MaxBufferSizeInBytes = 100 * 1024 * 1024;
o.MaxLogRecordSizeInBytes = 50 * 1024;
o.AutoFlushDuration = TimeSpan.FromSeconds(30);
});

- MaxBufferSizeInBytes – максимальный размер буфера.
- MaxLogRecordSizeInBytes – максимальный размер отдельных записей лога.
- AutoFlushDuration – как долго буферизация лога будет оставаться отключенной после запуска операции записи (flush). В примере выше буферизация будет оставаться отключенной в течение 30 секунд, что позволит приложению нормально писать все логи.

Запись глобального буфера
Чтобы записать буферизованные логи, внедрите класс GlobalLogBuffer и вызовите его метод Flush():
public class PaymentService
{
private ILogger<PaymentService> _logger;
private GlobalLogBuffer _buffer;

public PaymentService(
ILogger<PaymentService> logger,
GlobalLogBuffer buffer)
{
_logger = logger;
_buffer = buffer;
}

public async Task ProcessPayment(
PaymentRequest req)
{
try
{
_logger.LogInformation(
"Старт обработки платежа для транзакции {TransId}", req.TransactionId);
// Обработка платежа...
_logger.LogInformation("Платёж обработан");
}
catch (Exception ex)
{
_logger.LogError(ex, "Сбой обработки");
// Записываем буфер для записи детальных логов
_buffer.Flush();
throw;
}
}
}

В этом примере подробные логи о процессе оплаты сохраняются только в случае возникновения исключения.

Окончание следует…

Источник:
https://devblogs.microsoft.com/dotnet/emit-logs-on-demand-with-log-buffering/
👍18
День 2323. #ЧтоНовенького
Запись Логов по Требованию с Буферизацией. Окончание

Начало

2. Буферизация по запросу
Для веб-приложений ASP.NET Core буферизация по запросу обеспечивает более детальный контроль, поддерживая отдельные буферы для каждого HTTP-запроса. Подходит для отслеживания полного контекста отдельных взаимодействий пользователей.

Добавляем буферизацию по запросу:
builder.Services.AddPerIncomingRequestBuffer(o =>
{
// Логи Information от API контроллеров
o.Rules.Add(
new LogBufferingFilterRule(
categoryPrefix: "MyApp.Controllers",
logLevel: LogLevel.Information));

o.AutoFlushDuration = TimeSpan.FromSeconds(5);
});

Ключевое отличие от глобальной буферизации - когда HTTP-запрос завершается, буфер очищается и все его логи удаляются.

Очистка буфера по запросу
Чтобы выдать буферизованные логи для определённого запроса, внедрите класс PerRequestLogBuffer:
[ApiController]
[Route("[controller]")]
public class OrderController : ControllerBase
{
private ILogger<OrderController> _logger;
private PerRequestLogBuffer _buffer;

public OrderController(
ILogger<OrderController> logger,
PerRequestLogBuffer buffer)
{
_logger = logger;
_buffer = buffer;
}

[HttpPost]
public IActionResult CreateOrder(
OrderRequest request)
{
try
{
_logger.LogInformation("Заказ для клиента {CustomerId}", request.CustomerId);
// Обработка заказа…
_logger.LogInformation("Заказ {OrderId} создан", orderId);

return Ok(new { OrderId = orderId });
}
catch (Exception ex)
{
_logger.LogError(ex, "Сбой заказа");
_buffer.Flush();
return StatusCode(500, "Сбой создания заказа");
}
}
}

Запись (flush) буфера по запросу также записывает глобальный буфер, гарантируя, что все соответствующие логи будут записаны при возникновении ошибки.

Динамические обновления конфигурации
Если вы используете провайдер конфигурации, поддерживающий перезагрузки (например, File Configuration Provider), вы можете обновить правила буферизации без перезапуска приложения.

Это особенно ценно в производственных сценариях, где может потребоваться временно увеличить детализацию логов для диагностики проблемы, а затем вернуться к обычным уровням после её устранения.

Рекомендации
1. Стратегия буферизации
Буферизуйте подробные логи с уровня Information, но позвольте логам Error и Critical записываться немедленно. Это гарантирует, что важные проблемы всегда будут видны, а подробный контекст будет доступен только при необходимости.

2. Создайте явные триггеры записи (flush)
Определите конкретные условия, при которых контекст лога имеет значение, и добавьте явные вызовы записи:
- При исключениях или ошибках,
- Когда операции превышают ожидаемую продолжительность,
- Когда обнаружено что-то подозрительное.

3. Добавьте выборку логов для максимальной эффективности
Для приложений с большим объёмом логов используйте буферизацию и выборку:
- Фильтруйте обычные логи для уменьшения общего объёма,
- Буферизируйте подробные логи для записи контекста очистки при необходимости.

Ограничения
-.NET 9 и выше,
- Точный порядок логов может не сохраняться (временные метки сохраняются),
- Области (scope) логов не поддерживаются,
- Некоторые расширенные свойства записи логов (например, ActivitySpanId) не сохраняются.

Производительность
Буферизация логов — это компромисс между памятью и хранилищем:
- Буферизованные логи потребляют память, пока они не будут либо записаны, либо отброшены,
- Записывая логи только в определённых сценариях, вы можете радикально сократить расходы на хранение.
Для больших распределённых приложений накладные расходы памяти минимальны по сравнению с потенциальной экономией хранилища.

Источник: https://devblogs.microsoft.com/dotnet/emit-logs-on-demand-with-log-buffering/
👍10
День 2327. #ЧтоНовенького
Вам не Хватало Vim в Windows? Представляем Edit!

Edit — это новый текстовый редактор командной строки в Windows. Edit имеет открытый исходный код. Вы можете посмотреть код на GitHub или установить его, выполнив следующую команду:
winget install Microsoft.Edit


Edit будет доступен для предварительного просмотра в программе Windows Insider в ближайшие месяцы. После этого он будет поставляться как часть Windows 11.

Как использовать?
Введите edit в командной строке или edit <your-file-name>, чтобы открыть файл. Теперь вы можете редактировать файлы непосредственно в командной строке без переключения контекста.

Возможности
Edit — это небольшой, легкий текстовый редактор. Он занимает менее 250 КБ. Он пока находится на ранней стадии разработки, но у него есть несколько готовых функций:
1. Поддержка режима мыши
Пункты меню другие элементы UI поддерживают использование мыши, а также горячие клавиши.
2. Открытие нескольких файлов
Вы можете открыть несколько файлов в Edit и переключаться между ними с помощью Ctrl+P (или щелкнув на список файлов в правом нижнем углу).
3. Поиск и замена
Вы можете найти и заменить текст с помощью Ctrl+R или выбрать Edit > Replace в меню. Также есть поддержка регистра и регулярных выражений.
4. Перенос по словам
Edit поддерживает перенос по словам. Чтобы использовать перенос по словам, вы можете использовать Alt+Z или выбрать View > Word Wrap в меню.

Зачем нам ещё один CLI-редактор?
Edit - текстовый редактор CLI по умолчанию в 64-разрядных версиях Windows. 32-разрядные версии Windows поставляются с редактором MS-DOS, но в 64-разрядных версиях редактор CLI не установлен.

В Microsoft решили, что нужен немодальный редактор для Windows (в отличие от модального редактора, в котором новым пользователям пришлось бы запоминать различные режимы работы и как переключаться между ними). К сожалению, это ограничило выбор списком редакторов, которые либо не имели собственной поддержки для Windows, либо были слишком большими, чтобы включать их в каждую версию ОС. В результате родился Edit.

Источник: https://devblogs.microsoft.com/commandline/edit-is-now-open-source/
👍8👎1
День 2331. #ЧтоНовенького
Вышел .NET Aspire 9.3
Команда .NET выпустила версию 9.3 .NET Aspire, в которой представлены обновления для диагностики, интеграции и рабочих процессов развёртывания. Этот выпуск направлен на улучшение опыта разработчиков путём интеграции GitHub Copilot в панель управления Aspire, расширения возможностей трассировки и упрощения развёртываний в Azure.

Интеграция GitHub Copilot в панель управления Aspire (на первой картинке выше) позволяет разработчикам анализировать журналы, исследовать ошибки в распределённых сервисах и выявлять проблемы производительности с помощью ИИ, не покидая среду панели управления разработчика. По словам команды .NET, Copilot дополняет диагностику на основе OpenTelemetry, представляя саммари журналов, интерпретируя коды ошибок и помогая выявлять основные причины в сложных сценариях трассировки.

В панель управления Aspire было добавлено контекстное меню в представлении Resource Graph (на второй картинке выше), предлагающее быстрый доступ к данным телеметрии, специфичным для ресурсов командам и URL. Как отмечено в релизе, страница Traces теперь отображает исходящие вызовы к зависимостям, таким как базы данных и кэши, даже если эти сервисы не выдают собственную телеметрию. Эти обновления призваны предоставить разработчикам более широкую наблюдаемость поведения приложений.

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

Улучшения интеграции Aspire включают поддержку размещения самостоятельно управляемого экземпляра YARP через пакет Aspire.Hosting.Yarp. Кроме того, интеграция с MySQL теперь позволяет создавать базу данных во время настройки хоста приложения:
builder.AddMySql("mysql").AddDatabase("mydb");

Для контейнеризированных сервисов в выпуске представлены упрощенные API конфигурации для Postgres, Redis и SQL Server, позволяющие разработчикам указывать порты хоста и пароли с помощью метода RunAsContainer:
var sql = builder.AddAzureSqlServer("sql");
sql.RunAsContainer(c =>
{
c.WithHostPort(12455);
});


Интеграция с Azure также была расширена. Разработчики теперь могут создавать и добавлять контейнеры Blob Storage в AppHost. Были введены два новых API — AddAzureKeyVaultKeyClient и AddAzureKeyVaultCertificateClient — для упрощения доступа к Azure Key Vault для операций с ключами и сертификатами.

Функция Custom URLs в модели приложения была обновлена для поддержки относительных путей и большего контроля над видимостью. Новая перегрузка WithUrlForEndpoint позволяет прикреплять несколько конечных точек к одному ресурсу.

Для Azure App Service версия 9.3 представляет предварительную поддержку для развёртывания проектов .NET в ней. Поток развёртывания поддерживается через API AddAzureAppServiceEnvironment(…) и позволяет настраивать общие сценарии, такие как проекты .NET с одной конечной точкой, опубликованные в реестре контейнеров Azure:
builder.AddAzureAppServiceEnvironment("env");

builder.AddProject<Projects.Api>("api")
.WithExternalHttpEndpoints()
.PublishAsAzureAppServiceWebsite((infra, site) =>
{
site.SiteConfig.IsWebSocketsEnabled = true;
});


Другие изменения в этом выпуске включают дополнительные улучшения CLI, улучшения диагностических визуальных элементов и расширенные параметры конфигурации контейнера.

Источник: https://www.infoq.com/news/2025/06/dotnet-aspire-93-release/
👍8
День 2343. #ЧтоНовенького
Вышел 5 Превью .NET 10. Начало
Microsoft объявили о выпуске .NET 10 превью 5, представив обновления для нескольких компонентов, включая ASP.NET Core, .NET MAUI, WPF и EF Core.

ASP.NET Core
1. Появилась возможность настраивать пользовательские дескрипторы безопасности для очередей запросов HTTP.sys через свойство RequestQueueSecurityDescriptor в HttpSysOptions. Это обеспечивает лучший контроль над доступом к очередям запросов на уровне ОС.

2. API валидации, поддерживающие Minimal API, были помечены как экспериментальные, чтобы разрешить будущие модификации, хотя API AddValidation верхнего уровня остаются стабильными.

3. Генерация OpenAPI была улучшена в версии 3.1. Выпуск также расширяет извлечение метаданных из XML-документации, распознавая теги <returns> и <response> для описаний ответов.

4. В Blazor представлен метод для более простого рендеринга страниц Not Found путем указания компонента NotFoundPage в конфигурации маршрутизатора. Этот подход имеет приоритет над старым фрагментом NotFound. Теперь страница NotFound.razor включена в шаблоны проектов по умолчанию и будет отображаться всякий раз, когда в приложении вызывается метод NavigationManager.NotFound():
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>This content will be ignored because we have NotFoundPage defined.</NotFound>
</Router>


5. Введены подробные метрики и возможности трассировки для приложений Blazor. Метрики публикуются через выделенные счетчики для компонентов, событий жизненного цикла и конвейеров сервера. Трассировка использует новый источник активности Microsoft.AspNetCore.Components, включающий подробный инструментарий для навигации, обработки событий и жизненных циклов конвейера. Разработчики могут включить эту диагностику, настроив OpenTelemetry для сбора данных из соответствующих источников и счётчиков:
builder.Services
.ConfigureOpenTelemetryMeterProvider(p =>
{
p.AddMeter("Microsoft.AspNetCore.Components");
p.AddMeter("Microsoft.AspNetCore.Components.Lifecycle");
p.AddMeter("Microsoft.AspNetCore.Components.Server.Circuits");
});

builder.Services
.ConfigureOpenTelemetryTracerProvider(p =>
{
p.AddSource("Microsoft.AspNetCore.Components");
});


Окончание следует…

Источник:
https://www.infoq.com/news/2025/06/dotnet-10-preview-5/
👍10
День 2344. #ЧтоНовенького
Вышел 5 Превью .NET 10. Окончание

Начало

MAUI
1. Добавлена поддержка глобальных и неявных пространств имён XAML. Это упрощает разметку, позволяя разработчикам использовать элементы управления без указания нескольких объявлений xmlns. Новое глобальное пространство имён может включать пользовательские представления, конвертеры и сторонние библиотеки, что позволяет сделать XAML более чистым и удобным для обслуживания. Функцию можно активировать через свойства проекта, что снижает необходимость в подробных объявлениях. Однако Microsoft отмечает, что могут возникать ошибки инструментов, пока эта функция остаётся в предварительной версии.

2. Добавлена возможность перехвата веб-запросов в HybridWebView благодаря обработке события WebResourceRequested. Можно изменять или блокировать запросы, позволяя использовать такие сценарии, как внедрение пользовательских заголовков или обслуживание локальных ресурсов:
<HybridWebView WebResourceRequested="HybridWebView_WebResourceRequested" />


WPF
1. Представлен сокращённый синтаксис для Grid.RowDefinitions и Grid.ColumnDefinitions, делая XAML более лаконичным и улучшая поддержку Hot Reload.

2. Улучшения шрифтов и глобализации включают добавление шрифта simsun-extg для улучшения рендеринга на восточноазиатских языках. Тема Fluent была усовершенствована, устраняя сбои и улучшая стили для макетов RTL. Повышение производительности было достигнуто за счёт сокращения выделения памяти и удаления неиспользуемых путей кода.

Entity Framework
В предыдущих версиях EF Core, когда вы указывали значение по умолчанию для свойства, EF Core всегда позволял базе данных автоматически генерировать имя ограничения. Теперь вы можете явно указать имя для ограничений значения по умолчанию для SQL Server, что даёт больше контроля над схемой БД:
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Blog>()
.Property(b => b.IsActive)
.HasDefaultValue(true, "DF_Blog_IsActive");

mb.Entity<Post>()
.Property(p => b.CreatedDate)
.HasDefaultValueSql("GETDATE()", "DF_Post_CreatedDate");
}

Вы также можете вызвать UseNamedDefaultConstraints, чтобы включить автоматическое именование всех ограничений по умолчанию. Обратите внимание, что если у вас есть существующие миграции, то следующая добавленная миграция переименует каждое ограничение по умолчанию в модели:
protected override void OnModelCreating(ModelBuilder mb)
{
mb.UseNamedDefaultConstraints();
}


Полный список новинок можно посмотреть здесь

Источник: https://www.infoq.com/news/2025/06/dotnet-10-preview-5/
👍4