рд▓реЙрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рд╕рдВрдЧреНрд░рд╣

рдЕрдХреНрд╕рд░ рдЖрдкрдХреЛ рд▓реЙрдЧ рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬреЛ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░ рд╕рдХрддреА рд╣реИ рдФрд░ рдЖрд╡реЗрджрди рдХреЗ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЛ рдФрд░ рд╕рд░рд▓ рдХрд░ рд╕рдХрддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рддреНрд░реБрдЯрд┐ рдЬрд╛рдирдХрд╛рд░реА рд▓реЙрдЧ рд╣реЛрддреА рд╣реИ, рддреЛ рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЛ рдХрд┐рд╕реА рди рдХрд┐рд╕реА рд░реВрдк рдореЗрдВ рд╕рд╣реЗрдЬрдирд╛ рднреА рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛, рддрд╛рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдкреБрди: рдкреЗрд╢ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реЛред рдпрд╣рд╛рдВ рдореИрдВ рдПрдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдЖрдкрдХреЛ рдЗрд╕ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред


рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдмрдпрд╛рди


рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ ASP.NET MVC рд╡реА рд╕рд░реНрд╡рд┐рд╕ рд╣реИред рдпрд╣ POST рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ JSON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреЗ рд╡рд┐рд╡рд░рдг рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕реЗрд╡рд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдХрдИ рдПрд╕рдХреНрдпреВрдПрд▓ рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХрд░рддреА рд╣реИред рд╡рд╣ рдлрд┐рд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреА рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рднреЗрдЬрддреА рд╣реИред


рдпрд╣ рдХрд╣рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпрд╣ рд╕реЗрд╡рд╛ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрд╛ рд╡реНрдпрд╛рдкрдХ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ рдФрд░ рдПрд╕рд┐рдВрдХреНрд╕реНрдЯ / рд╡реЗрдЯ рдФрд░ Task рдорд╛рдзреНрдпрдо рд╕реЗ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХрд░рддреА рд╣реИред


рдЕрдм рдЬрдм рд╣рдо рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдХрд┐рд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЪрд▓рд┐рдП рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреА рдУрд░ рдмрдврд╝рддреЗ рд╣реИрдВред


рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рддреНрд░реБрдЯрд┐ рдЬрд╛рдирдХрд╛рд░реА рдПрдХрддреНрд░рд┐рдд рдХрд░рдирд╛


рдХрднреА-рдХрднреА рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рджреЗрддреА рд╣реИред рдХрд╛рд░рдг рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ: рдЧрд▓рдд рдЗрдирдкреБрдЯ JSON, рдХреЛрдб рдореЗрдВ рдмрдЧ, рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ ... рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рд▓реЙрдЧ рдореЗрдВ рддреНрд░реБрдЯрд┐ рдЬрд╛рдирдХрд╛рд░реА рд▓рд┐рдЦрдиреА рдЪрд╛рд╣рд┐рдПред


рдЕрдкрд╡рд╛рдж рдХреЛ рд▓реЙрдЧ рдХрд░рдиреЗ рдореЗрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред рд╣рдо рдЗрд╕реЗ рдЕрдкрдиреЗ рдирд┐рдпрдВрддреНрд░рдХ рдХреА рдХреНрд░рд┐рдпрд╛ рд╡рд┐рдзрд┐ рдореЗрдВ рдкрдХрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:


 public class ServiceController : ApiController { [Route("api/service")] [HttpPost] public async Task<HttpResponseMessage> ServiceAction( [FromBody] RequestModel requestModel ) { try { ... } catch (Exception ex) { Logger.LogError(ex); throw; } } } 

рдпрд╛ рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡рд┐рд╢реЗрд╖рддрд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:


 public class LogErrorAttribute : ActionFilterAttribute { public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { base.OnActionExecuted(actionExecutedContext); if (actionExecutedContext.Exception != null) { Logger.LogError(actionExecutedContext.Exception); } } } 

рдФрд░ рдЗрд╕рдХрд╛ рдкреНрд░рдпреЛрдЧ рдХреНрд░рд┐рдпрд╛ рд╡рд┐рдзрд┐ рдкрд░ рдХрд░реЗрдВ:


 [Route("api/service")] [HttpPost] [LogError] public async Task<HttpResponseMessage> ServiceAction( [FromBody] RequestModel requestModel ) { ... } 

рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдФрд░ рдЪрд╛рд╣рд┐рдПред рдкреНрд░рддреНрдпреЗрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:


  • рдЕрдиреБрд░реЛрдз рдХреЗ JSON рдирд┐рдХрд╛рдп рдХрд╛ рдкрд╛рдаред
  • рд╕рднреА рдЙрддреНрдкрдиреНрди рдПрд╕рдХреНрдпреВрдПрд▓ рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдкрд╛рдаред

рдПрдХ рдФрд░ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рд▓реЙрдЧ рдореЗрдВ рддрднреА рджрд░реНрдЬ рдХреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП рдЬрдм рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИред рдЕрдиреНрдпрдерд╛, рд╣рдореЗрдВ рд▓реЙрдЧ рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред


рдЕрдиреБрд░реЛрдз рд╢рд░реАрд░ рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ:


 public class ServiceController : ApiController { [Route("api/service")] [HttpPost] public async Task<HttpResponseMessage> ServiceAction( [FromBody] RequestModel requestModel ) { var requestText = await Request.Content.ReadAsStringAsync(); try { ... } catch (Exception ex) { Logger.LogError(ex); Logger.LogError($"Request test is {requestText}"); throw; } } } 

рд▓реЗрдХрд┐рди SQL рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рд▓рд┐рдП, рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдпреЗ рдЕрдиреБрд░реЛрдз рдПрдХреНрд╢рди рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред рд╡реЗ рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рднреА рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред SQL рдмрдирд╛рдиреЗ рдХреА рдХреНрд░рд┐рдпрд╛ рд╡рд┐рдзрд┐ рдФрд░ рд╡рд┐рдзрд┐ рдХреЗ рдмреАрдЪ, рдЕрдиреНрдп рд╡рд░реНрдЧреЛрдВ рдХреЗ рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдХрдИ рдХреЙрд▓ рд╣реИрдВред рдЬрдм рд╣рдореЗрдВ рдЙрдирдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╣рдо рдЗрди рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдкрд╛рда рдХреИрд╕реЗ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ?


рдПрдХ рд╡рд┐рдХрд▓реНрдк рд╕рдВрджреЗрд╢реЛрдВ рдХреА рд╕реВрдЪреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ (рдЙрджрд╛ред List<string> )ред рд╣рдо рдЗрд╕реЗ рдЕрдкрдиреЗ рдПрдХреНрд╢рди рдореЗрдердб ( ServiceAction ) рдореЗрдВ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдЙрд╕ рддрд░реАрдХреЗ рд╕реЗ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ SQL рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред рд╡рд╣рд╛рдВ рд╣рдо рдЗрд╕ рд╕реВрдЪреА рдореЗрдВ SQL рдХреНрд╡реЗрд░реА рдкрд╛рда рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗред рдпрджрд┐ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ, рддреЛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╡рд┐рдзрд┐ рдореЗрдВ рд╕рдВрджреЗрд╢реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реЛрдЧреА, рдЬрд┐рд╕реЗ рд▓реЙрдЧ рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред


рдЗрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ рдПрдХ рдмрд╣реБрдд рд╣реА рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рджреЛрд╖ред рдЬрдм рддрдХ рд╣рдо SQL рдмрдирд╛рдиреЗ рд╡рд╛рд▓реА рд╡рд┐рдзрд┐ рддрдХ рдирд╣реАрдВ рдкрд╣реБрдБрдЪрддреЗ, рддрдм рддрдХ рд╣рдореЗрдВ рдЕрдкрдиреЗ рд╕рдВрджреЗрд╢ рдХреА рд╕реВрдЪреА рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреА рдкреВрд░реА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ рджреЗрдиреА рд╣реЛрдЧреАред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдХрдИ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рд╕рдВрджреЗрд╢реЛрдВ рдХреА рдЗрд╕ рд╕реВрдЪреА рдХреЛ рдХреЗрд╡рд▓ рдЗрд╕реЗ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдпрд╣ рдХреЛрдб рдХреЛ рдЬрдЯрд┐рд▓ рдмрдирд╛рддрд╛ рд╣реИ, рдФрд░ рдореИрдВ рдЗрд╕рд╕реЗ рдмрдЪрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред


