ΠΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΎΡΠ΅Π½Ρ Π²Π°ΠΆΠ½ΡΠΌ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠΌ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°, Π½ΠΎ ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΡΠ°ΡΠΏΡΠ΅Π΄Π΅Π»ΡΠ½Π½ΡΡ ΡΠΈΡΡΠ΅ΠΌ ΠΎΠ½ΠΎ ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡ ΠΊΠ°ΠΌΠ½Π΅ΠΌ, ΠΊΠΎΡΠΎΡΡΠΉ Π½ΡΠΆΠ½ΠΎ Π·Π°Π»ΠΎΠΆΠΈΡΡ ΠΏΡΡΠΌΠΎ Π² ΡΡΠ½Π΄Π°ΠΌΠ΅Π½Ρ Π²Π°ΡΠ΅Π³ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, ΠΈΠ½Π°ΡΠ΅ ΡΠ»ΠΎΠΆΠ½ΠΎΡΡΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠΎΠ² ΠΎΡΠ΅Π½Ρ Π±ΡΡΡΡΠΎ Π΄Π°ΡΡ ΠΎ ΡΠ΅Π±Π΅ Π·Π½Π°ΡΡ.
Π .Net Core 3 Π΄ΠΎΠ±Π°Π²ΠΈΠ»Π°ΡΡ ΠΎΡΠ»ΠΈΡΠ½Π°Ρ
Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ ΠΌΡ Π²ΠΎΠ·ΡΠΌΡΠΌ ΠΏΡΠΎΡΡΠΎΠ΅ Π²Π΅Π±-Π°ΠΏΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΈ ΠΎΡΠ³Π°Π½ΠΈΠ·ΡΠ΅ΠΌ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π±ΡΠ΄Π΅Ρ
-
ΡΠΎΡ ΡΠ°Π½ΡΡΡ ΡΠΊΠ²ΠΎΠ·Π½ΡΡ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ Π»ΠΎΠ³Π°ΠΌΠΈ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΡΡ ΡΠ΅ΡΠ²ΠΈΡΠΎΠ² ΡΠ°ΠΊ, ΡΡΠΎΠ±Ρ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ Π²ΡΠ΅ Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π±ΡΠ»ΠΈ Π²ΡΠ·Π²Π°Π½Ρ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΌ Π·Π°ΠΏΡΠΎΡΠΎΠΌ Ρ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°
-
ΠΈΠΌΠ΅ΡΡ Π΅Π΄ΠΈΠ½ΡΡ ΡΠΎΡΠΊΡ Π²Ρ ΠΎΠ΄Π° Ρ ΡΠ΄ΠΎΠ±Π½ΡΠΌ Π°Π½Π°Π»ΠΈΠ·ΠΎΠΌ, ΡΡΠΎΠ±Ρ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠΌ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΠΌΠΎΠ³Π»Π° ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ Π΄Π°ΠΆΠ΅ ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ°, ΠΊ ΠΊΠΎΡΠΎΡΠΎΠΉ Π»Π΅ΡΡΡ Π²ΠΎΠΏΡΠΎΡΡ Π²ΡΠΎΠ΄Π΅ Β«Ρ ΠΌΠ΅Π½Ρ ΡΡΡ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Π²ΡΡΠΊΠΎΡΠΈΠ»Π° ΠΎΡΠΈΠ±ΠΊΠ° Ρ ΡΠ°ΠΊΠΈΠΌ-ΡΠΎ Π°ΠΉΠ΄ΠΈΡΠ½ΠΈΠΊΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ°Β»
ΠΠΎ-ΠΏΠ΅ΡΠ²ΡΡ , Π½Π°ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡΡΡ Ρ ΠΏΠΎΡΡΠ°Π²ΡΠΈΠΊΠΎΠΌ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π² Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ. ΠΠ»Π°Π²Π½ΠΎΠ΅ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΌΡ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΡΠΎ ΡΡΡΡΠΊΡΡΡΠ½ΠΎΡΡΡ, Ρ.Π΅. ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π½Π΅ Ρ ΠΏΠ»ΠΎΡΠΊΠΈΠΌΠΈ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠΌΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡΠΌΠΈ, Π° Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌΠΈ. ΠΠ»Π°Π³ΠΎΠ΄Π°ΡΡ ΡΠ°ΠΊΠΈΠΌ Π»ΠΎΠ³Π°ΠΌ ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π»Π΅Π³ΠΊΠΎ ΡΡΡΠΎΠΈΡΡ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΡ Π½Π°ΡΠΈΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ Π² ΡΠ°Π·Π½ΡΡ ΡΠ°Π·ΡΠ΅Π·Π°Ρ ΠΈ ΠΏΡΠΎΠ²ΠΎΠ΄ΠΈΡΡ Π°Π½Π°Π»ΠΈΡΠΈΠΊΡ.
ΠΠ»Ρ Π½Π°ΡΠ΅Π³ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΌΡ Π²ΠΎΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ Serilog (Π‘Π΅ΡΠΈΠ»ΠΎΠ³), ΠΊΠΎΡΠΎΡΡΠΉ ΠΈΠΌΠ΅Π΅Ρ ΠΎΡΠ»ΠΈΡΠ½ΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ ΡΡΡΡΠΊΡΡΡΠ½ΠΎΠ³ΠΎ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΈ Π±ΠΎΠ³Π°ΡΡΡ ΡΠΈΡΡΠ΅ΠΌΡ Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΉ. Π― ΠΎΠΏΡΡΡ Π±Π°Π·ΠΎΠ²ΡΠ΅ ΡΡΠ°ΠΏΡ Π΅Π³ΠΎ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ (Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π½Π°ΠΉΡΠΈ Π±ΠΎΠ»ΡΡΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΡΠ°ΡΠ΅ΠΉ Π½Π° ΡΡΡ ΡΠ΅ΠΌΡ) ΠΈ ΡΠ΄Π΅Π»Π°Ρ Π΄ΠΎΠΏΡΡΠ΅Π½ΠΈΠ΅ ΠΎ ΡΠΎΠΌ, ΡΡΠΎ
-
Π‘Π΅ΡΠΈΠ»ΠΎΠ³ ΡΠΆΠ΅ ΡΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΠΎΠ²Π°Π½ ΠΈ ΡΠ²Π»ΡΠ΅ΡΡΡ Π»ΠΎΠ³Π΅ΡΠΎΠΌ ΠΏΠΎ-ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ Ρ Π²Π°ΡΠ΅Π³ΠΎ ΠΏΠΎΡΡΠ°Π²ΡΠΈΠΊΠ° Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ
-
Π² Π΅Π³ΠΎ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΎ ΠΎΠ±ΠΎΠ³Π°ΡΠ΅Π½ΠΈΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌΠΈ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ° (Enrich.FromLogContext)
Π‘Π»Π΅Π΄ΡΡΡΠΈΠΌ ΡΠ°Π³ΠΎΠΌ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ Π²ΡΠ±ΡΠ°ΡΡ Π² ΠΊΠ°ΠΊΡΡ ΡΠΈΡΡΠ΅ΠΌΡ ΡΠ΅Π½ΡΡΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΡΠ±ΠΎΡΠ° Π»ΠΎΠ³ΠΎΠ² ΠΏΠΎΡΡΠ»Π°ΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΈΠ· Serilog. ΠΠΎΠΆΠ°Π»ΡΠΉ, ΡΠ°ΠΌΡΠΉ ΡΠ°ΡΠΏΡΠΎΡΡΡΠ°Π½ΡΠ½Π½ΡΠΉ Π½Π° ΡΠ΅Π³ΠΎΠ΄Π½Ρ Π²Π°ΡΠΈΠ°Π½Ρ ΠΈΠ· ΠΎΡΠΊΡΡΡΠΎΠ³ΠΎ ΠΠ ΡΡΠΎ ΡΡΠ΅ΠΊ ELK (Elasticsearch, Logstash ΠΈ Kibana), Π΅Π³ΠΎ ΠΈ Π²ΠΎΠ·ΡΠΌΡΠΌ. ΠΠ»Ρ ΡΡΠΎΠ³ΠΎ Π²ΠΎΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΡ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΠΎΡ
ΠΠ°ΠΌ ΠΎΡΡΠ°ΡΡΡΡ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π² Π½Π°Ρ ΠΏΡΠΎΠ΅ΠΊΡ ΠΏΠ°ΠΊΠ΅Ρ
Install-Package Serilog.Sinks.Logzio
Π Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΡΠ½ΡΠΈΡΠ΅Ρ Π² ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ Π½Π°ΡΠ΅Π³ΠΎ Π»ΠΎΠ³Π΅ΡΠ°, ΡΠΊΠΎΡΠΌΠΈΠ² Π΅ΠΌΡ ΡΠΎΠΊΠ΅Π½ Π΄ΠΎΡΡΡΠΏΠ°
LoggerConfiguration loggerConfig = new LoggerConfiguration();
loggerConfig.WriteTo.Logzio(secrets.LogzioToken, 10, TimeSpan.FromSeconds(10), null, LogEventLevel.Debug);
ΠΠ°ΠΏΡΡΡΠΈΠ² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΡ ΡΠΌΠΎΠΆΠ΅ΠΌ Π½Π°Π±Π»ΡΠ΄Π°ΡΡ Π½Π°ΡΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ Π² ΠΊΠΎΠ½ΡΠΎΠ»ΠΈ, Π½ΠΎ ΠΈ Π² ΠΠΈΠ±Π°Π½Π΅.
ΠΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ
Π ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ ΡΠ΅ΡΠ²ΠΈΡΠ½ΠΎΠ³ΠΎ ΡΠΈΠΏΠ° ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΠ΄Π΅Π»ΠΈΡΡ Π΄Π²Π° Π³Π»Π°Π²Π½ΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° Π΅Π³ΠΎ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ Ρ Π²Π½Π΅ΡΠ½ΠΈΠΌ ΠΌΠΈΡΠΎΠΌ, ΠΎΠ±ΠΎΠ·Π½Π°ΡΠΈΠΌ ΠΈΡ ΠΊΠ°ΠΊ Π²Π΅ΡΡΠΈΠΊΠ°Π»ΡΠ½ΡΠΉ ΠΈ Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΡΠΉ. ΠΠ΅ΡΡΠΈΠΊΠ°Π»ΡΠ½ΡΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ β ΡΡΠΎ Π²Π΅Π±-Π°ΠΏΠΈ, ΡΠ΅ΡΠ΅Π· ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΡΠΈΠ»Π΅ΡΠ°ΡΡ Π²ΡΠ·ΠΎΠ²Ρ ΠΎΡ ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΎΠ³ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ. ΠΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΡΠΉ β ΡΡΠΎ Π±ΡΠΎΠΊΠ΅Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ ΠΎΠ±ΠΌΠ΅Π½Π° Π΄Π°Π½Π½ΡΠΌΠΈ Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠΌΠΈ ΡΠ΅ΡΠ²ΠΈΡΠ°ΠΌΠΈ.
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΡΡΠ°ΠΏΡ Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΡ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΠΎΠ½Π½ΠΎΡΡΠΈ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΈΠ· ΡΡΠΈΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ².
ΠΠΎΡΠ΅Π»Π»ΡΡΠΈΡ Π² HTTP-Π·Π°ΠΏΡΠΎΡΠ°Ρ
Π§ΡΠΎΠ±Ρ ΠΏΠΎΠ»ΡΡΠ°ΡΡ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π±ΠΎΠ»ΡΡΠ΅ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ Π½Π°ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΠΈ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π±Π»ΠΈΠΆΠ΅ ΠΊ Π½Π°ΡΠ°Π»Ρ Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈ, Ρ.Π΅. Π½Π° ΡΠ»ΡΠ·Π΅ ΠΈΠ»ΠΈ ΠΏΡΡΠΌΠΎ Π½Π° ΠΊΠ»ΠΈΠ΅Π½ΡΠ΅ (ΠΌΠΎΠ±ΠΈΠ»ΡΠ½ΠΎΠΌ ΠΈΠ»ΠΈ Π²Π΅Π±). ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΌΡ ΡΠ΅Π³ΠΎΠ΄Π½Ρ ΠΈΠΌΠ΅Π΅ΠΌ Π΄Π΅Π»ΠΎ Ρ Π±Π΅ΠΊΠ΅Π½Π΄Π½ΡΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ, ΡΠΎ ΠΏΡΠΎΡΡΠΎ ΠΎΠ±ΠΎΠ·Π½Π°ΡΠΈΠΌ Π½Π° Π½ΡΠΌ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎΠ³ΠΎ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° Β«X-Correlation-IDΒ» Π²ΠΎ Π²ΡΠ΅Ρ Π·Π°ΠΏΡΠΎΡΠ°Ρ ΠΊ Π²Π΅Π±-Π°ΠΏΠΈ.
ΠΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΠΏΠ°ΠΊΠ΅Ρ
Install-Package CorrelationID
ΠΠΎΠ±Π°Π²ΠΈΠΌ Π΅Π³ΠΎ Π² ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π·Π°ΠΏΡΠΎΡΠ°
public class Startup
{
public void Configure(IApplicationBuilder application)
{
application
.UseCorrelationId(new CorrelationIdOptions
{
Header = "X-Correlation-ID",
IncludeInResponse = false,
UpdateTraceIdentifier = false,
UseGuidForCorrelationId = false
});
}
}
Π’Π΅ΠΏΠ΅ΡΡ Ρ Π΅Π³ΠΎ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠ΄Π΅Π»Π°Π΅ΠΌ ΠΏΡΠΎΡΡΠΎΠΉ action-ΡΠΈΠ»ΡΡΡ:
public sealed class ApiRequestFilter : ActionFilterAttribute
{
public ApiRequestFilter(IApiRequestTracker apiRequestTracker, ICorrelationContextAccessor correlationContextAccessor)
{
_correlationContextAccessor = correlationContextAccessor ?? throw new ArgumentNullException(nameof(correlationContextAccessor));
}
private readonly ICorrelationContextAccessor _correlationContextAccessor;
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (!Guid.TryParse(_correlationContextAccessor.CorrelationContext.CorrelationId, out Guid correlationId))
{
context.Result = new BadRequestResult();
return;
}
await next.Invoke();
}
public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
await next.Invoke();
}
}
Π Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π΅Π³ΠΎ Π² ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅Ρ
[Route("[controller]")]
[ApiController]
[ServiceFilter(typeof(ApiRequestFilter))]
public class CarsController : ControllerBase
{
}
Π ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅Ρ ΡΡΠ°Π½Π΅Ρ Π²ΡΠ²ΠΎΠ΄ΠΈΡΡ 400 Bad request Π½Π° Π²ΡΠ΅ Π·Π°ΠΏΡΠΎΡΡ Π±Π΅Π· Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° Ρ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΌ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΎΠΌ.
ΠΠΎΡΠ»Π΅ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΌΡ ΡΡΠ°Π»ΠΈ ΠΏΠΎΠ»ΡΡΠ°ΡΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΎΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π΅Π³ΠΎ Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ ΠΆΡΡΠ½Π°Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ, ΡΠ΄Π΅Π»Π°Π΅ΠΌ Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ ΠΎΠ±ΡΠ°ΠΌΠ»ΡΡΡΡΡ ΠΏΡΠΎΡΠ»ΠΎΠΉΠΊΡ:
public class CorrelationIdContextLogger
{
public CorrelationIdContextLogger(RequestDelegate next)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
}
readonly RequestDelegate _next;
public async Task InvokeAsync(HttpContext httpContext, ILogger<CorrelationIdContextLogger> logger, ICorrelationContextAccessor correlationContextAccessor)
{
if (Guid.TryParse(correlationContextAccessor.CorrelationContext.CorrelationId, out Guid correlationId))
{
using (logger.BeginScopeWith(("CorrelationId", correlationId)))
{
await _next(context);
}
}
else
{
await _next(context);
}
}
}
Π Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ ΠΌΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ILogger ΠΈΠ· ΠΏΠ°ΠΊΠ΅ΡΠ° Microsoft.Extensions.Logging.Abstractions, ΠΏΠΎΡΡΠΎΠΌΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π±ΡΠ΄Π΅ΠΌ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π½Π΅Ρ ΠΈΡΡΠΎΠ³ΠΎ ΡΠ°ΡΡΠΈΡΠ΅Π½ΠΈΡ ΠΊ Π½Π΅ΠΌΡ.
public static IDisposable BeginScopeWith(this ILogger logger, params (string key, object value)[] keys)
{
return logger.BeginScope(keys.ToDictionary(x => x.key, x => x.value));
}
ΠΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΠΏΡΠΎΡΠ»ΠΎΠΉΠΊΡ Π² ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Π·Π°ΠΏΡΠΎΡΠ° ΠΈ ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ Π½ΡΠΆΠ½ΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ.
public class Startup
{
public void Configure(IApplicationBuilder application)
{
application.UseMiddleware<CorrelationIdContextLogger>();
}
}
Π’Π΅ΠΏΠ΅ΡΡ Π²ΡΠ΅ Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΠΎΡΠΎΠΆΠ΄Π΅Π½Ρ Π·Π°ΠΏΡΠΎΡΠ°ΠΌΠΈ ΠΊ Π½Π°ΡΠ΅ΠΌΡ Π²Π΅Π±-Π°ΠΏΠΈ, ΡΠΎΠ΄Π΅ΡΠΆΠ°Ρ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΠΎΠ½Π½ΡΠΉ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΏΠΎ ΠΊΠΎΡΠΎΡΠΎΠΌΡ ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ ΡΠ²ΡΠ·Π°ΡΡ.
ΠΠΎΡΠ΅Π»Π»ΡΡΠΈΡ Π² ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡΡ Π±ΡΠΎΠΊΠ΅ΡΠ°
Π‘Π»Π΅Π΄ΡΡΡΠΈΠΌ ΡΠ°Π³ΠΎΠΌ Π½Π°ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π½Π°Π»Π°Π΄ΠΈΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΈ ΠΏΡΠΈΡΠΌ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΠΎΠ½Π½ΠΎΠ³ΠΎ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠ° ΡΠ΅ΡΠ΅Π· Π±ΡΠΎΠΊΠ΅Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ. Π Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΠΌΡ Π±ΡΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ RabbitMQ, Π° Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° Π²ΠΎΠ·ΡΠΌΡΠΌ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ MassTransit (ΠΠ°ΡΡΠ’ΡΠ°Π½Π·ΠΈΡ). ΠΠΏΡΡΡ ΠΆΠ΅, ΠΎΠΏΡΡΡΠΈΠΌ ΠΏΠ΅ΡΠ²ΠΎΠ½Π°ΡΠ°Π»ΡΠ½ΡΡ Π½Π°ΡΡΡΠΎΠΉΠΊΡ ΡΠ°Π±ΠΎΡΡ Ρ ΠΠ°ΡΡΠ’ΡΠ°Π½Π·ΠΈΡΠ° ΠΈ ΠΏΠ΅ΡΠ΅ΠΉΠ΄ΡΠΌ ΡΡΠ°Π·Ρ ΠΊ Π½Π°ΡΡΡΠΎΠΉΠΊΠ΅ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ.
ΠΠ»Ρ Π½Π°ΡΠ°Π»Π° ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΊΠ»ΡΡΠΈΡΡ Π»ΠΎΠ³ΠΈ ΡΠ°ΠΌΠΎΠ³ΠΎ ΠΠ°ΡΡΠ’ΡΠ°Π½Π·ΠΈΡΠ°, Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² Π½Π°ΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠ°ΠΊΠ΅Ρ
Install-Package MassTransit.SerilogIntegration
Π’Π΅ΠΏΠ΅ΡΡ ΠΏΠΎΡΠ»Π΅ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΡ Π»ΠΎΠ³Π΅ΡΠ° Π² Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ MassTransit ΠΌΡ ΡΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΈΠ΄Π΅ΡΡ Π»ΠΎΠ³ΠΈ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠ°.
services
.AddSingleton(provider =>
{
return Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.UseSerilog();
});
});
ΠΡΡΡΡ Π½Π°ΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΡΠ΅Π°ΠΊΡΠΈΠΈ Π½Π° POST-Π·Π°ΠΏΡΠΎΡ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅Ρ ΡΠΎΠ±ΡΡΠΈΠ΅ SomethingDoneMessage ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ Β«doneΒ». ΠΠΎΠ½ΡΡΠ°ΠΊΡ ΡΠ°ΠΊΠΎΠ³ΠΎ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΠΈΡΠ°ΡΡ ΡΠ°ΠΊ:
namespace MbMessages
{
public interface ISomethingDoneMessageV1
{
string Value { get; }
}
}
Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΠ°ΡΡΠ’ΡΠ°Π½Π·ΠΈΡΠ° ΠΏΠΎ ΡΡΡΠΈ ΡΠ²Π»ΡΡΡΡΡ ΠΊΠΎΠ½Π²Π΅ΡΡΠΎΠΌ, Π² ΠΊΠΎΡΠΎΡΡΠΉ Π²Π»ΠΎΠΆΠ΅Π½Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π±ΡΠΎΠΊΠ΅ΡΠ°. ΠΡΠ³Π»ΡΠ΄ΠΈΡ ΠΊΠΎΠ½Π²Π΅ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ ΡΠ°ΠΊ:
{
"messageId": "59020000-5dba-0015-10b8-08d77ec28593",
"requestId": "59020000-5dba-0015-5674-08d77ec28592",
"conversationId": "59020000-5dba-0015-bca8-08d77ec28594",
"destinationAddress": "rabbitmq://bear.rmq.cloudamqp.com/aelzlsta/ya.servicetemplate.receiveendpoint",
"headers": {},
"messageType": [
"urn:message:MbMessages:ISomethingDoneMessageV1"
],
"message": {
"value": "done"
}
}
Π ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΈ Π²ΠΈΠ΄Π½Ρ ΡΠ»ΡΠΆΠ΅Π±Π½ΡΠ΅ ΠΏΠΎΠ»Ρ, ΠΊΠΎΡΠΎΡΡΠ΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ ΡΠ°ΠΌΠΎΠ³ΠΎ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠ°, Π½ΠΎ ΠΌΡ ΠΈΠΌΠ΅Π΅ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ Π² ΡΡΠΎΡ ΠΊΠΎΠ½Π²Π΅ΡΡ ΠΈ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ²ΠΎΠΉΡΡΠ²Π°. ΠΠΎΠ»Π΅Π΅ ΡΠΎΠ³ΠΎ, MassTransit ΠΈΠΌΠ΅Π΅Ρ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ ΡΡΠ΅Π΄ΡΡΠ²Π° ΡΠ°Π±ΠΎΡΡ Ρ Π½Π΅ΠΊΠΎΡΠΎΡΡΠΌΠΈ ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΡΠΌΠΈ ΠΏΠΎΠ»ΡΠΌΠΈ, Π±ΠΎΠ»Π΅Π΅ Π²ΡΠ΅Π³ΠΎ ΠΈΠ· ΠΊΠΎΡΠΎΡΡΡ Π½Π°ΠΌ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΠΎΠ½Π½ΠΎΡΡΠΈ CorrelationId.
ΠΠΎΠ±Π°Π²ΠΈΠΌ ΠΊ ΠΊΠΎΠ½ΡΡΠ°ΠΊΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ CorrelatedBy:
namespace MbMessages
{
public interface ISomethingDoneMessageV1 : CorrelatedBy<Guid>
{
string Value { get; }
}
}
Π Π΅Π°Π»ΠΈΠ·ΡΠ΅ΠΌ Π΅Π³ΠΎ ΠΈ Π±ΡΠ΄Π΅ΠΌ ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°ΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΡΠ²ΠΎΠΉΡΡΠ²Ρ CorrelationId ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ:
internal class SomethingDoneMessageV1 : ISomethingDoneMessageV1
{
internal SomethingDoneMessageV1(Guid correlationId, string value)
{
CorrelationId = correlationId;
Value = value;
}
public Guid CorrelationId { get; private set; }
public string Value { get; private set; }
}
ΠΡΠ»ΠΈ ΠΌΡ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° ΠΎΠ±Π½ΠΎΠ²Π»ΡΠ½Π½ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅, ΡΠΎ ΡΠ²ΠΈΠ΄ΠΈΠΌ ΡΡΠΎ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΠΈ ΡΡΠ°Π» Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ°ΡΡΡΡ Π½Π°ΡΠ΅Π³ΠΎ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, Π½ΠΎ ΠΈ ΡΠ°ΡΡΡΡ ΠΊΠΎΠ½Π²Π΅ΡΡΠ° β ΡΡΠΎΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΡΠ΅ΠΏΠ΅ΡΡ Π±ΡΠ΄Π΅Ρ ΡΠ°ΠΊΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ Π²ΠΎ Π²ΡΠ΅Ρ Π»ΠΎΠ³Π°Ρ ΠΠ°ΡΡΠ’ΡΠ°Π½Π·ΠΈΡΠ°, Π° Π·Π½Π°ΡΠΈΡ Π½Π°ΠΌ Π±ΡΠ΄Π΅Ρ Π³ΠΎΡΠ°Π·Π΄ΠΎ ΠΏΡΠΎΡΠ΅ ΡΠ°Π·Π±ΠΈΡΠ°ΡΡΡΡ Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°ΠΌΠΈ Π½Π° ΡΡΠΎΠ²Π½Π΅ Π±ΡΠΎΠΊΠ΅ΡΠ° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ.
{
"messageId": "59020000-5dba-0015-10b8-08d77ec28593",
"requestId": "59020000-5dba-0015-5674-08d77ec28592",
"conversationId": "59020000-5dba-0015-bca8-08d77ec28594",
"correlationId": "c7ff562a-b639-415b-9add-c9e524a727cc",
"destinationAddress": "rabbitmq://bear.rmq.cloudamqp.com/aelzlsta/ya.servicetemplate.receiveendpoint",
"headers": {},
"messageType": [
"urn:message:MbMessages:ISomethingDoneMessageV1"
],
"message": {
"correlationId": "c7ff562a-b639-415b-9add-c9e524a727cc",
"value": "Hello"
}
}
ΠΠ°ΠΌ ΠΎΡΡΠ°Π»ΠΎΡΡ Π½Π°ΡΡΡΠΎΠΈΡΡ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΡΠΈΡ
ΡΠ»ΡΠΆΠ΅Π±Π½ΡΡ
ΡΠ²ΠΎΠΉΡΡΠ² ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² ΠΏΡΠΎΠ΅ΠΊΡ ΠΏΠ°ΠΊΠ΅Ρ
Install-Package Serilog.Enrichers.MassTransitMessage
Π ΠΠ°ΡΡΠ’ΡΠ°Π½Π·ΠΈΡΠ΅ Π²ΡΡΠ°Π²Π»ΡΠ΅ΠΌ ΡΠΈΠ»ΡΡΡ
services
.AddSingleton(provider =>
{
return Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.UseSerilog();
cfg.UseSerilogMessagePropertiesEnricher();
});
});
Π Π² ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π‘Π΅ΡΠΈΠ»ΠΎΠ³Π° Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΡΠ½ΡΠΈΡΠ΅Ρ
Log.Logger = new LoggerConfiguration()
.Enrich.FromMassTransitMessage()
.CreateLogger();
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΈΠ· ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ RabbitMQ, ΠΈΠΌΠ΅Π΅Ρ Π΄ΠΎΡΡΡΠΏ ΠΊΠΎ Π²ΡΠ΅ΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΠΌ ΠΊΠΎΠ½Π²Π΅ΡΡΠ° MassTransit, ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΠΉ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΊΠΎΡΠ΅Π»Π»ΡΡΠΈΠΎΠ½Π½ΠΎΡΡΠΈ Π²Π½ΡΡΡΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ-ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»Ρ, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°ΡΡ Π΅Π³ΠΎ Π΄Π°Π»ΡΡΠ΅ ΠΏΠΎ Π²ΡΠ΅ΠΉ ΡΠ΅ΠΏΠΎΡΠΊΠ΅ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
Π ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ΅ Π½Π°ΡΠΈ Π»ΠΎΠ³ΠΈ ΡΡΠ°Π»ΠΈ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ CorrelationId Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ Π² ΠΏΡΠ΅Π΄Π΅Π»Π°Ρ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡΠ΅ΡΠ²ΠΈΡΠ°, Π½ΠΎ ΠΈ ΠΏΡΠΈ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠΈ Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΠΌΠΈ.
ΠΡΠ°ΠΊ, ΠΏΠΎΠ»ΡΡΠ΅Π½Π½Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π² .Net ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΡ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π½Π°ΠΌ Π±Π΅Π· ΠΎΡΠΎΠ±ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ ΡΠΊΠΎΡΠ΅Π»Π»ΠΈΡΠΎΠ²Π°ΡΡ Π»ΠΎΠ³ΠΈ ΠΈΠ· Π°Π±ΡΠΎΠ»ΡΡΠ½ΠΎ ΡΠ°Π·Π½ΡΡ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠΎΠ² β Π΄Π°ΠΆΠ΅ ΡΠ΅Ρ , ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΠ΅ΡΠ΅Π· Π±ΡΠΎΠΊΠ΅ΡΠ° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ. Π Ρ ΠΏΠΎΠΌΠΎΡΡΡ Elasticsearch ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π±ΡΡΡΡΠΎ ΠΈ ΡΠ΄ΠΎΠ±Π½ΠΎ ΠΏΡΠΎΠ²ΠΎΠ΄ΠΈΡΡ Π°Π½Π°Π»ΠΈΠ· Π»ΠΎΠ³ΠΎΠ², ΠΏΠΎΡΡΡΠΎΠΈΠ² Π² ΠΠΈΠ±Π°Π½Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠ΅ Π½Π°ΠΌ Π΄Π°ΡΠ±ΠΎΡΠ΄Ρ (ΠΏΡΠΈΠΌΠ΅Ρ ΠΏΡΠΈΠ²Π΅Π΄ΡΠ½ Π½Π° ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ΅ ΠΊ ΠΏΠΎΡΡΡ).
Π Π°Π·ΡΠΌΠ΅Π΅ΡΡΡ, Π² ΡΠ°ΠΊΠΎΠΌ Π²ΠΈΠ΄Π΅ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π΅ ΠΏΠΎΠΊΡΠΎΠ΅Ρ ΡΠ»ΠΎΠΆΠ½ΡΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΡ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ Π²Π°ΡΠΈΡ ΡΠ΅ΡΠ²ΠΈΡΠΎΠ² ΠΈ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ Π²Π½Π΅ΡΠ½ΠΈΡ ΡΠΈΡΡΠ΅ΠΌ, Π½ΠΎ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎΠ³ΠΎ ΠΏΠΎΡΡΠ΄ΠΊΠ° Π² ΡΠ°ΠΌΠΎΠΌ Π½Π°ΡΠ°Π»Π΅ ΡΠ°Π·Π²ΠΈΡΠΈΡ ΠΏΡΠΎΠ΅ΠΊΡΠ° β ΡΡΠΎ ΠΎΠ΄Π½Π° ΠΈΠ· ΡΠ΅Ρ Π²Π΅ΡΠ΅ΠΉ, Π·Π° ΠΊΠΎΡΠΎΡΡΠ΅ Π²Ρ ΡΠ°ΠΌΠΈ ΡΠ΅Π±Π΅ Π½Π΅ ΡΠ°Π· ΡΠΊΠ°ΠΆΠ΅ΡΠ΅ ΡΠΏΠ°ΡΠΈΠ±ΠΎ.
ΠΠΎΡΠ°Π·Π±ΠΈΡΠ°ΡΡΡΡ Π² ΠΈΡΡ
ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠΎΠ΄Π΅ ΠΏΠΎΠ»ΡΡΠΈΠ²ΡΠ΅ΠΉΡΡ ΡΠΈΡΡΠ΅ΠΌΡ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π² ΠΏΡΠΎΠ΅ΠΊΡΠ΅:
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com