рдпрджрд┐ рдЖрдк DI рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЖрдк рдЙрд╕рдореЗрдВ рд╕реЗ рдЕрдкрдиреА рдХрдХреНрд╖рд╛рдПрдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЬреАрд╡рди рднрд░ "рдЕрдиреБрд░реЛрдз" рдХреЗ рд╕рд╛рде рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд╕рдВрджреЗрд╢реЛрдВ рдХреА рд╕реВрдЪреА рдбрд╛рд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред SQL рдЬрдирд░реЗрд╢рди рдХреНрд▓рд╛рд╕ рдЗрд╕ рдореИрд╕реЗрдЬ рд▓рд┐рд╕реНрдЯ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдЧреАред рддрдм рдЗрд╕ рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдФрд░ рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╕рдВрджреЗрд╢ рд╕реВрдЪреА рдХреЗ рдПрдХ рд╣реА рдЙрджрд╛рд╣рд░рдг рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗред


рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк DI рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рднреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдПрдХрддреНрд░ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рд╣реИред рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо рдПрдХ рд╕реНрдерд┐рд░ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдВрджреЗрд╢ рд╕реВрдЪреА рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХреЗрдВ:


 public static async Task<SqlDataReader> RunReaderAsync(this SqlCommand cmd) { var message = $"SQL Server query is: {cmd.CommandText}"; ErrorContext.Current.AttachMessage(message); ... } 

рдпрд╣рд╛рдВ рдПрдХ рдЧрдВрднреАрд░ рд╕рдорд╕реНрдпрд╛ рд╣реИред рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рдПрдХ рд╕рд╛рде рдХрдИ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░ рд╕рдХрддреА рд╣реИред рдФрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдореЗрдВ рд╕рдВрджреЗрд╢реЛрдВ рдХреА рдЕрдкрдиреА рд╕реВрдЪреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рд╣реА рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддреЗ рд╕рдордп, рд╣рдорд╛рд░рд╛ рдХреЛрдб рдХрдИ рдереНрд░реЗрдбреНрд╕ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, async / рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдХреЛ рд╕реНрдкреЙрди рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдФрд░ рдЗрди рд╕рднреА рдереНрд░реЗрдбреНрд╕ рдХреЗ рдкрд╛рд╕ рдПрдХ рд╣реА рд╕рдВрджреЗрд╢ рд╕реВрдЪреА рддрдХ рдкрд╣реБрдВрдЪ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдЗрд╕реЗ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?


AsyncLocal<T> рд╡рд░реНрдЧ рд╣рдорд╛рд░реА рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП рдЖрддрд╛ рд╣реИред рдпрд╣ рдЧрд╛рд░рдВрдЯреА рджреЗрддрд╛ рд╣реИ рдХрд┐ рдпрджрд┐ рдЖрдк рдПрдХ рдзрд╛рдЧреЗ рдореЗрдВ рдЗрд╕ рд╡рд░реНрдЧ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдХреБрдЫ рдореВрд▓реНрдп рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕ рдореВрд▓реНрдп рдХреЛ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рдЕрдм рд╕реЗ рдПрдХ рд╕реЗ рд▓реЙрдиреНрдЪ рдХрд┐рдП рдЧрдП рд╕рднреА рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рднреАред рдЗрд╕реА рд╕рдордп, рдЕрдиреНрдп рд╕рднреА рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рдЗрд╕ рдорд╛рди рддрдХ рдкрд╣реБрдВрдЪ рдирд╣реАрдВ рд╣реЛрдЧреАред


рдЖрдЗрдП ErrorContext рд╡рд░реНрдЧ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ ErrorContext :


 public class ErrorContext { private static readonly object Lock = new object(); private static readonly AsyncLocal<ErrorContext> CurrentErrorContext = new AsyncLocal<ErrorContext>(); private readonly Lazy<ConcurrentBag<string>> _attachedMessages = new Lazy<ConcurrentBag<string>>(() => new ConcurrentBag<string>()); private ErrorContext() {} public static ErrorContext Current { get { lock (Lock) { var errorContext = CurrentErrorContext.Value; if (errorContext == null) { CurrentErrorContext.Value = errorContext = new ErrorContext(); } return errorContext; } } } public static ErrorContext CreateNewErrorContext() { lock (Lock) { var errorContext = new ErrorContext(); CurrentErrorContext.Value = errorContext; return errorContext; } } public void AttachMessage(string message) { if (!string.IsNullOrWhiteSpace(message)) { _attachedMessages.Value.Add(message); } } public IReadOnlyList<string> GetMessages() { return _attachedMessages.Value.ToArray(); } } 

CreateNewErrorContext рд╡рд┐рдзрд┐ рддреБрд░рдВрдд рдПрдХ рдирдИ рд╕рдВрджреЗрд╢ рд╕реВрдЪреА рдмрдирд╛рддреА рд╣реИ рдФрд░ рдЗрд╕реЗ CurrentErrorContext рдлрд╝реАрд▓реНрдб рдореЗрдВ CurrentErrorContext , рдЬреЛ рдХрд┐ AsyncLocal рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реИред рдЖрдк рд╕реНрдерд┐рд░ рд╕рдВрдкрддреНрддрд┐ Current рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЛрдб рдореЗрдВ рдХрд╣реАрдВ рднреА рд╡рд░реНрддрдорд╛рди рд╕реВрдЪреА рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред AttachMessage рдкрджреНрдзрддрд┐ рд╕реВрдЪреА рдореЗрдВ рдПрдХ рдирдпрд╛ рд╕рдВрджреЗрд╢ рдЬреЛрдбрд╝рддреА рд╣реИред рдпрд╣ ConcurrentBag рдПрдХ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд┐рдзрд┐ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдХрдИ рдереНрд░реЗрдбреНрд╕ рд╕реЗ рдХреЙрд▓ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред GetMessages рдкрджреНрдзрддрд┐ рд╕рднреА рд╕рд╣реЗрдЬреЗ рдЧрдП рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рд▓реМрдЯрд╛рддреА рд╣реИ, рддрд╛рдХрд┐ рдЙрдиреНрд╣реЗрдВ рд▓реЙрдЧ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХреЗред


рдЕрдм рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рдЖрд░рдВрдн рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ ErrorContext рдЕрдВрджрд░ LogErrorAttribute рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 public class LogErrorAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { ErrorContext.CreateNewErrorContext(); base.OnActionExecuting(actionContext); } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { base.OnActionExecuted(actionExecutedContext); if (actionExecutedContext.Exception != null) { foreach(var message in ErrorContext.Current.GetMessages()) { Logger.LogError(message); } Logger.LogError(actionExecutedContext.Exception); } } } 

рдЖрдкрдХреЗ рдХреЛрдб рдореЗрдВ рдХрд╣реАрдВ рднреА, рдЖрдк рд╡рд░реНрддрдорд╛рди рддреНрд░реБрдЯрд┐ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЕрдкрдирд╛ рд╕рдВрджреЗрд╢ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:


 ErrorContext.Current.AttachMessage(message); 

рдкреНрд░рджрд░реНрд╢рди рд▓реЙрдЧрд┐рдВрдЧ


рдХрднреА-рдХрднреА рдореЗрд░реА рд╕реЗрд╡рд╛ рдзреАрдореА рд╣реЛрддреА рд╣реИред рд╕рднреА рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдХреБрдЫ рдХреЛ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдореЗрдВ рдмрд╣реБрдд рд▓рдВрдмрд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИред рдореИрдВ рдмрд╛рдж рдореЗрдВ рдЗрд╕рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд░рдЦрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред рдЗрд╕реЗ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рд╣рдореЗрдВ рдХреНрдпрд╛ рдЬрд╛рдирдХрд╛рд░реА рдЪрд╛рд╣рд┐рдП?


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдореБрдЭреЗ рдХреБрдЫ рд░рдирдЯрд╛рдЗрдо рдереНрд░реЗрд╢реЛрд▓реНрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХрдо рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ, рддреЛ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИред рдореИрдВ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд▓реЙрдЧ рдХреЛ рдХреБрдЫ рднреА рдирд╣реАрдВ рд▓рд┐рдЦреВрдВрдЧрд╛ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЗрд╕рдореЗрдВ рдЕрдзрд┐рдХ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ, рддреЛ рдореБрдЭреЗ рд▓реЙрдЧ рдореЗрдВ рдХреБрдЫ рдЬрд╛рдирдХрд╛рд░реА рдЬреЛрдбрд╝рдиреА рд╣реЛрдЧреАред


рдореБрдЭреЗ рдХреНрдпрд╛ рдЬрд╛рдирдХрд╛рд░реА рдЪрд╛рд╣рд┐рдП? рдЖрдкрдХреЛ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдпрд╣ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХрд┐рддрдирд╛ рд╕рдордп рд▓рдЧрд╛ред рд▓реЗрдХрд┐рди рдЗрддрдирд╛ рд╣реА рдХрд╛рдлреА рдирд╣реАрдВ рд╣реИред рдореЗрд░реА рд╕реЗрд╡рд╛ рдмрд╣реБрдд рд╕реА рдЪреАрдЬреЗрдВ рдХрд░рддреА рд╣реИ: рдХреНрд╡реЗрд░реА рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛, рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛, рдПрд╕рдХреНрдпреВрдПрд▓ рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ ... рдореБрдЭреЗ рдпрд╣ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рднрд╛рдЧ рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдХрд┐рддрдирд╛ рд╕рдордп рд▓рдЧрд╛ рдЬрд╣рд╛рдВ рд╕рдорд╕реНрдпрд╛ рдЫрд┐рдкреА рд╣реИред


рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рдореБрдЭреЗ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдЬрд╛рдирдХрд╛рд░реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рдорд╕реНрдпрд╛ рдХреЛ рдкреБрди: рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдПрдХ рдЕрдиреБрд░реЛрдз рдирд┐рдХрд╛рдп рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореБрдЭреЗ рдПрд╕рдХреНрдпреВрдПрд▓ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рдкрд╛рда рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬрдм рд╡реЗ рд╕рдмрд╕реЗ рд▓рдВрдмрд╛ рд╕рдордп рд▓реЗрддреЗ рд╣реИрдВред


рдпрд╣ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдлрд┐рд░ рд╕реЗ, AsyncLocal рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░:


 public class Timer : IDisposable { private static readonly object Lock = new object(); private static readonly AsyncLocal<Timer> CurrentTimer = new AsyncLocal<Timer>(); private readonly Stopwatch _stopwatch = new Stopwatch(); private readonly Lazy<ConcurrentQueue<Timer>> _attachedTimers = new Lazy<ConcurrentQueue<Timer>>(() => new ConcurrentQueue<Timer>()); private readonly Lazy<ConcurrentQueue<string>> _attachedMessages = new Lazy<ConcurrentQueue<string>>(() => new ConcurrentQueue<string>()); private readonly string _description; private readonly TimeSpan? _threshold; private readonly Timer _previousCurrent; private bool _isDisposed; private bool _suspendLogging; private Timer(Timer previousCurrent, string description = null, TimeSpan? threshold = null) { _previousCurrent = previousCurrent; _description = description; _threshold = threshold; _stopwatch.Start(); } public static Timer Current { get { lock (Lock) { var timer = CurrentTimer.Value; if (timer == null) { CurrentTimer.Value = timer = new Timer(null); } return timer; } } } public static Timer SetCurrentTimer(string description, TimeSpan? threshold = null) { lock (Lock) { var currentTimer = CurrentTimer.Value; var timer = new Timer(currentTimer, description, threshold); CurrentTimer.Value = timer; currentTimer?._attachedTimers.Value.Enqueue(timer); return timer; } } public void AttachMessage(string message) { if (!string.IsNullOrWhiteSpace(message)) { _attachedMessages.Value.Enqueue(message); } } public void Dispose() { if (!_isDisposed) { _isDisposed = true; _stopwatch.Stop(); if (_attachedTimers.IsValueCreated) { foreach (var attachedTimer in _attachedTimers.Value) { attachedTimer.Dispose(); } } if (!_suspendLogging && _threshold.HasValue && _stopwatch.Elapsed > _threshold.Value) { Log(); } if (_previousCurrent != null) { CurrentTimer.Value = _previousCurrent; } } } private JObject Message { get { Dispose(); var message = new StringBuilder($"It took {_stopwatch.ElapsedMilliseconds} ms to execute {_description}."); if (_threshold.HasValue) { message.Append($" Duration threshold is {_threshold.Value.TotalMilliseconds} ms."); } var messageObj = new JObject { ["message"] = message.ToString(), }; if (_attachedTimers.IsValueCreated && _attachedTimers.Value.Any()) { messageObj["attachedTimers"] = new JArray(_attachedTimers.Value.Select(t => t.Message)); } if (_attachedMessages.IsValueCreated && _attachedMessages.Value.Any()) { messageObj["attachedMessages"] = new JArray(_attachedMessages.Value); } return messageObj; } } public void Log() { try { _suspendLogging = true; Dispose(); if (_stopwatch.Elapsed < _threshold) { Logger.LogDebug(Message.ToString()); } else { Logger.LogWarning(Message.ToString()); } } finally { _suspendLogging = false; } } } 

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред SetCurrentTimer рд╡рд┐рдзрд┐ рдПрдХ рдирдпрд╛ рдЯрд╛рдЗрдорд░ рдмрдирд╛рддрд╛ рд╣реИред рдпрд╣рд╛рдВ рдЖрдк рдЗрд╕рдХреЗ рд╡рд┐рд╡рд░рдг рдФрд░ рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд░рди-рдЯрд╛рдЗрдо рд╕реАрдорд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдпрд╣ рджрд╣рд▓реАрдЬ рд╡реИрдХрд▓реНрдкрд┐рдХ рдХреНрдпреЛрдВ рд╣реИ? рдХрднреА-рдХрднреА рдореБрдЭреЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордп рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рдЪрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдХреЛрдб рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдЪрд╛рд╣рд┐рдП рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЪрд╛рд╣ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдкреВрд░реЗ рд╕реЗрд╡рд╛ рдЕрдиреБрд░реЛрдз рдХреЛ 3 рд╕реЗрдХрдВрдб рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред рдЕрдиреНрдп рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдореИрдВ рд░рдирдЯрд╛рдЗрдо рдкрд░ рдкреНрд░рддрд┐рдмрдВрдз рдирд╣реАрдВ рд▓рдЧрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореЗрд░реЗ рд▓рд┐рдП рдпрд╣ рдорд╛рдпрдиреЗ рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдореЗрд░реЗ рдПрд╕рдХреНрдпреВрдПрд▓ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХрд┐рддрдирд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдкреВрд░реЗ рд╕реЗрд╡рд╛ рдЕрдиреБрд░реЛрдз рдХреЛ 3 рд╕реЗрдХрдВрдб рд╕реЗ рдХрдо рд╕рдордп рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ, рдХреБрдЫ рдЯрд╛рдЗрдорд░ рдХреЗ рд▓рд┐рдП, рдПрдХ рд░рди-рдЯрд╛рдЗрдо рдереНрд░реЗрд╢реЛрд▓реНрдб рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬрдмрдХрд┐ рдЕрдиреНрдп рдХреЗ рд▓рд┐рдП рдпрд╣ рдирд╣реАрдВ рд╣реИред


SetCurrentTimer рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░, рдПрдХ рдирдпрд╛ рдЯрд╛рдЗрдорд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЯрд╛рдЗрдк AsyncLocal рдЪрд░ рдореЗрдВ рдбрд╛рд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдм рдирд╣реАрдВ рд╣реИред рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рдПрдХ рдФрд░ рд╕рдХреНрд░рд┐рдп рдЯрд╛рдЗрдорд░ рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдирдпрд╛ рдЯрд╛рдЗрдорд░ рдореМрдЬреВрджрд╛ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдкреВрд░реЗ рдХреЛрдб рдмреНрд▓реЙрдХ рдФрд░ рдЙрд╕рдХреЗ рднрд╛рдЧреЛрдВ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордп рдХреЛ рдорд╛рдкрдиреЗ рдХреЗ рд▓рд┐рдП рдиреЗрд╕реНрдЯреЗрдб рдЯрд╛рдЗрдорд░ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:


 using (Timer.SetCurrentTimer("The whole block")) { ... using (Timer.SetCurrentTimer("Part 1")) { ... } ... using (Timer.SetCurrentTimer("Part 2")) { ... } ... } 

Current рд╕рдВрдкрддреНрддрд┐ рд╡рд░реНрддрдорд╛рди рдЯрд╛рдЗрдорд░ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИред рдпрджрд┐ рдЖрдк рдЗрд╕рдореЗрдВ рдХреБрдЫ рд╕рдВрджреЗрд╢ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╣реИ:


 var message = $"SQL Server query is: {cmd.CommandText}"; Timer.Current.AttachMessage(message); 

рдпрд╣рд╛рдБ, рд╕рдВрд▓рдЧреНрди рд╕рдВрджреЗрд╢ рдФрд░ рдиреЗрд╕реНрдЯреЗрдб рдЯрд╛рдЗрдорд░ ConcurrentQueue рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдХрд╛ рдХреНрд░рдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реЛ рд╕рдХрддрд╛ рд╣реИред


Message рдкреНрд░реЙрдкрд░реНрдЯреА рдХрд░рдВрдЯ рд╕реЗ рдЗрдХрдареНрдард╛ рдХреА рдЧрдИ рдпреВрдирд┐рдЯ рдореЗрдВ рдЬрдорд╛ рдХрд┐рдП рдЧрдП Message рд▓реМрдЯрд╛ рджреЗрддреА рд╣реИ рдФрд░ рд╕рднреА рдЯрд╛рдЗрдорд░ рдЙрд╕рдореЗрдВ рдвреЗрд░ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдореИрдВ JSON.NET рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ JSON рдХреНрд▓рд╛рд╕реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рднреА рд╕рдВрджреЗрд╢реЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХрд░рддрд╛ рд╣реВрдБред рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдЗрддрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИред рдЖрдк рдХрд┐рд╕реА рднреА рдкреНрд░рд╛рд░реВрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


Log рд╡рд┐рдзрд┐ рдЯрд╛рдЗрдорд░ рдореЗрдВ рд▓реЙрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдЧреНрд░рд╣реАрдд рдЬрд╛рдирдХрд╛рд░реА рд▓рд┐рдЦрддреА рд╣реИ, рднрд▓реЗ рд╣реА рд░рди-рдЯрд╛рдЗрдо рдереНрд░реЗрд╢реЛрд▓реНрдб рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЙрд╕реА рд╕рдордп, Dispose рд╡рд┐рдзрд┐ рд▓реЙрдЧ рдХреЛ рдЬрд╛рдирдХрд╛рд░реА рд▓рд┐рдЦрддреА рд╣реИ рдХреЗрд╡рд▓ рдЕрдЧрд░ рд╕реЗрдЯ рд░рдирдЯрд╛рдЗрдо рдереНрд░реЗрд╢реЛрд▓реНрдб рдкрд╛рд░ рд╣реЛ рдЧрдпрд╛ рд╣реЛред


рдЕрдм рд╣рдо рдЕрдкрдиреЗ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рд╡рд┐рд╢реЗрд╖рддрд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:


 public class TimerContextAttribute : ActionFilterAttribute { private readonly string _timerDescription; private readonly int _durationThresholdMs; private readonly AsyncLocal<Timer> _timer = new AsyncLocal<Timer>(); public TimerContextAttribute(string timerDescription, int durationThresholdMs) { if (string.IsNullOrWhiteSpace(timerDescription)) throw new ArgumentNullException(nameof(timerDescription)); _timerDescription = timerDescription; _durationThresholdMs = durationThresholdMs; } public override void OnActionExecuting(HttpActionContext actionContext) { _timer.Value = Timer.SetCurrentTimer(_timerDescription, TimeSpan.FromMilliseconds(_durationThresholdMs)); base.OnActionExecuting(actionContext); } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { base.OnActionExecuted(actionExecutedContext); _timer.Value?.Dispose(); } } 

рдФрд░ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рдПрдХреНрд╢рди рддрд░реАрдХреЛрдВ рдкрд░ рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВ:


 [Route("api/service")] [HttpPost] [TimerContext("For ServiceAction method", 3000)] public async Task<HttpResponseMessage> ServiceAction( [FromBody] RequestModel requestModel ) { ... } 

рдирд┐рд╖реНрдХрд░реНрд╖


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВрдиреЗ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдХрд┐ рдХреЛрдб рдореЗрдВ рдХрдИ рд╕реНрдерд╛рдиреЛрдВ рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдПрдХрддреНрд░ рдХрд░рдирд╛ рдФрд░ рдмрд╛рдж рдореЗрдВ рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдирд╛ рдХрд┐рддрдирд╛ рд╕рд░рд▓ рд╣реИред рдРрд╕реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд╕реНрдерд┐рд░ рдЧреБрдгреЛрдВ рдФрд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ AsyncLocal рд╡рд░реНрдЧ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд╣реЗрд░рдлреЗрд░ рдХрд░рддреЗ рд╣реИрдВред


рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рд▓реЗрдЦ рдЖрдкрдХреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рд▓реЙрдЧрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред

Source: https://habr.com/ru/post/hi416751/


All Articles