[{"data":1,"prerenderedAt":15326},["ShallowReactive",2],{"navigation_docs":3,"-csharp-aspnet-web-api-health-checks-monitoring":2949,"-csharp-aspnet-web-api-health-checks-monitoring-surround":15321},[4,1640,1765,2219,2352,2559,2641,2691,2748,2782,2908,2945],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"C#","i-devicon-csharp","/csharp","01.csharp",[10,13,60,90,120,202,219,253,379,404,457,650,1346,1636],{"title":11,"path":7,"stem":12},"C# Roadmap","01.csharp/index",{"title":14,"icon":15,"path":16,"stem":17,"children":18,"page":59},"Fundamentals","i-lucide-book-open","/csharp/fundamentals","01.csharp/01.fundamentals",[19,23,27,31,35,39,43,47,51,55],{"title":20,"path":21,"stem":22},"Вступ до екосистеми .NET","/csharp/fundamentals/introduction-to-ecosystem","01.csharp/01.fundamentals/01.introduction-to-ecosystem",{"title":24,"path":25,"stem":26},"Структура програми на C#","/csharp/fundamentals/program-structure","01.csharp/01.fundamentals/02.program-structure",{"title":28,"path":29,"stem":30},"Змінні та Типи Даних","/csharp/fundamentals/variables-data-types","01.csharp/01.fundamentals/03.variables-data-types",{"title":32,"path":33,"stem":34},"Масиви","/csharp/fundamentals/arrays","01.csharp/01.fundamentals/04.arrays",{"title":36,"path":37,"stem":38},"Strings & Text Handling","/csharp/fundamentals/strings-text-handling","01.csharp/01.fundamentals/05.strings-text-handling",{"title":40,"path":41,"stem":42},"Дати і Час","/csharp/fundamentals/dates-time-handling","01.csharp/01.fundamentals/06.dates-time-handling",{"title":44,"path":45,"stem":46},"Потік Керування","/csharp/fundamentals/control-flow","01.csharp/01.fundamentals/07.control-flow",{"title":48,"path":49,"stem":50},"Методи","/csharp/fundamentals/methods","01.csharp/01.fundamentals/08.methods",{"title":52,"path":53,"stem":54},"Основи Відлагодження","/csharp/fundamentals/debugging-basics","01.csharp/01.fundamentals/09.debugging-basics",{"title":56,"path":57,"stem":58},"Інтерактивна Консоль (Classic)","/csharp/fundamentals/interactive-console","01.csharp/01.fundamentals/10.interactive-console",false,{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":59},"OOP","i-lucide-box","/csharp/oop","01.csharp/02.oop",[66,70,74,78,82,86],{"title":67,"path":68,"stem":69},"Package Management (Управління Пакетами)","/csharp/oop/package-management","01.csharp/02.oop/01.package-management",{"title":71,"path":72,"stem":73},"Класи та Об'єкти","/csharp/oop/classes-objects","01.csharp/02.oop/02.classes-objects",{"title":75,"path":76,"stem":77},"Властивості та Поля","/csharp/oop/properties-fields","01.csharp/02.oop/03.properties-fields",{"title":79,"path":80,"stem":81},"Стовпи ООП","/csharp/oop/oop-pillars","01.csharp/02.oop/04.oop-pillars",{"title":83,"path":84,"stem":85},"Advanced Types","/csharp/oop/advanced-types","01.csharp/02.oop/05.advanced-types",{"title":87,"path":88,"stem":89},"Namespaces (Простори Імен)","/csharp/oop/namespaces","01.csharp/02.oop/06.namespaces",{"title":91,"icon":92,"path":93,"stem":94,"children":95,"page":59},"Advanced Core","i-lucide-zap","/csharp/advanced-core","01.csharp/03.advanced-core",[96,100,104,108,112,116],{"title":97,"path":98,"stem":99},"Generics (Узагальнення)","/csharp/advanced-core/generics","01.csharp/03.advanced-core/01.generics",{"title":101,"path":102,"stem":103},"Делегати, Події та Лямбда-вирази","/csharp/advanced-core/delegates-events-lambdas","01.csharp/03.advanced-core/02.delegates-events-lambdas",{"title":105,"path":106,"stem":107},"Interfaces Deep Dive (Інтерфейси: Поглиблений Розгляд)","/csharp/advanced-core/interfaces-deep-dive","01.csharp/03.advanced-core/03.interfaces-deep-dive",{"title":109,"path":110,"stem":111},"Обробка Винятків","/csharp/advanced-core/exception-handling","01.csharp/03.advanced-core/04.exception-handling",{"title":113,"path":114,"stem":115},"Pattern Matching","/csharp/advanced-core/pattern-matching","01.csharp/03.advanced-core/05.pattern-matching",{"title":117,"path":118,"stem":119},"Додаткові Можливості C#","/csharp/advanced-core/additional-features","01.csharp/03.advanced-core/06.additional-features",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":59},"Architecture Best Practices","i-lucide-building-2","/csharp/architecture-best-practices","01.csharp/04.architecture-best-practices",[126,130,149,153,157,161,165,169],{"title":127,"path":128,"stem":129},"Software Design Principles (Частина 1)","/csharp/architecture-best-practices/software-design-principles","01.csharp/04.architecture-best-practices/01.software-design-principles",{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":59},"Design Patterns","i-lucide-folder","/csharp/architecture-best-practices/design-patterns","01.csharp/04.architecture-best-practices/02.design-patterns",[136],{"title":137,"icon":132,"path":138,"stem":139,"children":140,"page":59},"Creational","/csharp/architecture-best-practices/design-patterns/creational","01.csharp/04.architecture-best-practices/02.design-patterns/creational",[141,145],{"title":142,"path":143,"stem":144},"Singleton (Одинак)","/csharp/architecture-best-practices/design-patterns/creational/singleton","01.csharp/04.architecture-best-practices/02.design-patterns/creational/01.singleton",{"title":146,"path":147,"stem":148},"Builder (Будівельник)","/csharp/architecture-best-practices/design-patterns/creational/builder","01.csharp/04.architecture-best-practices/02.design-patterns/creational/02.builder",{"title":150,"path":151,"stem":152},"Building Professional CLIs","/csharp/architecture-best-practices/building-professional-clis","01.csharp/04.architecture-best-practices/03.building-professional-clis",{"title":154,"path":155,"stem":156},"Validation & Flow Control","/csharp/architecture-best-practices/validation-flow-control","01.csharp/04.architecture-best-practices/04.validation-flow-control",{"title":158,"path":159,"stem":160},"The Modern .NET Host (Microsoft.Extensions)","/csharp/architecture-best-practices/modern-dotnet-host","01.csharp/04.architecture-best-practices/05.modern-dotnet-host",{"title":162,"path":163,"stem":164},"Data Mapper: Repository та DAO патерни (Частина 1)","/csharp/architecture-best-practices/data-mapper-part1","01.csharp/04.architecture-best-practices/06.data-mapper-part1",{"title":166,"path":167,"stem":168},"Data Mapper: Repository та DAO патерни (Частина 2)","/csharp/architecture-best-practices/data-mapper-part2","01.csharp/04.architecture-best-practices/07.data-mapper-part2",{"title":170,"icon":132,"path":171,"stem":172,"children":173,"page":59},"Di Ioc","/csharp/architecture-best-practices/di-ioc","01.csharp/04.architecture-best-practices/08.di-ioc",[174,178,182,186,190,194,198],{"title":175,"path":176,"stem":177},"Проблема залежностей та Інверсія Контролю","/csharp/architecture-best-practices/di-ioc/the-dependency-problem","01.csharp/04.architecture-best-practices/08.di-ioc/01.the-dependency-problem",{"title":179,"path":180,"stem":181},"Будуємо власний Service Container","/csharp/architecture-best-practices/di-ioc/build-your-own-container","01.csharp/04.architecture-best-practices/08.di-ioc/02.build-your-own-container",{"title":183,"path":184,"stem":185},"Service Locator: Паттерн та Анти-паттерн","/csharp/architecture-best-practices/di-ioc/service-locator-pattern","01.csharp/04.architecture-best-practices/08.di-ioc/03.service-locator-pattern",{"title":187,"path":188,"stem":189},"Паттерни Dependency Injection","/csharp/architecture-best-practices/di-ioc/dependency-injection-patterns","01.csharp/04.architecture-best-practices/08.di-ioc/04.dependency-injection-patterns",{"title":191,"path":192,"stem":193},"Microsoft DI: IServiceCollection та IServiceProvider","/csharp/architecture-best-practices/di-ioc/microsoft-di-deep-dive","01.csharp/04.architecture-best-practices/08.di-ioc/05.microsoft-di-deep-dive",{"title":195,"path":196,"stem":197},"Service Lifetimes та Scopes","/csharp/architecture-best-practices/di-ioc/service-lifetimes-and-scopes","01.csharp/04.architecture-best-practices/08.di-ioc/06.service-lifetimes-and-scopes",{"title":199,"path":200,"stem":201},"DI Анти-паттерни та Найкращі Практики","/csharp/architecture-best-practices/di-ioc/di-anti-patterns-and-best-practices","01.csharp/04.architecture-best-practices/08.di-ioc/07.di-anti-patterns-and-best-practices",{"title":203,"icon":132,"path":204,"stem":205,"children":206,"page":59},"Standard Library","/csharp/standard-library","01.csharp/05.standard-library",[207,211,215],{"title":208,"path":209,"stem":210},"Collections (Колекції)","/csharp/standard-library/collections","01.csharp/05.standard-library/01.collections",{"title":212,"path":213,"stem":214},"High Performance Types (Високопродуктивні Типи)","/csharp/standard-library/high-performance-types","01.csharp/05.standard-library/02.high-performance-types",{"title":216,"path":217,"stem":218},"LINQ (Language Integrated Query)","/csharp/standard-library/linq","01.csharp/05.standard-library/03.linq",{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":59},"System Internals Concurrency","i-lucide-server","/csharp/system-internals-concurrency","01.csharp/06.system-internals-concurrency",[225,229,233,237,241,245,249],{"title":226,"path":227,"stem":228},"Memory Management","/csharp/system-internals-concurrency/memory-management","01.csharp/06.system-internals-concurrency/01.memory-management",{"title":230,"path":231,"stem":232},"Reflection API: System.Type та Метадані","/csharp/system-internals-concurrency/reflection-fundamentals","01.csharp/06.system-internals-concurrency/02.reflection-fundamentals",{"title":234,"path":235,"stem":236},"Attributes та Dynamic Language Runtime","/csharp/system-internals-concurrency/attributes-dynamic","01.csharp/06.system-internals-concurrency/03.attributes-dynamic",{"title":238,"path":239,"stem":240},"Expression Trees: Швидка Альтернатива Рефлексії","/csharp/system-internals-concurrency/expression-trees-compiled","01.csharp/06.system-internals-concurrency/04.expression-trees-compiled",{"title":242,"path":243,"stem":244},"Source Generators: Compile-Time Code Generation","/csharp/system-internals-concurrency/source-generators","01.csharp/06.system-internals-concurrency/05.source-generators",{"title":246,"path":247,"stem":248},"Multithreading Fundamentals","/csharp/system-internals-concurrency/multithreading-fundamentals","01.csharp/06.system-internals-concurrency/06.multithreading-fundamentals",{"title":250,"path":251,"stem":252},"Synchronization Primitives","/csharp/system-internals-concurrency/synchronization-primitives","01.csharp/06.system-internals-concurrency/07.synchronization-primitives",{"title":254,"icon":255,"path":256,"stem":257,"children":258,"page":59},"System Programming Windows","i-lucide-cpu","/csharp/system-programming-windows","01.csharp/07.system-programming-windows",[259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,355,359,363,367,371,375],{"title":260,"path":261,"stem":262},"Як Працює Операційна Система","/csharp/system-programming-windows/how-os-works","01.csharp/07.system-programming-windows/01.how-os-works",{"title":264,"path":265,"stem":266},"Процеси в .NET — API та Запуск","/csharp/system-programming-windows/processes-in-dotnet","01.csharp/07.system-programming-windows/02.processes-in-dotnet",{"title":268,"path":269,"stem":270},"Процеси в .NET — IPC та Міжпроцесна Комунікація","/csharp/system-programming-windows/02a.processes-ipc","01.csharp/07.system-programming-windows/02a.processes-ipc",{"title":272,"path":273,"stem":274},"Application Domains та Збірки — AppDomain і AssemblyLoadContext","/csharp/system-programming-windows/appdomains-assemblies","01.csharp/07.system-programming-windows/03.appdomains-assemblies",{"title":276,"path":277,"stem":278},"Application Domains та Збірки — Plug-in Система з Hot-Reload","/csharp/system-programming-windows/03a.appdomains-plugin-system","01.csharp/07.system-programming-windows/03a.appdomains-plugin-system",{"title":280,"path":281,"stem":282},"Потоки — Основи та API Thread","/csharp/system-programming-windows/thread-fundamentals","01.csharp/07.system-programming-windows/04.thread-fundamentals",{"title":284,"path":285,"stem":286},"Потоки — Lifecycle, Пріоритети та Безпечне Завершення","/csharp/system-programming-windows/04a.thread-lifecycle-priorities","01.csharp/07.system-programming-windows/04a.thread-lifecycle-priorities",{"title":288,"path":289,"stem":290},"Проблеми Спільного Стану — Race Condition та Data Race","/csharp/system-programming-windows/shared-state-problems","01.csharp/07.system-programming-windows/05.shared-state-problems",{"title":292,"path":293,"stem":294},"Проблеми Спільного Стану — Memory Model та volatile","/csharp/system-programming-windows/05a.shared-state-memory-model","01.csharp/07.system-programming-windows/05a.shared-state-memory-model",{"title":296,"path":297,"stem":298},"Синхронізація — Monitor, lock та еволюція примітивів","/csharp/system-programming-windows/synchronization-fundamentals","01.csharp/07.system-programming-windows/06.synchronization-fundamentals",{"title":300,"path":301,"stem":302},"Синхронізація — Наскрізний Приклад та Deadlock Detection","/csharp/system-programming-windows/06a.synchronization-walkthrough","01.csharp/07.system-programming-windows/06a.synchronization-walkthrough",{"title":304,"path":305,"stem":306},"Синхронізація — Mutex, Semaphore та Event-Based Primitives","/csharp/system-programming-windows/synchronization-advanced","01.csharp/07.system-programming-windows/07.synchronization-advanced",{"title":308,"path":309,"stem":310},"Синхронізація — Interlocked, Volatile та Lock-Free Структури","/csharp/system-programming-windows/07a.synchronization-advanced-walkthrough","01.csharp/07.system-programming-windows/07a.synchronization-advanced-walkthrough",{"title":312,"path":313,"stem":314},"Interlocked, CAS та Lock-Free Структури","/csharp/system-programming-windows/interlocked-cas-lockfree","01.csharp/07.system-programming-windows/08.interlocked-cas-lockfree",{"title":316,"path":317,"stem":318},"Volatile, Memory Model та Spinning","/csharp/system-programming-windows/08a.volatile-memory-model","01.csharp/07.system-programming-windows/08a.volatile-memory-model",{"title":320,"path":321,"stem":322},"ThreadPool — Пул Потоків для Ефективного Виконання","/csharp/system-programming-windows/thread-pool","01.csharp/07.system-programming-windows/09.thread-pool",{"title":324,"path":325,"stem":326},"ThreadPool — Просунуті Сценарії та Внутрішня Будова","/csharp/system-programming-windows/09a.thread-pool-advanced","01.csharp/07.system-programming-windows/09a.thread-pool-advanced",{"title":328,"path":329,"stem":330},"Concurrent та Immutable Collections","/csharp/system-programming-windows/concurrent-collections","01.csharp/07.system-programming-windows/10.concurrent-collections",{"title":332,"path":333,"stem":334},"TPL, Task та Композиція — Від Thread до Task","/csharp/system-programming-windows/tpl-parallel-plinq","01.csharp/07.system-programming-windows/11.tpl-parallel-plinq",{"title":336,"path":337,"stem":338},"Parallel Class та PLINQ — Data Parallelism","/csharp/system-programming-windows/11a.tpl-parallel-plinq-advanced","01.csharp/07.system-programming-windows/11a.tpl-parallel-plinq-advanced",{"title":340,"path":341,"stem":342},"Async/Await — Фундамент Асинхронного Програмування","/csharp/system-programming-windows/async-fundamentals","01.csharp/07.system-programming-windows/12.async-fundamentals",{"title":344,"path":345,"stem":346},"SynchronizationContext та ConfigureAwait — Контекст Виконання","/csharp/system-programming-windows/async-context-configureawait","01.csharp/07.system-programming-windows/13.async-context-configureawait",{"title":348,"path":349,"stem":350},"Async — Просунуті Паттерни","/csharp/system-programming-windows/async-advanced","01.csharp/07.system-programming-windows/14.async-advanced",{"title":352,"path":353,"stem":354},"System.Threading.Channels — Async Producer-Consumer","/csharp/system-programming-windows/channels","01.csharp/07.system-programming-windows/15.channels",{"title":356,"path":357,"stem":358},"Асинхронна Синхронізація","/csharp/system-programming-windows/async-synchronization","01.csharp/07.system-programming-windows/16.async-synchronization",{"title":360,"path":361,"stem":362},"Unsafe Code та Вказівники","/csharp/system-programming-windows/unsafe-code","01.csharp/07.system-programming-windows/17.unsafe-code",{"title":364,"path":365,"stem":366},"P/Invoke та Windows API — Міст між .NET та Native Code","/csharp/system-programming-windows/pinvoke-winapi","01.csharp/07.system-programming-windows/18.pinvoke-winapi",{"title":368,"path":369,"stem":370},"Реєстр Windows — Центральна База Конфігурації Системи","/csharp/system-programming-windows/windows-registry","01.csharp/07.system-programming-windows/19.windows-registry",{"title":372,"path":373,"stem":374},"Windows Hooks, Hotkeys та Services — Глибока Інтеграція з ОС","/csharp/system-programming-windows/windows-hooks-services","01.csharp/07.system-programming-windows/20.windows-hooks-services",{"title":376,"path":377,"stem":378},"Системне Програмування C# (Windows) — 07.system-programming-windows","/csharp/system-programming-windows/implementation_plan","01.csharp/07.system-programming-windows/implementation_plan",{"title":380,"icon":132,"path":381,"stem":382,"children":383,"page":59},"Io","/csharp/io","01.csharp/08.io",[384,388,392,396,400],{"title":385,"path":386,"stem":387},"8.1.1. Основи роботи з файловою системою","/csharp/io/file-system-basics","01.csharp/08.io/01.file-system-basics",{"title":389,"path":390,"stem":391},"8.1.2. Потоки (Streams) та Серіалізація Даних","/csharp/io/streams-serialization","01.csharp/08.io/02.streams-serialization",{"title":393,"path":394,"stem":395},"8.2.1. JSON Serialization з System.Text.Json","/csharp/io/json-serialization","01.csharp/08.io/03.json-serialization",{"title":397,"path":398,"stem":399},"8.2.2. XML Serialization та LINQ to XML","/csharp/io/xml-serialization","01.csharp/08.io/04.xml-serialization",{"title":401,"path":402,"stem":403},"8.2.3. Binary Serialization: MessagePack та Protocol Buffers","/csharp/io/binary-serialization","01.csharp/08.io/05.binary-serialization",{"title":405,"icon":132,"path":406,"stem":407,"children":408,"page":59},"Ado Net","/csharp/ado-net","01.csharp/09.ado-net",[409,413,417,421,425,429,433,437,441,445,449,453],{"title":410,"path":411,"stem":412},"9.1. Введення в ADO.NET","/csharp/ado-net/introduction-to-adonet","01.csharp/09.ado-net/01.introduction-to-adonet",{"title":414,"path":415,"stem":416},"9.2. Клас DbConnection — з'єднання з базою даних","/csharp/ado-net/connection","01.csharp/09.ado-net/02.connection",{"title":418,"path":419,"stem":420},"9.3. Клас DbCommand — виконання SQL-запитів","/csharp/ado-net/command-and-queries","01.csharp/09.ado-net/03.command-and-queries",{"title":422,"path":423,"stem":424},"9.4. Клас DbDataReader — ефективне читання даних","/csharp/ado-net/datareader","01.csharp/09.ado-net/04.datareader",{"title":426,"path":427,"stem":428},"9.5. Параметризовані запити та захист від SQL Injection","/csharp/ado-net/parameters-and-sql-injection","01.csharp/09.ado-net/05.parameters-and-sql-injection",{"title":430,"path":431,"stem":432},"9.6. Транзакції в ADO.NET","/csharp/ado-net/transactions","01.csharp/09.ado-net/06.transactions",{"title":434,"path":435,"stem":436},"9.7. DbProviderFactory — провайдер-незалежний код","/csharp/ado-net/provider-factory","01.csharp/09.ado-net/07.provider-factory",{"title":438,"path":439,"stem":440},"9.8. Асинхронний доступ до даних","/csharp/ado-net/async-data-access","01.csharp/09.ado-net/08.async-data-access",{"title":442,"path":443,"stem":444},"9.9. Від'єднаний режим: DataSet, DataTable, DataRow","/csharp/ado-net/disconnected-mode-dataset","01.csharp/09.ado-net/09.disconnected-mode-dataset",{"title":446,"path":447,"stem":448},"9.10. DataAdapter — міст між DataSet та базою даних","/csharp/ado-net/data-adapter","01.csharp/09.ado-net/10.data-adapter",{"title":450,"path":451,"stem":452},"9.11. Data Mapper та Repository: Архітектура доступу до даних","/csharp/ado-net/data-mapper-repository","01.csharp/09.ado-net/11.data-mapper-repository",{"title":454,"path":455,"stem":456},"9.12. Identity Map, Unit of Work та Specification Pattern","/csharp/ado-net/advanced-patterns","01.csharp/09.ado-net/12.advanced-patterns",{"title":458,"icon":255,"path":459,"stem":460,"children":461,"page":59},"Ef Core","/csharp/ef-core","01.csharp/10.ef-core",[462,466,470,474,478,482,486,490,494,498,502,506,510,514,518,522,526,532,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646],{"title":463,"path":464,"stem":465},"Що таке ORM? Від SQL до об'єктів","/csharp/ef-core/what-is-orm","01.csharp/10.ef-core/01.what-is-orm",{"title":467,"path":468,"stem":469},"Перший проєкт — від нуля до CRUD","/csharp/ef-core/first-project","01.csharp/10.ef-core/02.first-project",{"title":471,"path":472,"stem":473},"DbContext — Серце EF Core","/csharp/ef-core/dbcontext-deep-dive","01.csharp/10.ef-core/03.dbcontext-deep-dive",{"title":475,"path":476,"stem":477},"Провайдери баз даних — Архітектура та Вибір СУБД","/csharp/ef-core/database-providers","01.csharp/10.ef-core/04.database-providers",{"title":479,"path":480,"stem":481},"Конвенції EF Core — Магія без конфігурації","/csharp/ef-core/conventions","01.csharp/10.ef-core/05.conventions",{"title":483,"path":484,"stem":485},"Fluent API та Data Annotations — Явна конфігурація моделі","/csharp/ef-core/fluent-api-vs-annotations","01.csharp/10.ef-core/06.fluent-api-vs-annotations",{"title":487,"path":488,"stem":489},"Зв'язки — One-to-One та One-to-Many","/csharp/ef-core/relationships-basics","01.csharp/10.ef-core/07.relationships-basics",{"title":491,"path":492,"stem":493},"Зв'язки Advanced — Many-to-Many та Складні Сценарії","/csharp/ef-core/relationships-advanced","01.csharp/10.ef-core/08.relationships-advanced",{"title":495,"path":496,"stem":497},"Властивості — Типи, Конвертери, Компаратори (Частина 1)","/csharp/ef-core/property-configuration-part1","01.csharp/10.ef-core/09.property-configuration-part1",{"title":499,"path":500,"stem":501},"Властивості — Value Comparers, Generators, Shadow Properties (Частина 2)","/csharp/ef-core/property-configuration-part2","01.csharp/10.ef-core/09.property-configuration-part2",{"title":503,"path":504,"stem":505},"Складні типи — Owned Types та Complex Types (Частина 1)","/csharp/ef-core/complex-types-owned-part1","01.csharp/10.ef-core/10.complex-types-owned-part1",{"title":507,"path":508,"stem":509},"Складні типи — Complex Types, Keyless Entities, Порівняння (Частина 2)","/csharp/ef-core/complex-types-owned-part2","01.csharp/10.ef-core/10.complex-types-owned-part2",{"title":511,"path":512,"stem":513},"JSON Columns — Складні дані у JSON (Частина 1)","/csharp/ef-core/json-columns-part1","01.csharp/10.ef-core/11.json-columns-part1",{"title":515,"path":516,"stem":517},"JSON Columns — Value Comparers, Індекси, Провайдери (Частина 2)","/csharp/ef-core/json-columns-part2","01.csharp/10.ef-core/11.json-columns-part2",{"title":519,"path":520,"stem":521},"Успадкування — Абстрактні класи та TPH (Частина 1)","/csharp/ef-core/inheritance-part1","01.csharp/10.ef-core/12.inheritance-part1",{"title":523,"path":524,"stem":525},"Успадкування — TPT, TPC та Порівняння Стратегій (Частина 2)","/csharp/ef-core/inheritance-part2","01.csharp/10.ef-core/12.inheritance-part2",{"title":527,"path":528,"stem":529,"children":530},"Індекси, Обмеження та Схема (Частина 1)","/csharp/ef-core/indexes-constraints-part1","01.csharp/10.ef-core/13.indexes-constraints-part1",[531],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"Індекси, Обмеження та Схема (Частина 2)","/csharp/ef-core/indexes-constraints-part2","01.csharp/10.ef-core/13.indexes-constraints-part2",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541},"Seed Data — Початкові Дані (Частина 1)","/csharp/ef-core/seeding-part1","01.csharp/10.ef-core/14.seeding-part1",{"title":543,"path":544,"stem":545},"Seed Data — SQL-скрипти, Bogus та Стратегії (Частина 2)","/csharp/ef-core/seeding-part2","01.csharp/10.ef-core/14.seeding-part2",{"title":547,"path":548,"stem":549},"Global Query Filters — Глобальні Фільтри (Частина 1)","/csharp/ef-core/global-query-filters-part1","01.csharp/10.ef-core/15.global-query-filters-part1",{"title":551,"path":552,"stem":553},"Global Query Filters — Підводні камені та Інтеграція (Частина 2)","/csharp/ef-core/global-query-filters-part2","01.csharp/10.ef-core/15.global-query-filters-part2",{"title":555,"path":556,"stem":557},"LINQ-запити в EF Core (Частина 1)","/csharp/ef-core/linq-queries-part1","01.csharp/10.ef-core/16.linq-queries-part1",{"title":559,"path":560,"stem":561},"LINQ-запити в EF Core (Частина 2)","/csharp/ef-core/linq-queries-part2","01.csharp/10.ef-core/16.linq-queries-part2",{"title":563,"path":564,"stem":565},"Завантаження Пов'язаних Даних (Частина 1)","/csharp/ef-core/loading-related-data-part1","01.csharp/10.ef-core/17.loading-related-data-part1",{"title":567,"path":568,"stem":569},"Завантаження Пов'язаних Даних (Частина 2)","/csharp/ef-core/loading-related-data-part2","01.csharp/10.ef-core/17.loading-related-data-part2",{"title":571,"path":572,"stem":573},"Raw SQL, Views та Stored Procedures (Частина 1)","/csharp/ef-core/raw-sql-part1","01.csharp/10.ef-core/18.raw-sql-part1",{"title":575,"path":576,"stem":577},"Raw SQL — Stored Procedures, DbFunction та Bulk Operations (Частина 2)","/csharp/ef-core/raw-sql-part2","01.csharp/10.ef-core/18.raw-sql-part2",{"title":579,"path":580,"stem":581},"Продвинуті Запити — Compiled Queries, Bulk та Оптимізація (Частина 1)","/csharp/ef-core/advanced-queries-part1","01.csharp/10.ef-core/19.advanced-queries-part1",{"title":583,"path":584,"stem":585},"Продвинуті Запити — Query Tags, Bulk та Interceptors (Частина 2)","/csharp/ef-core/advanced-queries-part2","01.csharp/10.ef-core/19.advanced-queries-part2",{"title":587,"path":588,"stem":589},"Change Tracker — Відстеження Змін (Частина 1)","/csharp/ef-core/change-tracking-part1","01.csharp/10.ef-core/20.change-tracking-part1",{"title":591,"path":592,"stem":593},"Change Tracker — Графи Об'єктів та Disconnected (Частина 2)","/csharp/ef-core/change-tracking-part2","01.csharp/10.ef-core/20.change-tracking-part2",{"title":595,"path":596,"stem":597},"Збереження Даних та Транзакції (Частина 1)","/csharp/ef-core/saving-data-part1","01.csharp/10.ef-core/21.saving-data-part1",{"title":599,"path":600,"stem":601},"Збереження Даних — Concurrency та Outbox (Частина 2)","/csharp/ef-core/saving-data-part2","01.csharp/10.ef-core/21.saving-data-part2",{"title":603,"path":604,"stem":605},"Конкурентність та Блокування (Частина 1)","/csharp/ef-core/concurrency-part1","01.csharp/10.ef-core/22.concurrency-part1",{"title":607,"path":608,"stem":609},"Конкурентність — Дедлоки та Queue Processing (Частина 2)","/csharp/ef-core/concurrency-part2","01.csharp/10.ef-core/22.concurrency-part2",{"title":611,"path":612,"stem":613},"Міграції в EF Core — Основи (Частина 1)","/csharp/ef-core/migrations-basics-part1","01.csharp/10.ef-core/23.migrations-basics-part1",{"title":615,"path":616,"stem":617},"Міграції в EF Core — Основи (Частина 2)","/csharp/ef-core/migrations-basics-part2","01.csharp/10.ef-core/23.migrations-basics-part2",{"title":619,"path":620,"stem":621},"Міграції — Просунуті Сценарії (Частина 1)","/csharp/ef-core/migrations-advanced-part1","01.csharp/10.ef-core/24.migrations-advanced-part1",{"title":623,"path":624,"stem":625},"Міграції — Просунуті Сценарії (Частина 2)","/csharp/ef-core/migrations-advanced-part2","01.csharp/10.ef-core/24.migrations-advanced-part2",{"title":627,"path":628,"stem":629},"Управління Схемою та Database-First (Частина 1)","/csharp/ef-core/schema-management-part1","01.csharp/10.ef-core/25.schema-management-part1",{"title":631,"path":632,"stem":633},"Управління Схемою та Database-First (Частина 2)","/csharp/ef-core/schema-management-part2","01.csharp/10.ef-core/25.schema-management-part2",{"title":635,"path":636,"stem":637},"Продуктивність EF Core — Основи (Частина 1)","/csharp/ef-core/performance-fundamentals-part1","01.csharp/10.ef-core/26.performance-fundamentals-part1",{"title":639,"path":640,"stem":641},"Interceptors в EF Core (Частина 1)","/csharp/ef-core/interceptors-part1","01.csharp/10.ef-core/29.interceptors-part1",{"title":643,"path":644,"stem":645},"Interceptors в EF Core — Connection, Transaction та Materialization (Частина 2)","/csharp/ef-core/interceptors-part2","01.csharp/10.ef-core/29.interceptors-part2",{"title":647,"path":648,"stem":649},"План вивчення Entity Framework Core — Повний курс","/csharp/ef-core/implementation_plan","01.csharp/10.ef-core/implementation_plan",{"title":651,"icon":652,"path":653,"stem":654,"children":655,"page":59},"ASP.NET","i-devicon-dotnetcore","/csharp/aspnet","01.csharp/11.aspnet",[656,730,791,869,927,941,967,1057,1111,1182,1212,1289],{"title":657,"icon":658,"path":659,"stem":660,"children":661,"page":59},"Minimal API","i-lucide-network","/csharp/aspnet/minimal-api","01.csharp/11.aspnet/01.minimal-api",[662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726],{"title":663,"path":664,"stem":665},"Вступ до ASP.NET та еволюція фреймворку","/csharp/aspnet/minimal-api/introduction","01.csharp/11.aspnet/01.minimal-api/01.introduction",{"title":667,"path":668,"stem":669},"Перший додаток на ASP.NET Core","/csharp/aspnet/minimal-api/first-application","01.csharp/11.aspnet/01.minimal-api/02.first-application",{"title":671,"path":672,"stem":673},"WebApplication, Builder та Dependency Injection","/csharp/aspnet/minimal-api/webapplication-builder","01.csharp/11.aspnet/01.minimal-api/03.webapplication-builder",{"title":675,"path":676,"stem":677},"Конвеєр запитів та Middleware","/csharp/aspnet/minimal-api/request-pipeline-middleware","01.csharp/11.aspnet/01.minimal-api/04.request-pipeline-middleware",{"title":679,"path":680,"stem":681},"Маршрутизація в ASP.NET Core: Основи","/csharp/aspnet/minimal-api/routing-basics","01.csharp/11.aspnet/01.minimal-api/05.routing-basics",{"title":683,"path":684,"stem":685},"Маршрутизація в ASP.NET Core: Розширені можливості","/csharp/aspnet/minimal-api/routing-advanced","01.csharp/11.aspnet/01.minimal-api/06.routing-advanced",{"title":687,"path":688,"stem":689},"Статичні файли в ASP.NET Core","/csharp/aspnet/minimal-api/static-files","01.csharp/11.aspnet/01.minimal-api/07.static-files",{"title":691,"path":692,"stem":693},"Статичні Активи: MapStaticAssets (ASP.NET Core 9.0)","/csharp/aspnet/minimal-api/static-assets","01.csharp/11.aspnet/01.minimal-api/08.static-assets",{"title":695,"path":696,"stem":697},"Конфігурація в ASP.NET Core: Основи","/csharp/aspnet/minimal-api/configuration-fundamentals","01.csharp/11.aspnet/01.minimal-api/09.configuration-fundamentals",{"title":699,"path":700,"stem":701},"Конфігурація: Паттерн Options","/csharp/aspnet/minimal-api/configuration-options","01.csharp/11.aspnet/01.minimal-api/10.configuration-options",{"title":703,"path":704,"stem":705},"Логування в ASP.NET Core: Основи","/csharp/aspnet/minimal-api/logging-basics","01.csharp/11.aspnet/01.minimal-api/11.logging-basics",{"title":707,"path":708,"stem":709},"Логування: Serilog та Middleware","/csharp/aspnet/minimal-api/logging-advanced","01.csharp/11.aspnet/01.minimal-api/12.logging-advanced",{"title":711,"path":712,"stem":713},"Управління станом: HttpContext.Items та Cookies","/csharp/aspnet/minimal-api/state-management","01.csharp/11.aspnet/01.minimal-api/13.state-management",{"title":715,"path":716,"stem":717},"Стан сесії: Sessions","/csharp/aspnet/minimal-api/session-state","01.csharp/11.aspnet/01.minimal-api/14.session-state",{"title":719,"path":720,"stem":721},"Структура проєкту: від хаосу до архітектури","/csharp/aspnet/minimal-api/project-structure","01.csharp/11.aspnet/01.minimal-api/15.project-structure",{"title":723,"path":724,"stem":725},"Scalar у Minimal API: повний проєкт і Fluent OpenAPI","/csharp/aspnet/minimal-api/scalar-openapi-fluent","01.csharp/11.aspnet/01.minimal-api/16.scalar-openapi-fluent",{"title":727,"path":728,"stem":729},"Swagger / Swashbuckle у Minimal API: окремий класичний шлях","/csharp/aspnet/minimal-api/swagger-swashbuckle","01.csharp/11.aspnet/01.minimal-api/17.swagger-swashbuckle",{"title":731,"icon":658,"path":732,"stem":733,"children":734,"page":59},"API","/csharp/aspnet/api","01.csharp/11.aspnet/02.api",[735,739,743,747,751,755,759,763,767,771,775,779,783,787],{"title":736,"path":737,"stem":738},"Що таке API. Клієнт-серверна архітектура","/csharp/aspnet/api/what-is-api","01.csharp/11.aspnet/02.api/01.what-is-api",{"title":740,"path":741,"stem":742},"Формати даних: JSON, XML, TOML та бінарні формати","/csharp/aspnet/api/data-formats","01.csharp/11.aspnet/02.api/02.data-formats",{"title":744,"path":745,"stem":746},"Парадигми API та концепція REST","/csharp/aspnet/api/api-paradigms-rest","01.csharp/11.aspnet/02.api/03.api-paradigms-rest",{"title":748,"path":749,"stem":750},"HTTP-методи, статус-коди та заголовки","/csharp/aspnet/api/http-methods-status-codes","01.csharp/11.aspnet/02.api/04.http-methods-status-codes",{"title":752,"path":753,"stem":754},"Організація HTTP API за принципами REST","/csharp/aspnet/api/rest-organizing","01.csharp/11.aspnet/02.api/05.rest-organizing",{"title":756,"path":757,"stem":758},"Номенклатура URL та CRUD-операції","/csharp/aspnet/api/url-nomenclature-crud","01.csharp/11.aspnet/02.api/06.url-nomenclature-crud",{"title":760,"path":761,"stem":762},"Правила дизайну: іменування та стандарти","/csharp/aspnet/api/api-design-naming","01.csharp/11.aspnet/02.api/07.api-design-naming",{"title":764,"path":765,"stem":766},"Валідація, ліміти та обробка помилок","/csharp/aspnet/api/api-design-validation","01.csharp/11.aspnet/02.api/08.api-design-validation",{"title":768,"path":769,"stem":770},"Обробка помилок у Minimal API","/csharp/aspnet/api/error-handling-http","01.csharp/11.aspnet/02.api/09.error-handling-http",{"title":772,"path":773,"stem":774},"Ідемпотентність та синхронізація стану","/csharp/aspnet/api/idempotency-sync","01.csharp/11.aspnet/02.api/10.idempotency-sync",{"title":776,"path":777,"stem":778},"Пагінація та організація списків","/csharp/aspnet/api/pagination-lists","01.csharp/11.aspnet/02.api/11.pagination-lists",{"title":780,"path":781,"stem":782},"Безпека API, кешування та інтернаціоналізація","/csharp/aspnet/api/security-auth","01.csharp/11.aspnet/02.api/12.security-auth",{"title":784,"path":785,"stem":786},"Процес проєктування API та документування","/csharp/aspnet/api/api-design-process","01.csharp/11.aspnet/02.api/13.api-design-process",{"title":788,"path":789,"stem":790},"OpenAPI: контракт, специфікація та документація API","/csharp/aspnet/api/openapi","01.csharp/11.aspnet/02.api/14.openapi",{"title":792,"icon":793,"path":794,"stem":795,"children":796,"page":59},"Auth","i-lucide-shield-check","/csharp/aspnet/auth","01.csharp/11.aspnet/03.auth",[797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865],{"title":798,"path":799,"stem":800},"Основи аутентифікації та авторизації","/csharp/aspnet/auth/auth-fundamentals","01.csharp/11.aspnet/03.auth/01.auth-fundamentals",{"title":802,"path":803,"stem":804},"JWT-аутентифікація","/csharp/aspnet/auth/jwt-authentication","01.csharp/11.aspnet/03.auth/02.jwt-authentication",{"title":806,"path":807,"stem":808},"Авторизація: ролі, політики та resource-based доступ","/csharp/aspnet/auth/authorization-policies","01.csharp/11.aspnet/03.auth/03.authorization-policies",{"title":810,"path":811,"stem":812},"Cookie-аутентифікація та ASP.NET Core Identity","/csharp/aspnet/auth/cookie-auth-identity","01.csharp/11.aspnet/03.auth/04.cookie-auth-identity",{"title":814,"path":815,"stem":816},"JWT + Refresh Tokens (HttpOnly Cookie)","/csharp/aspnet/auth/04b.identity-auth-jwt","01.csharp/11.aspnet/03.auth/04b.identity-auth-jwt",{"title":818,"path":819,"stem":820},"Identity: Підтвердження Email та Скидання Пароля","/csharp/aspnet/auth/identity-email-confirmation","01.csharp/11.aspnet/03.auth/05.identity-email-confirmation",{"title":822,"path":823,"stem":824},"Identity: Двофакторна Аутентифікація (2FA)","/csharp/aspnet/auth/identity-two-factor","01.csharp/11.aspnet/03.auth/06.identity-two-factor",{"title":826,"path":827,"stem":828},"Identity: Внутрішня Архітектура та Кастомізація","/csharp/aspnet/auth/identity-internals","01.csharp/11.aspnet/03.auth/07.identity-internals",{"title":830,"path":831,"stem":832},"OAuth 2.0 та зовнішні провайдери","/csharp/aspnet/auth/oauth-external-providers","01.csharp/11.aspnet/03.auth/08.oauth-external-providers",{"title":834,"path":835,"stem":836},"Безпека на практиці: CORS, HTTPS та захист від атак","/csharp/aspnet/auth/security-hardening","01.csharp/11.aspnet/03.auth/09.security-hardening",{"title":838,"path":839,"stem":840},"Теорія OAuth 2.0: Поняття, Аналогії та Флоу","/csharp/aspnet/auth/oauth-theory","01.csharp/11.aspnet/03.auth/10.oauth-theory",{"title":842,"path":843,"stem":844},"OIDC, OAuth 2.0 та Keycloak в ASP.NET Core","/csharp/aspnet/auth/oidc-keycloak","01.csharp/11.aspnet/03.auth/10.oidc-keycloak",{"title":846,"path":847,"stem":848},"API Keys аутентифікація в ASP.NET Core","/csharp/aspnet/auth/api-keys","01.csharp/11.aspnet/03.auth/11.api-keys",{"title":850,"path":851,"stem":852},"Rate Limiting та Throttling в ASP.NET Core","/csharp/aspnet/auth/rate-limiting","01.csharp/11.aspnet/03.auth/12.rate-limiting",{"title":854,"path":855,"stem":856},"Refresh Token Rotation в ASP.NET Core","/csharp/aspnet/auth/refresh-token-rotation","01.csharp/11.aspnet/03.auth/13.refresh-token-rotation",{"title":858,"path":859,"stem":860},"Certificate Authentication та mTLS в ASP.NET Core","/csharp/aspnet/auth/certificate-auth","01.csharp/11.aspnet/03.auth/14.certificate-auth",{"title":862,"path":863,"stem":864},"RBAC, ABAC та ReBAC в ASP.NET Core","/csharp/aspnet/auth/rbac-abac-rebac","01.csharp/11.aspnet/03.auth/15.rbac-abac-rebac",{"title":866,"path":867,"stem":868},"Multi-tenancy та ізоляція даних в ASP.NET Core","/csharp/aspnet/auth/multi-tenancy","01.csharp/11.aspnet/03.auth/16.multi-tenancy",{"title":870,"icon":871,"path":872,"stem":873,"children":874,"page":59},"Нотифікації","i-lucide-bell","/csharp/aspnet/notifications","01.csharp/11.aspnet/04.notifications",[875,879,883,887,891,895,899,903,907,911,915,919,923],{"title":876,"path":877,"stem":878},"In-App нотифікації через базу даних","/csharp/aspnet/notifications/in-app-database-notifications","01.csharp/11.aspnet/04.notifications/01.in-app-database-notifications",{"title":880,"path":881,"stem":882},"Polling: Регулярний запит оновлень","/csharp/aspnet/notifications/polling","01.csharp/11.aspnet/04.notifications/02.polling",{"title":884,"path":885,"stem":886},"Server-Sent Events: Однострімовий push від сервера","/csharp/aspnet/notifications/server-sent-events","01.csharp/11.aspnet/04.notifications/03.server-sent-events",{"title":888,"path":889,"stem":890},"WebSockets: Двостороннє з'єднання в реальному часі","/csharp/aspnet/notifications/websockets","01.csharp/11.aspnet/04.notifications/04.websockets",{"title":892,"path":893,"stem":894},"SignalR: Абстракція над транспортами реального часу","/csharp/aspnet/notifications/signalr","01.csharp/11.aspnet/04.notifications/05.signalr",{"title":896,"path":897,"stem":898},"Background Services: Фонові задачі в ASP.NET Core","/csharp/aspnet/notifications/background-services","01.csharp/11.aspnet/04.notifications/06.background-services",{"title":900,"path":901,"stem":902},"Web Push нотифікації","/csharp/aspnet/notifications/web-push","01.csharp/11.aspnet/04.notifications/07.web-push",{"title":904,"path":905,"stem":906},"Email нотифікації","/csharp/aspnet/notifications/email-notifications","01.csharp/11.aspnet/04.notifications/08.email-notifications",{"title":908,"path":909,"stem":910},"Порівняння підходів: Як вибрати правильну технологію нотифікацій","/csharp/aspnet/notifications/choosing-the-right-approach","01.csharp/11.aspnet/04.notifications/09.choosing-the-right-approach",{"title":912,"path":913,"stem":914},"Hangfire: Надійне планування фонових задач","/csharp/aspnet/notifications/hangfire","01.csharp/11.aspnet/04.notifications/10.hangfire",{"title":916,"path":917,"stem":918},"Практика: Конвертація зображень у WebP через Hangfire","/csharp/aspnet/notifications/hangfire-image-webp","01.csharp/11.aspnet/04.notifications/11.hangfire-image-webp",{"title":920,"path":921,"stem":922},"Практика: Підготовка відео до HLS-стрімінгу через Hangfire","/csharp/aspnet/notifications/hangfire-video-hls","01.csharp/11.aspnet/04.notifications/12.hangfire-video-hls",{"title":924,"path":925,"stem":926},"Telegram-нотифікації: від одного повідомлення до масових розсилок і мульти-канального підходу","/csharp/aspnet/notifications/telegram-notifications","01.csharp/11.aspnet/04.notifications/13.telegram-notifications",{"title":928,"icon":929,"path":930,"stem":931,"children":932,"page":59},"Інтернаціоналізація","i-lucide-languages","/csharp/aspnet/i18n","01.csharp/11.aspnet/05.i18n",[933,937],{"title":934,"path":935,"stem":936},"Інтернаціоналізація (i18n) у Minimal API: від A до Я","/csharp/aspnet/i18n/internationalization","01.csharp/11.aspnet/05.i18n/01.internationalization",{"title":938,"path":939,"stem":940},"Humanizer: людиномовні рядки у .NET","/csharp/aspnet/i18n/humanizer","01.csharp/11.aspnet/05.i18n/02.humanizer",{"title":942,"icon":943,"path":944,"stem":945,"children":946,"page":59},"Кешування","i-lucide-layers","/csharp/aspnet/caching","01.csharp/11.aspnet/06.caching",[947,951,955,959,963],{"title":948,"path":949,"stem":950},"Огляд кешування: чотири рівні і коли що обирати","/csharp/aspnet/caching/caching","01.csharp/11.aspnet/06.caching/01.caching",{"title":952,"path":953,"stem":954},"IMemoryCache: кеш в оперативній пам'яті","/csharp/aspnet/caching/memory-cache","01.csharp/11.aspnet/06.caching/02.memory-cache",{"title":956,"path":957,"stem":958},"IDistributedCache і Redis: розподілений кеш","/csharp/aspnet/caching/distributed-cache","01.csharp/11.aspnet/06.caching/03.distributed-cache",{"title":960,"path":961,"stem":962},"Response Cache: HTTP-кешування через Cache-Control","/csharp/aspnet/caching/response-cache","01.csharp/11.aspnet/06.caching/04.response-cache",{"title":964,"path":965,"stem":966},"Output Cache: серверний кеш HTTP-відповідей (.NET 7+)","/csharp/aspnet/caching/output-cache","01.csharp/11.aspnet/06.caching/05.output-cache",{"title":968,"icon":969,"path":970,"stem":971,"children":972,"page":59},"Тестування","i-lucide-test-tube","/csharp/aspnet/testing","01.csharp/11.aspnet/07.testing",[973,977,981,985,989,993,997,1001,1005,1009,1013,1017,1021,1025,1029,1033,1037,1041,1045,1049,1053],{"title":974,"path":975,"stem":976},"Що таке тестування? Від інтуїції до науки","/csharp/aspnet/testing/what-is-testing","01.csharp/11.aspnet/07.testing/01.what-is-testing",{"title":978,"path":979,"stem":980},"Піраміда тестування — Стратегія, а не Догма","/csharp/aspnet/testing/testing-pyramid","01.csharp/11.aspnet/07.testing/02.testing-pyramid",{"title":982,"path":983,"stem":984},"Дві Школи Тестування — Лондон проти Детройту","/csharp/aspnet/testing/testing-schools","01.csharp/11.aspnet/07.testing/03.testing-schools",{"title":986,"path":987,"stem":988},"TDD та BDD — Тести як Дизайн-інструмент","/csharp/aspnet/testing/tdd-and-bdd","01.csharp/11.aspnet/07.testing/04.tdd-and-bdd",{"title":990,"path":991,"stem":992},"Що саме тестувати — Техніки аналізу та Циклomatична складність","/csharp/aspnet/testing/what-to-test","01.csharp/11.aspnet/07.testing/05.what-to-test",{"title":994,"path":995,"stem":996},"Тестові Фреймворки — Навіщо вони і що всередині","/csharp/aspnet/testing/test-frameworks","01.csharp/11.aspnet/07.testing/06.test-frameworks",{"title":998,"path":999,"stem":1000},"xUnit — Факти, Теорії та Lifecycle тестів","/csharp/aspnet/testing/xunit-basics","01.csharp/11.aspnet/07.testing/07.xunit-basics",{"title":1002,"path":1003,"stem":1004},"xUnit Advanced — Fixtures, Кастомізація та Розширення","/csharp/aspnet/testing/xunit-advanced","01.csharp/11.aspnet/07.testing/08.xunit-advanced",{"title":1006,"path":1007,"stem":1008},"Moq — Глибоке занурення в мокування","/csharp/aspnet/testing/mocking-with-moq","01.csharp/11.aspnet/07.testing/09.mocking-with-moq",{"title":1010,"path":1011,"stem":1012},"Тестування Баз Даних — EF Core, SQLite та Testcontainers","/csharp/aspnet/testing/database-testing","01.csharp/11.aspnet/07.testing/10.database-testing",{"title":1014,"path":1015,"stem":1016},"Integration Testing — Частина 1 [Теорія та WebApplicationFactory]","/csharp/aspnet/testing/integration-testing","01.csharp/11.aspnet/07.testing/11.integration-testing",{"title":1018,"path":1019,"stem":1020},"Інтеграційне тестування — Практика","/csharp/aspnet/testing/11a.integration-testing-practice","01.csharp/11.aspnet/07.testing/11a.integration-testing-practice",{"title":1022,"path":1023,"stem":1024},"Integration Testing — Частина 2 [Просунуті Сценарії та Testcontainers]","/csharp/aspnet/testing/integration-testing-advanced","01.csharp/11.aspnet/07.testing/12.integration-testing-advanced",{"title":1026,"path":1027,"stem":1028},"Професійний Postman: Колекції, Змінні та GitHub Інтеграція","/csharp/aspnet/testing/postman-professional","01.csharp/11.aspnet/07.testing/13.postman-professional",{"title":1030,"path":1031,"stem":1032},"HttpClient у Тестах Частина 1: Архітектура та MockHttpMessageHandler","/csharp/aspnet/testing/httpclient-testing","01.csharp/11.aspnet/07.testing/14.httpclient-testing",{"title":1034,"path":1035,"stem":1036},"HttpClient у Тестах Частина 2: WireMock.Net та Resilience","/csharp/aspnet/testing/wiremock-net","01.csharp/11.aspnet/07.testing/15.wiremock-net",{"title":1038,"path":1039,"stem":1040},"Патерни та Анти-патерни Тестування: Test Smells","/csharp/aspnet/testing/testing-patterns","01.csharp/11.aspnet/07.testing/16.testing-patterns",{"title":1042,"path":1043,"stem":1044},"Просунуті інструменти: Time, Snapshots та Властивості","/csharp/aspnet/testing/advanced-testing-tools","01.csharp/11.aspnet/07.testing/17.advanced-testing-tools",{"title":1046,"path":1047,"stem":1048},"Тестування Архітектури з NetArchTest","/csharp/aspnet/testing/architecture-testing","01.csharp/11.aspnet/07.testing/18.architecture-testing",{"title":1050,"path":1051,"stem":1052},"Тестування Продуктивності: BenchmarkDotNet, NBomber та k6","/csharp/aspnet/testing/performance-testing","01.csharp/11.aspnet/07.testing/19.performance-testing",{"title":1054,"path":1055,"stem":1056},"Залишок плану для курсу \"Тестування ASP.NET Minimal API\"","/csharp/aspnet/testing/remaining_plan","01.csharp/11.aspnet/07.testing/remaining_plan",{"title":1058,"icon":1059,"path":1060,"stem":1061,"children":1062,"page":59},"Платежі","i-lucide-credit-card","/csharp/aspnet/payments","01.csharp/11.aspnet/08.payments",[1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107],{"title":1064,"path":1065,"stem":1066},"Основи платіжної інфраструктури","/csharp/aspnet/payments/payment-fundamentals","01.csharp/11.aspnet/08.payments/01.payment-fundamentals",{"title":1068,"path":1069,"stem":1070},"Методи оплати в Україні","/csharp/aspnet/payments/payment-methods-ukraine","01.csharp/11.aspnet/08.payments/02.payment-methods-ukraine",{"title":1072,"path":1073,"stem":1074},"PCI DSS та безпека платежів","/csharp/aspnet/payments/pci-dss-security","01.csharp/11.aspnet/08.payments/03.pci-dss-security",{"title":1076,"path":1077,"stem":1078},"Архітектура платіжної підсистеми","/csharp/aspnet/payments/payment-architecture","01.csharp/11.aspnet/08.payments/04.payment-architecture",{"title":1080,"path":1081,"stem":1082},"Інтеграція LiqPay (ПриватБанк)","/csharp/aspnet/payments/liqpay-integration","01.csharp/11.aspnet/08.payments/05.liqpay-integration",{"title":1084,"path":1085,"stem":1086},"Інтеграція Monobank Acquiring API","/csharp/aspnet/payments/monobank-acquiring","01.csharp/11.aspnet/08.payments/06.monobank-acquiring",{"title":1088,"path":1089,"stem":1090},"Інтеграція Stripe","/csharp/aspnet/payments/stripe-integration","01.csharp/11.aspnet/08.payments/07.stripe-integration",{"title":1092,"path":1093,"stem":1094},"Webhooks — глибоке занурення","/csharp/aspnet/payments/webhooks-deep-dive","01.csharp/11.aspnet/08.payments/08.webhooks-deep-dive",{"title":1096,"path":1097,"stem":1098},"Підписки та рекурентні платежі","/csharp/aspnet/payments/subscriptions-recurring","01.csharp/11.aspnet/08.payments/09.subscriptions-recurring",{"title":1100,"path":1101,"stem":1102},"Повернення коштів та диспути","/csharp/aspnet/payments/refunds-disputes","01.csharp/11.aspnet/08.payments/10.refunds-disputes",{"title":1104,"path":1105,"stem":1106},"Тестування платіжних інтеграцій","/csharp/aspnet/payments/testing-payments","01.csharp/11.aspnet/08.payments/11.testing-payments",{"title":1108,"path":1109,"stem":1110},"Чекліст виходу в Production","/csharp/aspnet/payments/production-checklist","01.csharp/11.aspnet/08.payments/12.production-checklist",{"title":1112,"icon":1113,"items":1114,"path":1127,"stem":1128,"children":1129,"page":59},"Популярні бібліотеки","lucide:box",[1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126],"01.fluent-validation","02.mapster","03.erroror-result-pattern","04.serilog","05.mediatr","06.polly","07.health-checks","08.feature-management","09.fluent-email","10.quest-pdf","11.bogus","12.humanizer-guard","/csharp/aspnet/libraries","01.csharp/11.aspnet/09.libraries",[1130,1134,1138,1142,1146,1150,1154,1158,1162,1166,1170,1174,1178],{"title":1131,"path":1132,"stem":1133},"Валідація з FluentValidation в ASP.NET Core","/csharp/aspnet/libraries/fluent-validation","01.csharp/11.aspnet/09.libraries/01.fluent-validation",{"title":1135,"path":1136,"stem":1137},"Маппінг об","/csharp/aspnet/libraries/mapster","01.csharp/11.aspnet/09.libraries/02.mapster",{"title":1139,"path":1140,"stem":1141},"Обробка помилок з ErrorOr та Result Pattern в ASP.NET Core","/csharp/aspnet/libraries/erroror-result-pattern","01.csharp/11.aspnet/09.libraries/03.erroror-result-pattern",{"title":1143,"path":1144,"stem":1145},"Структуроване логування з Serilog в ASP.NET Core","/csharp/aspnet/libraries/serilog","01.csharp/11.aspnet/09.libraries/04.serilog",{"title":1147,"path":1148,"stem":1149},"CQRS та Mediator з MediatR в ASP.NET Core","/csharp/aspnet/libraries/mediatr","01.csharp/11.aspnet/09.libraries/05.mediatr",{"title":1151,"path":1152,"stem":1153},"Відмовостійкість з Polly в ASP.NET Core","/csharp/aspnet/libraries/polly","01.csharp/11.aspnet/09.libraries/06.polly",{"title":1155,"path":1156,"stem":1157},"Health Checks в ASP.NET Core","/csharp/aspnet/libraries/health-checks","01.csharp/11.aspnet/09.libraries/07.health-checks",{"title":1159,"path":1160,"stem":1161},"Feature Management та Feature Flags в ASP.NET Core","/csharp/aspnet/libraries/feature-management","01.csharp/11.aspnet/09.libraries/08.feature-management",{"title":1163,"path":1164,"stem":1165},"Відправка Email з FluentEmail в ASP.NET Core","/csharp/aspnet/libraries/fluent-email","01.csharp/11.aspnet/09.libraries/09.fluent-email",{"title":1167,"path":1168,"stem":1169},"Генерація PDF з QuestPDF в ASP.NET Core","/csharp/aspnet/libraries/quest-pdf","01.csharp/11.aspnet/09.libraries/10.quest-pdf",{"title":1171,"path":1172,"stem":1173},"Генерація тестових даних з Bogus в ASP.NET Core","/csharp/aspnet/libraries/bogus","01.csharp/11.aspnet/09.libraries/11.bogus",{"title":1175,"path":1176,"stem":1177},"Humanizer та Guard Clauses в ASP.NET Core","/csharp/aspnet/libraries/humanizer-guard","01.csharp/11.aspnet/09.libraries/12.humanizer-guard",{"title":1179,"path":1180,"stem":1181},"План модуля 10.libraries — Популярні бібліотеки ASP.NET","/csharp/aspnet/libraries/plan","01.csharp/11.aspnet/09.libraries/plan",{"title":1183,"icon":1184,"path":1185,"stem":1186,"children":1187,"page":59},"Razor Pages","i-lucide-layout-template","/csharp/aspnet/razor-pages","01.csharp/11.aspnet/10.razor-pages",[1188,1192,1196,1200,1204,1208],{"title":1189,"path":1190,"stem":1191},"Від Minimal API до Razor Pages: концептуальний перехід","/csharp/aspnet/razor-pages/from-minimal-api","01.csharp/11.aspnet/10.razor-pages/01.from-minimal-api",{"title":1193,"path":1194,"stem":1195},"PageModel: логіка сторінки Razor Pages","/csharp/aspnet/razor-pages/page-model","01.csharp/11.aspnet/10.razor-pages/02.page-model",{"title":1197,"path":1198,"stem":1199},"Razor синтаксис: шаблонізатор у .cshtml","/csharp/aspnet/razor-pages/razor-syntax","01.csharp/11.aspnet/10.razor-pages/03.razor-syntax",{"title":1201,"path":1202,"stem":1203},"Tag Helpers: типізований HTML","/csharp/aspnet/razor-pages/tag-helpers","01.csharp/11.aspnet/10.razor-pages/04.tag-helpers",{"title":1205,"path":1206,"stem":1207},"Форми і валідація: повний цикл обробки даних","/csharp/aspnet/razor-pages/forms-validation","01.csharp/11.aspnet/10.razor-pages/05.forms-validation",{"title":1209,"path":1210,"stem":1211},"Практичний проєкт: TaskManager на Razor Pages","/csharp/aspnet/razor-pages/project-task-manager","01.csharp/11.aspnet/10.razor-pages/06.project-task-manager",{"title":1213,"path":1214,"stem":1215,"children":1216,"page":59},"ASP.NET Core MVC","/csharp/aspnet/mvc","01.csharp/11.aspnet/11.mvc",[1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1285],{"title":1218,"path":1219,"stem":1220},"Патерн MVC: архітектура, що змінила веб","/csharp/aspnet/mvc/mvc-pattern","01.csharp/11.aspnet/11.mvc/01.mvc-pattern",{"title":1222,"path":1223,"stem":1224},"Від Razor Pages до MVC: концептуальний перехід","/csharp/aspnet/mvc/from-razor-pages","01.csharp/11.aspnet/11.mvc/02.from-razor-pages",{"title":1226,"path":1227,"stem":1228},"Controllers та Actions: серце MVC","/csharp/aspnet/mvc/controllers-actions","01.csharp/11.aspnet/11.mvc/03.controllers-actions",{"title":1230,"path":1231,"stem":1232},"Маршрутизація в MVC: Convention vs Attribute Routing","/csharp/aspnet/mvc/routing-mvc","01.csharp/11.aspnet/11.mvc/04.routing-mvc",{"title":1234,"path":1235,"stem":1236},"Model Binding: від HTTP до C#","/csharp/aspnet/mvc/model-binding","01.csharp/11.aspnet/11.mvc/05.model-binding",{"title":1238,"path":1239,"stem":1240},"Views, ViewData, ViewBag, TempData і ViewModel","/csharp/aspnet/mvc/views-viewdata-tempdata","01.csharp/11.aspnet/11.mvc/06.views-viewdata-tempdata",{"title":1242,"path":1243,"stem":1244},"Filters: аспектно-орієнтоване програмування в MVC","/csharp/aspnet/mvc/filters","01.csharp/11.aspnet/11.mvc/07.filters",{"title":1246,"path":1247,"stem":1248},"Areas: структурування великих застосунків","/csharp/aspnet/mvc/areas","01.csharp/11.aspnet/11.mvc/08.areas",{"title":1250,"path":1251,"stem":1252},"View Components: повторювані незалежні блоки UI","/csharp/aspnet/mvc/view-components","01.csharp/11.aspnet/11.mvc/09.view-components",{"title":1254,"path":1255,"stem":1256},"Display та Editor Templates","/csharp/aspnet/mvc/display-editor-templates","01.csharp/11.aspnet/11.mvc/10.display-editor-templates",{"title":1258,"path":1259,"stem":1260},"Валідація: IValidatableObject та FluentValidation","/csharp/aspnet/mvc/validation-advanced","01.csharp/11.aspnet/11.mvc/11.validation-advanced",{"title":1262,"path":1263,"stem":1264},"HTMX: інтерактивність через HTML-атрибути","/csharp/aspnet/mvc/htmx","01.csharp/11.aspnet/11.mvc/12.htmx",{"title":1266,"path":1267,"stem":1268},"HTMX у ASP.NET Core MVC: серверна інтеграція","/csharp/aspnet/mvc/ajax-htmx-mvc","01.csharp/11.aspnet/11.mvc/13.ajax-htmx-mvc",{"title":1270,"path":1271,"stem":1272},"Практичний проєкт: Каталог товарів з HTMX","/csharp/aspnet/mvc/htmx-project","01.csharp/11.aspnet/11.mvc/14.htmx-project",{"title":1274,"path":1275,"stem":1276},"Завантаження та обробка файлів","/csharp/aspnet/mvc/file-upload","01.csharp/11.aspnet/11.mvc/15.file-upload",{"title":1278,"path":1279,"stem":1280},"Глобалізація та Локалізація MVC","/csharp/aspnet/mvc/globalization-localization","01.csharp/11.aspnet/11.mvc/16.globalization-localization",{"title":1282,"path":1283,"stem":1284},"Підсумковий проєкт: Блог-платформа","/csharp/aspnet/mvc/mvc-project","01.csharp/11.aspnet/11.mvc/17.mvc-project",{"title":1286,"path":1287,"stem":1288},"План курсу: ASP.NET Core MVC","/csharp/aspnet/mvc/plan","01.csharp/11.aspnet/11.mvc/plan",{"title":1290,"path":1291,"stem":1292,"children":1293,"page":59},"Web Api","/csharp/aspnet/web-api","01.csharp/11.aspnet/12.web-api",[1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342],{"title":1295,"path":1296,"stem":1297},"Від Minimal API до Controller-based API","/csharp/aspnet/web-api/from-minimal-api-to-controllers","01.csharp/11.aspnet/12.web-api/01.from-minimal-api-to-controllers",{"title":1299,"path":1300,"stem":1301},"ControllerBase, ActionResult\u003CT> та Response Types","/csharp/aspnet/web-api/controller-base-actionresult","01.csharp/11.aspnet/12.web-api/02.controller-base-actionresult",{"title":1303,"path":1304,"stem":1305},"Content Negotiation - JSON, XML та власні форматери","/csharp/aspnet/web-api/content-negotiation","01.csharp/11.aspnet/12.web-api/03.content-negotiation",{"title":1307,"path":1308,"stem":1309},"Версіонування API","/csharp/aspnet/web-api/api-versioning","01.csharp/11.aspnet/12.web-api/04.api-versioning",{"title":1311,"path":1312,"stem":1313},"ProblemDetails та структурована обробка помилок","/csharp/aspnet/web-api/problemdetails-error-handling","01.csharp/11.aspnet/12.web-api/05.problemdetails-error-handling",{"title":1315,"path":1316,"stem":1317},"Фільтри у Web API контексті","/csharp/aspnet/web-api/filters-for-api","01.csharp/11.aspnet/12.web-api/06.filters-for-api",{"title":1319,"path":1320,"stem":1321},"Пагінація, фільтрація та сортування","/csharp/aspnet/web-api/pagination-filtering-sorting","01.csharp/11.aspnet/12.web-api/07.pagination-filtering-sorting",{"title":1323,"path":1324,"stem":1325},"HATEOAS та Resource Expansion","/csharp/aspnet/web-api/hateoas-resource-expansion","01.csharp/11.aspnet/12.web-api/08.hateoas-resource-expansion",{"title":1327,"path":1328,"stem":1329},"Гібридна архітектура - Minimal API + Controllers","/csharp/aspnet/web-api/minimal-api-vs-controllers-hybrid","01.csharp/11.aspnet/12.web-api/09.minimal-api-vs-controllers-hybrid",{"title":1331,"path":1332,"stem":1333},"Документація API - Swashbuckle, NSwag та генерація клієнтів","/csharp/aspnet/web-api/api-documentation-generation","01.csharp/11.aspnet/12.web-api/10.api-documentation-generation",{"title":1335,"path":1336,"stem":1337},"Health Checks та моніторинг API","/csharp/aspnet/web-api/health-checks-monitoring","01.csharp/11.aspnet/12.web-api/11.health-checks-monitoring",{"title":1339,"path":1340,"stem":1341},"Підсумковий проєкт - Production-Ready REST API","/csharp/aspnet/web-api/web-api-project","01.csharp/11.aspnet/12.web-api/12.web-api-project",{"title":1343,"path":1344,"stem":1345},"План курсу: ASP.NET Core Web API (Controllers)","/csharp/aspnet/web-api/plan","01.csharp/11.aspnet/12.web-api/plan",{"title":1347,"icon":1348,"path":1349,"stem":1350,"children":1351,"page":59},"Desktop UI","i-lucide-app-window","/csharp/desktop-ui","01.csharp/12.desktop-ui",[1352,1356,1360,1364,1368,1372,1376,1380,1384,1388,1392,1396,1400,1404,1408,1412,1416,1420,1424,1428,1432,1436,1440,1444,1448,1452,1456,1460,1464,1468,1472,1476,1480,1484,1488,1492,1496,1500,1504,1508,1512,1516,1520,1524,1528,1532,1536,1540,1544,1548,1552,1556,1560,1564,1568,1572,1576,1580,1584,1588,1592,1596,1600,1604,1608,1612,1616,1620,1624,1628,1632],{"title":1353,"path":1354,"stem":1355},"Що таке десктопна розробка?","/csharp/desktop-ui/what-is-desktop-dev","01.csharp/12.desktop-ui/01.what-is-desktop-dev",{"title":1357,"path":1358,"stem":1359},"Архітектура WPF — як влаштований графічний інтерфейс","/csharp/desktop-ui/wpf-architecture","01.csharp/12.desktop-ui/02.wpf-architecture",{"title":1361,"path":1362,"stem":1363},"Перший WPF-проєкт — від нуля до вікна","/csharp/desktop-ui/first-wpf-app","01.csharp/12.desktop-ui/03.first-wpf-app",{"title":1365,"path":1366,"stem":1367},"Перший Avalonia-проєкт: WPF для всіх платформ","/csharp/desktop-ui/03a.first-avalonia-app","01.csharp/12.desktop-ui/03a.first-avalonia-app",{"title":1369,"path":1370,"stem":1371},"XAML: декларативний інтерфейс","/csharp/desktop-ui/xaml-basics","01.csharp/12.desktop-ui/04.xaml-basics",{"title":1373,"path":1374,"stem":1375},"Fluent UI у WPF — сучасний дизайн Windows 11","/csharp/desktop-ui/04a.wpf-fluent-ui","01.csharp/12.desktop-ui/04a.wpf-fluent-ui",{"title":1377,"path":1378,"stem":1379},"WPF UI — сучасна бібліотека Fluent контролів","/csharp/desktop-ui/04b.wpf-ui-library","01.csharp/12.desktop-ui/04b.wpf-ui-library",{"title":1381,"path":1382,"stem":1383},"HandyControl — велика бібліотека UI контролів для WPF","/csharp/desktop-ui/04c.handycontrol-library","01.csharp/12.desktop-ui/04c.handycontrol-library",{"title":1385,"path":1386,"stem":1387},"Простори імен та ресурси XAML","/csharp/desktop-ui/xaml-namespaces-resources","01.csharp/12.desktop-ui/05.xaml-namespaces-resources",{"title":1389,"path":1390,"stem":1391},"XAML в Avalonia: ключові відмінності від WPF","/csharp/desktop-ui/05a.avalonia-xaml-differences","01.csharp/12.desktop-ui/05a.avalonia-xaml-differences",{"title":1393,"path":1394,"stem":1395},"Розширення розмітки XAML (Markup Extensions)","/csharp/desktop-ui/xaml-markup-extensions","01.csharp/12.desktop-ui/06.xaml-markup-extensions",{"title":1397,"path":1398,"stem":1399},"Панелі Layout: StackPanel, WrapPanel, DockPanel","/csharp/desktop-ui/layout-panels-part1","01.csharp/12.desktop-ui/07.layout-panels-part1",{"title":1401,"path":1402,"stem":1403},"Grid, Canvas, UniformGrid","/csharp/desktop-ui/layout-panels-part2","01.csharp/12.desktop-ui/07.layout-panels-part2",{"title":1405,"path":1406,"stem":1407},"Просунуті техніки Layout","/csharp/desktop-ui/layout-advanced","01.csharp/12.desktop-ui/08.layout-advanced",{"title":1409,"path":1410,"stem":1411},"Адаптивний Layout та найкращі практики","/csharp/desktop-ui/layout-responsive","01.csharp/12.desktop-ui/09.layout-responsive",{"title":1413,"path":1414,"stem":1415},"Layout в Avalonia: відмінності та нові можливості","/csharp/desktop-ui/09a.layout-avalonia","01.csharp/12.desktop-ui/09a.layout-avalonia",{"title":1417,"path":1418,"stem":1419},"Button, Image, ProgressBar та інші базові контроли","/csharp/desktop-ui/basic-controls","01.csharp/12.desktop-ui/10.basic-controls",{"title":1421,"path":1422,"stem":1423},"Контроли в Avalonia: відмінності від WPF","/csharp/desktop-ui/10a.controls-avalonia","01.csharp/12.desktop-ui/10a.controls-avalonia",{"title":1425,"path":1426,"stem":1427},"Текстові контроли — TextBlock, TextBox, RichTextBox","/csharp/desktop-ui/text-controls","01.csharp/12.desktop-ui/11.text-controls",{"title":1429,"path":1430,"stem":1431},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","/csharp/desktop-ui/selection-controls","01.csharp/12.desktop-ui/12.selection-controls",{"title":1433,"path":1434,"stem":1435},"Content Model — GroupBox, Expander, TabControl, StatusBar","/csharp/desktop-ui/content-controls","01.csharp/12.desktop-ui/13.content-controls",{"title":1437,"path":1438,"stem":1439},"UI/UX принципи десктопних застосунків","/csharp/desktop-ui/13a.ui-ux-principles","01.csharp/12.desktop-ui/13a.ui-ux-principles",{"title":1441,"path":1442,"stem":1443},"Dependency Properties — Концепція та Value Resolution","/csharp/desktop-ui/dependency-properties-part1","01.csharp/12.desktop-ui/14.dependency-properties-part1",{"title":1445,"path":1446,"stem":1447},"Avalonia Property System — StyledProperty та DirectProperty","/csharp/desktop-ui/14a.avalonia-property-system","01.csharp/12.desktop-ui/14a.avalonia-property-system",{"title":1449,"path":1450,"stem":1451},"Attached Properties — Властивості без меж","/csharp/desktop-ui/attached-properties","01.csharp/12.desktop-ui/15.attached-properties",{"title":1453,"path":1454,"stem":1455},"Routed Events — Маршрутизація подій у WPF","/csharp/desktop-ui/routed-events","01.csharp/12.desktop-ui/16.routed-events",{"title":1457,"path":1458,"stem":1459},"Data Binding — Від Code-Behind до Декларативності","/csharp/desktop-ui/data-binding-basics-part1","01.csharp/12.desktop-ui/17.data-binding-basics-part1",{"title":1461,"path":1462,"stem":1463},"INotifyPropertyChanged — Живе оновлення UI","/csharp/desktop-ui/data-binding-basics-part2","01.csharp/12.desktop-ui/17.data-binding-basics-part2",{"title":1465,"path":1466,"stem":1467},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","/csharp/desktop-ui/17a.avalonia-compiled-bindings","01.csharp/12.desktop-ui/17a.avalonia-compiled-bindings",{"title":1469,"path":1470,"stem":1471},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","/csharp/desktop-ui/data-binding-advanced","01.csharp/12.desktop-ui/18.data-binding-advanced",{"title":1473,"path":1474,"stem":1475},"Value Converters — Перетворення типів даних у Data Binding","/csharp/desktop-ui/value-converters","01.csharp/12.desktop-ui/19.value-converters",{"title":1477,"path":1478,"stem":1479},"Data Templates — Візуалізація об'єктів у WPF","/csharp/desktop-ui/data-templates","01.csharp/12.desktop-ui/20.data-templates",{"title":1481,"path":1482,"stem":1483},"Collections Binding Part 1 — ObservableCollection та ItemsControl","/csharp/desktop-ui/collections-binding-part1","01.csharp/12.desktop-ui/21.collections-binding-part1",{"title":1485,"path":1486,"stem":1487},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","/csharp/desktop-ui/collections-binding-part2","01.csharp/12.desktop-ui/21.collections-binding-part2",{"title":1489,"path":1490,"stem":1491},"MVVM Pattern — Від Spaghetti Code до архітектури","/csharp/desktop-ui/mvvm-pattern","01.csharp/12.desktop-ui/22.mvvm-pattern",{"title":1493,"path":1494,"stem":1495},"ViewModel Implementation — Від BaseViewModel до валідації","/csharp/desktop-ui/viewmodel-implementation","01.csharp/12.desktop-ui/23.viewmodel-implementation",{"title":1497,"path":1498,"stem":1499},"Commands — Від event handlers до декларативних команд","/csharp/desktop-ui/commands","01.csharp/12.desktop-ui/24.commands",{"title":1501,"path":1502,"stem":1503},"MVVM Toolkit — MVVM без boilerplate через Source Generators","/csharp/desktop-ui/mvvm-toolkit","01.csharp/12.desktop-ui/25.mvvm-toolkit",{"title":1505,"path":1506,"stem":1507},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","/csharp/desktop-ui/messenger-pattern","01.csharp/12.desktop-ui/26.messenger-pattern",{"title":1509,"path":1510,"stem":1511},"Стилі WPF — CSS для десктопу","/csharp/desktop-ui/styles-basics","01.csharp/12.desktop-ui/27.styles-basics",{"title":1513,"path":1514,"stem":1515},"CSS-like стилі Avalonia","/csharp/desktop-ui/27a.avalonia-css-styling","01.csharp/12.desktop-ui/27a.avalonia-css-styling",{"title":1517,"path":1518,"stem":1519},"Control Templates — Частина 1. Концепція та TemplateBinding","/csharp/desktop-ui/control-templates-part1","01.csharp/12.desktop-ui/28.control-templates-part1",{"title":1521,"path":1522,"stem":1523},"Control Templates — Частина 2. Named Parts та ContentPresenter","/csharp/desktop-ui/control-templates-part2","01.csharp/12.desktop-ui/28.control-templates-part2",{"title":1525,"path":1526,"stem":1527},"Control Themes в Avalonia — нова ера стилізації","/csharp/desktop-ui/28a.avalonia-control-themes","01.csharp/12.desktop-ui/28a.avalonia-control-themes",{"title":1529,"path":1530,"stem":1531},"Triggers та Visual State Manager у WPF","/csharp/desktop-ui/triggers-visual-states","01.csharp/12.desktop-ui/29.triggers-visual-states",{"title":1533,"path":1534,"stem":1535},"Pseudo-classes в Avalonia — замість WPF Triggers","/csharp/desktop-ui/29a.avalonia-pseudo-classes","01.csharp/12.desktop-ui/29a.avalonia-pseudo-classes",{"title":1537,"path":1538,"stem":1539},"Теми та ресурсні словники у WPF","/csharp/desktop-ui/resources-themes","01.csharp/12.desktop-ui/30.resources-themes",{"title":1541,"path":1542,"stem":1543},"Avalonia Themes — Fluent Design та система тематизації","/csharp/desktop-ui/30a.avalonia-themes-fluent","01.csharp/12.desktop-ui/30a.avalonia-themes-fluent",{"title":1545,"path":1546,"stem":1547},"Контроли колекцій — глибоке занурення","/csharp/desktop-ui/collection-controls","01.csharp/12.desktop-ui/31.collection-controls",{"title":1549,"path":1550,"stem":1551},"DataGrid — колонки та базове відображення","/csharp/desktop-ui/datagrid-part1","01.csharp/12.desktop-ui/32.datagrid-part1",{"title":1553,"path":1554,"stem":1555},"DataGrid — сортування, фільтрація, редагування","/csharp/desktop-ui/datagrid-part2","01.csharp/12.desktop-ui/32.datagrid-part2",{"title":1557,"path":1558,"stem":1559},"TreeView та GridView","/csharp/desktop-ui/treeview-listview","01.csharp/12.desktop-ui/33.treeview-listview",{"title":1561,"path":1562,"stem":1563},"Меню, Toolbar, ContextMenu, StatusBar","/csharp/desktop-ui/menus-toolbars","01.csharp/12.desktop-ui/34.menus-toolbars",{"title":1565,"path":1566,"stem":1567},"Навігація та керування вікнами. Частина 1: вікна та сторінки","/csharp/desktop-ui/navigation-windows-part1","01.csharp/12.desktop-ui/35.navigation-windows-part1",{"title":1569,"path":1570,"stem":1571},"Навігація та керування вікнами. Частина 2: MVVM-навігація","/csharp/desktop-ui/navigation-windows-part2","01.csharp/12.desktop-ui/35.navigation-windows-part2",{"title":1573,"path":1574,"stem":1575},"Avalonia — Навігація та діалоги","/csharp/desktop-ui/35a.avalonia-navigation-dialogs","01.csharp/12.desktop-ui/35a.avalonia-navigation-dialogs",{"title":1577,"path":1578,"stem":1579},"Діалоги та File Pickers у WPF","/csharp/desktop-ui/dialogs-file-pickers","01.csharp/12.desktop-ui/36.dialogs-file-pickers",{"title":1581,"path":1582,"stem":1583},"UserControl: компонентний підхід у WPF","/csharp/desktop-ui/user-controls","01.csharp/12.desktop-ui/37.user-controls",{"title":1585,"path":1586,"stem":1587},"Custom Controls: Lookless Controls у WPF","/csharp/desktop-ui/custom-controls","01.csharp/12.desktop-ui/38.custom-controls",{"title":1589,"path":1590,"stem":1591},"Avalonia TemplatedControl — Lookless Controls","/csharp/desktop-ui/38a.avalonia-templated-controls","01.csharp/12.desktop-ui/38a.avalonia-templated-controls",{"title":1593,"path":1594,"stem":1595},"Анімації у WPF: Storyboard та Easing Functions","/csharp/desktop-ui/animations-transitions","01.csharp/12.desktop-ui/39.animations-transitions",{"title":1597,"path":1598,"stem":1599},"Анімації в Avalonia","/csharp/desktop-ui/39a.avalonia-animations","01.csharp/12.desktop-ui/39a.avalonia-animations",{"title":1601,"path":1602,"stem":1603},"2D Графіка та Мультимедіа у WPF","/csharp/desktop-ui/media-graphics","01.csharp/12.desktop-ui/40.media-graphics",{"title":1605,"path":1606,"stem":1607},"Dependency Injection у WPF та Avalonia","/csharp/desktop-ui/di-integration","01.csharp/12.desktop-ui/41.di-integration",{"title":1609,"path":1610,"stem":1611},"SQLite та EF Core у десктопних додатках","/csharp/desktop-ui/data-persistence-part1","01.csharp/12.desktop-ui/42.data-persistence-part1",{"title":1613,"path":1614,"stem":1615},"Repository Pattern та Unit of Work","/csharp/desktop-ui/data-persistence-part2","01.csharp/12.desktop-ui/43.data-persistence-part2",{"title":1617,"path":1618,"stem":1619},"Тестування ViewModels","/csharp/desktop-ui/viewmodel-testing","01.csharp/12.desktop-ui/44.viewmodel-testing",{"title":1621,"path":1622,"stem":1623},"Avalonia Headless Testing — тестування UI без вікон","/csharp/desktop-ui/44a.avalonia-headless-testing","01.csharp/12.desktop-ui/44a.avalonia-headless-testing",{"title":1625,"path":1626,"stem":1627},"Кросплатформна розробка з Avalonia","/csharp/desktop-ui/avalonia-cross-platform","01.csharp/12.desktop-ui/45.avalonia-cross-platform",{"title":1629,"path":1630,"stem":1631},"Пакування та розгортання Avalonia додатків","/csharp/desktop-ui/avalonia-packaging-deployment","01.csharp/12.desktop-ui/46.avalonia-packaging-deployment",{"title":1633,"path":1634,"stem":1635},"Розгортання WPF застосунків","/csharp/desktop-ui/wpf-packaging-deployment","01.csharp/12.desktop-ui/47.wpf-packaging-deployment",{"title":1637,"path":1638,"stem":1639},"C# & .NET: The Ultimate Roadmap","/csharp/roadmap","01.csharp/roadmap",{"title":1641,"icon":1642,"path":1643,"stem":1644,"children":1645,"page":59},"C++","i-devicon-cplusplus","/cpp","02.cpp",[1646,1650,1654,1658,1662,1666,1670,1674,1678,1681,1685,1689,1693,1697,1701,1705,1709,1713,1717,1721,1725,1729,1733,1737,1741,1745,1749,1753,1757,1761],{"title":1647,"path":1648,"stem":1649},"Вступ у програмування та алгоритми","/cpp/intro-algorithms","02.cpp/01.intro-algorithms",{"title":1651,"path":1652,"stem":1653},"Code Style: угоди про оформлення коду","/cpp/code-style","02.cpp/02.code-style",{"title":1655,"path":1656,"stem":1657},"Середовище розробки та перший проєкт","/cpp/ide-setup","02.cpp/03.ide-setup",{"title":1659,"path":1660,"stem":1661},"Вивід даних на екран","/cpp/data-output","02.cpp/04.data-output",{"title":1663,"path":1664,"stem":1665},"Типи даних, змінні та константи","/cpp/data-types-variables","02.cpp/05.data-types-variables",{"title":1667,"path":1668,"stem":1669},"Ввід даних з клавіатури","/cpp/data-input","02.cpp/06.data-input",{"title":1671,"path":1672,"stem":1673},"Оператори, перетворення типів та логічні операції","/cpp/operators-type-conversion","02.cpp/07.operators-type-conversion",{"title":1675,"path":1676,"stem":1677},"Цикли","/cpp/loops","02.cpp/08.loops",{"title":32,"path":1679,"stem":1680},"/cpp/arrays","02.cpp/09.arrays",{"title":1682,"path":1683,"stem":1684},"Алгоритми сортування та аналіз складності","/cpp/sorting","02.cpp/10.sorting",{"title":1686,"path":1687,"stem":1688},"Алгоритми пошуку","/cpp/searching","02.cpp/11.searching",{"title":1690,"path":1691,"stem":1692},"Функції: основи","/cpp/functions-basics","02.cpp/12.functions-basics",{"title":1694,"path":1695,"stem":1696},"Функції: прототипи, область видимості та додаткові можливості","/cpp/functions-scope","02.cpp/13.functions-scope",{"title":1698,"path":1699,"stem":1700},"Функції: перевантаження та шаблони","/cpp/functions-overloading-templates","02.cpp/14.functions-overloading-templates",{"title":1702,"path":1703,"stem":1704},"Вказівники: основи","/cpp/pointers-basics","02.cpp/15.pointers-basics",{"title":1706,"path":1707,"stem":1708},"Посилання (References)","/cpp/references","02.cpp/16.references",{"title":1710,"path":1711,"stem":1712},"Вказівники, const і масиви","/cpp/pointers-const-arrays","02.cpp/17.pointers-const-arrays",{"title":1714,"path":1715,"stem":1716},"Адресна арифметика","/cpp/pointer-arithmetic","02.cpp/18.pointer-arithmetic",{"title":1718,"path":1719,"stem":1720},"Динамічна пам'ять","/cpp/dynamic-memory","02.cpp/19.dynamic-memory",{"title":1722,"path":1723,"stem":1724},"Вказівники типу void","/cpp/void-pointers","02.cpp/20.void-pointers",{"title":1726,"path":1727,"stem":1728},"Вказівники на вказівники","/cpp/pointers-to-pointers","02.cpp/21.pointers-to-pointers",{"title":1730,"path":1731,"stem":1732},"Оператор доступу до членів через вказівник (->)","/cpp/member-access-operator","02.cpp/22.member-access-operator",{"title":1734,"path":1735,"stem":1736},"Цикл for-each (Range-based for)","/cpp/foreach-loop","02.cpp/23.foreach-loop",{"title":1738,"path":1739,"stem":1740},"Вказівники на функції","/cpp/function-pointers","02.cpp/24.function-pointers",{"title":1742,"path":1743,"stem":1744},"Лямбда-вирази","/cpp/lambdas","02.cpp/25.lambdas",{"title":1746,"path":1747,"stem":1748},"Лямбда-захоплення","/cpp/lambda-captures","02.cpp/26.lambda-captures",{"title":1750,"path":1751,"stem":1752},"Еліпсис","/cpp/ellipsis","02.cpp/27.ellipsis",{"title":1754,"path":1755,"stem":1756},"Аргументи командного рядка","/cpp/command-line-arguments","02.cpp/28.command-line-arguments",{"title":1758,"path":1759,"stem":1760},"Перерахування (enum)","/cpp/enum","02.cpp/29.enum",{"title":1762,"path":1763,"stem":1764},"План навчання: Курс C++ — Продовження (Статті 29–60+)","/cpp/curriculum-plan","02.cpp/curriculum-plan",{"title":1766,"icon":1767,"path":1768,"stem":1769,"children":1770,"page":59},"JavaScript","i-devicon-javascript","/javascript","03.javascript",[1771,1797,1851,1873,2177,2215],{"title":1772,"icon":1773,"path":1774,"stem":1775,"children":1776,"page":59},"Events","i-lucide-mouse-pointer-click","/javascript/events","03.javascript/01.events",[1777,1781,1785,1789,1793],{"title":1778,"path":1779,"stem":1780},"Вступ до подій браузера","/javascript/events/intro","03.javascript/01.events/01.intro",{"title":1782,"path":1783,"stem":1784},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","/javascript/events/bubbling-capturing","03.javascript/01.events/02.bubbling-capturing",{"title":1786,"path":1787,"stem":1788},"Делегування подій (Event Delegation)","/javascript/events/delegate-events","03.javascript/01.events/03.delegate-events",{"title":1790,"path":1791,"stem":1792},"Типові дії браузера та preventDefault()","/javascript/events/prevent-default","03.javascript/01.events/04.prevent-default",{"title":1794,"path":1795,"stem":1796},"Запуск користувацьких подій (Custom Events)","/javascript/events/custom-events","03.javascript/01.events/05.custom-events",{"title":1798,"icon":1799,"path":1800,"stem":1801,"children":1802,"page":59},"Network","i-lucide-globe","/javascript/network","03.javascript/02.network",[1803,1807,1811,1815,1819,1823,1827,1831,1835,1839,1843,1847],{"title":1804,"path":1805,"stem":1806},"Fetch API - Сучасний підхід до HTTP-запитів","/javascript/network/01-fetch-api","03.javascript/02.network/01-fetch-api",{"title":1808,"path":1809,"stem":1810},"FormData - Робота з формами та файлами","/javascript/network/02-formdata","03.javascript/02.network/02-formdata",{"title":1812,"path":1813,"stem":1814},"Відстеження прогресу завантаження","/javascript/network/03-download-progress","03.javascript/02.network/03-download-progress",{"title":1816,"path":1817,"stem":1818},"Переривання fetch-запитів","/javascript/network/04-abort-requests","03.javascript/02.network/04-abort-requests",{"title":1820,"path":1821,"stem":1822},"CORS - Запити між різними джерелами","/javascript/network/05-cors","03.javascript/02.network/05-cors",{"title":1824,"path":1825,"stem":1826},"Fetch API - Повний довідник опцій","/javascript/network/06-fetch-options","03.javascript/02.network/06-fetch-options",{"title":1828,"path":1829,"stem":1830},"URL Objects - Робота з посиланнями","/javascript/network/07-url-objects","03.javascript/02.network/07-url-objects",{"title":1832,"path":1833,"stem":1834},"XMLHttpRequest - AJAX та низькорівневі запити","/javascript/network/08-xmlhttprequest","03.javascript/02.network/08-xmlhttprequest",{"title":1836,"path":1837,"stem":1838},"Відновлюване завантаження файлів","/javascript/network/09-resumable-upload","03.javascript/02.network/09-resumable-upload",{"title":1840,"path":1841,"stem":1842},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","/javascript/network/10-cookies","03.javascript/02.network/10-cookies",{"title":1844,"path":1845,"stem":1846},"js-cookie: Керування Cookies без Болю","/javascript/network/11-js-cookie","03.javascript/02.network/11-js-cookie",{"title":1848,"path":1849,"stem":1850},"Axios: Потужний HTTP-клієнт для JavaScript","/javascript/network/12-axios","03.javascript/02.network/12-axios",{"title":1852,"icon":1853,"path":1854,"stem":1855,"children":1856,"page":59},"Bom","i-lucide-monitor","/javascript/bom","03.javascript/03.bom",[1857,1861,1865,1869],{"title":1858,"path":1859,"stem":1860},"LocalStorage, SessionStorage та patterns збереження даних","/javascript/bom/01-localstorage","03.javascript/03.bom/01-localstorage",{"title":1862,"path":1863,"stem":1864},"Location Object - Керування адресою сторінки","/javascript/bom/02-location-object","03.javascript/03.bom/02-location-object",{"title":1866,"path":1867,"stem":1868},"History API - Керування історією браузера","/javascript/bom/03-history-api","03.javascript/03.bom/03-history-api",{"title":1870,"path":1871,"stem":1872},"Navigator Object - Ідентифікація та Можливості Пристрою","/javascript/bom/04-navigator-object","03.javascript/03.bom/04-navigator-object",{"title":1874,"icon":1875,"path":1876,"stem":1877,"children":1878},"React","i-devicon-react","/javascript/react","03.javascript/04.react/index",[1879,1880,1884,1888,1892,1896,1959,1994,2146],{"title":1874,"path":1876,"stem":1877},{"title":1881,"path":1882,"stem":1883},"Робота з Формами в React","/javascript/react/react-forms","03.javascript/04.react/01.react-forms",{"title":1885,"path":1886,"stem":1887},"React Hook Form: Професійна Робота з Формами","/javascript/react/react-hook-form","03.javascript/04.react/02.react-hook-form",{"title":1889,"path":1890,"stem":1891},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","/javascript/react/react-hook-form-new","03.javascript/04.react/02.react-hook-form-new",{"title":1893,"path":1894,"stem":1895},"Axios та React: Професійна Архітектура Запитів","/javascript/react/data-fetching-axios","03.javascript/04.react/03.data-fetching-axios",{"title":1897,"icon":132,"path":1898,"stem":1899,"children":1900},"Tanstack Query","/javascript/react/tanstack-query","03.javascript/04.react/04.tanstack-query/index",[1901,1903,1907,1911,1915,1919,1923,1927,1931,1935,1939,1943,1947,1951,1955],{"title":1902,"path":1898,"stem":1899},"TanStack Query: Майстерність Керування Станом Сервера",{"title":1904,"path":1905,"stem":1906},"Парадигма Server State: Чому useEffect недостатньо","/javascript/react/tanstack-query/server-state-paradigm","03.javascript/04.react/04.tanstack-query/01.server-state-paradigm",{"title":1908,"path":1909,"stem":1910},"Встановлення та Налаштування: Фундамент","/javascript/react/tanstack-query/installation-and-devtools","03.javascript/04.react/04.tanstack-query/02.installation-and-devtools",{"title":1912,"path":1913,"stem":1914},"Основи Запитів та Магія Ключів","/javascript/react/tanstack-query/query-basics-and-keys","03.javascript/04.react/04.tanstack-query/03.query-basics-and-keys",{"title":1916,"path":1917,"stem":1918},"Синхронізація Даних: Життєвий Цикл Запиту","/javascript/react/tanstack-query/data-synchronization","03.javascript/04.react/04.tanstack-query/04.data-synchronization",{"title":1920,"path":1921,"stem":1922},"Мутації та Інвалідація: Зміна Даних","/javascript/react/tanstack-query/mutations-and-invalidation","03.javascript/04.react/04.tanstack-query/05.mutations-and-invalidation",{"title":1924,"path":1925,"stem":1926},"Оптимістичні Оновлення: Швидше за Світло","/javascript/react/tanstack-query/optimistic-updates","03.javascript/04.react/04.tanstack-query/06.optimistic-updates",{"title":1928,"path":1929,"stem":1930},"Пагінація та Infinite Scroll","/javascript/react/tanstack-query/pagination-and-load-more","03.javascript/04.react/04.tanstack-query/07.pagination-and-load-more",{"title":1932,"path":1933,"stem":1934},"Просунуті Патерни та Оптимізація","/javascript/react/tanstack-query/advanced-patterns","03.javascript/04.react/04.tanstack-query/08.advanced-patterns",{"title":1936,"path":1937,"stem":1938},"Архітектура та Best Practices","/javascript/react/tanstack-query/architecture-and-best-practices","03.javascript/04.react/04.tanstack-query/09.architecture-and-best-practices",{"title":1940,"path":1941,"stem":1942},"Server-Side Rendering (SSR) та Гідратація","/javascript/react/tanstack-query/server-side-rendering","03.javascript/04.react/04.tanstack-query/10.server-side-rendering",{"title":1944,"path":1945,"stem":1946},"Стратегії Тестування","/javascript/react/tanstack-query/testing-strategies","03.javascript/04.react/04.tanstack-query/11.testing-strategies",{"title":1948,"path":1949,"stem":1950},"Аутентифікація та Обробка Помилок","/javascript/react/tanstack-query/authentication-and-errors","03.javascript/04.react/04.tanstack-query/12.authentication-and-errors",{"title":1952,"path":1953,"stem":1954},"React Suspense та Майбутнє","/javascript/react/tanstack-query/react-suspense","03.javascript/04.react/04.tanstack-query/13.react-suspense",{"title":1956,"path":1957,"stem":1958},"Глибоке Занурення в Продуктивність","/javascript/react/tanstack-query/performance-deep-dive","03.javascript/04.react/04.tanstack-query/14.performance-deep-dive",{"title":1960,"icon":1875,"path":1961,"stem":1962,"children":1963},"React Router","/javascript/react/react-router","03.javascript/04.react/05.react-router/index",[1964,1966,1970,1974,1978,1982,1986,1990],{"title":1965,"path":1961,"stem":1962},"React Router: Навігаційна система сучасного вебу",{"title":1967,"path":1968,"stem":1969},"Налаштування та Базовий Роутинг","/javascript/react/react-router/setup-and-basic-routing","03.javascript/04.react/05.react-router/01.setup-and-basic-routing",{"title":1971,"path":1972,"stem":1973},"Динамічна Навігація","/javascript/react/react-router/navigation-and-links","03.javascript/04.react/05.react-router/02.navigation-and-links",{"title":1975,"path":1976,"stem":1977},"Вкладені Маршрути та Макети","/javascript/react/react-router/nested-routes-and-layouts","03.javascript/04.react/05.react-router/03.nested-routes-and-layouts",{"title":1979,"path":1980,"stem":1981},"Динамічні Маршрути та Параметри","/javascript/react/react-router/dynamic-routing","03.javascript/04.react/05.react-router/04.dynamic-routing",{"title":1983,"path":1984,"stem":1985},"Data APIs: Loaders та Actions","/javascript/react/react-router/data-loading","03.javascript/04.react/05.react-router/05.data-loading",{"title":1987,"path":1988,"stem":1989},"Просунуті Патерни","/javascript/react/react-router/advanced-patterns","03.javascript/04.react/05.react-router/06.advanced-patterns",{"title":1991,"path":1992,"stem":1993},"Legacy Routing: Компонентний підхід","/javascript/react/react-router/legacy-routing","03.javascript/04.react/05.react-router/07.legacy-routing",{"title":1995,"icon":132,"path":1996,"stem":1997,"children":1998},"Redux","/javascript/react/redux","03.javascript/04.react/06.redux/index",[1999,2001,2017,2046,2055,2076,2092,2121],{"title":2000,"path":1996,"stem":1997},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2002,"stem":2003,"children":2004,"page":59},"/javascript/react/redux/fundamentals","03.javascript/04.react/06.redux/01.fundamentals",[2005,2009,2013],{"title":2006,"path":2007,"stem":2008},"Вступ до State Management","/javascript/react/redux/fundamentals/intro-state-management","03.javascript/04.react/06.redux/01.fundamentals/01.intro-state-management",{"title":2010,"path":2011,"stem":2012},"Філософія Redux та Три Принципи","/javascript/react/redux/fundamentals/redux-philosophy","03.javascript/04.react/06.redux/01.fundamentals/02.redux-philosophy",{"title":2014,"path":2015,"stem":2016},"Чисті функції та Іммутабельність","/javascript/react/redux/fundamentals/pure-functions-immutability","03.javascript/04.react/06.redux/01.fundamentals/03.pure-functions-immutability",{"title":2018,"icon":132,"path":2019,"stem":2020,"children":2021,"page":59},"Classic Redux","/javascript/react/redux/classic-redux","03.javascript/04.react/06.redux/02.classic-redux",[2022,2026,2030,2034,2038,2042],{"title":2023,"path":2024,"stem":2025},"Створення Store (Classic Redux)","/javascript/react/redux/classic-redux/store-setup","03.javascript/04.react/06.redux/02.classic-redux/01.store-setup",{"title":2027,"path":2028,"stem":2029},"Actions, Constants та Action Creators","/javascript/react/redux/classic-redux/actions-constants","03.javascript/04.react/06.redux/02.classic-redux/02.actions-constants",{"title":2031,"path":2032,"stem":2033},"Логіка Reducers","/javascript/react/redux/classic-redux/reducers","03.javascript/04.react/06.redux/02.classic-redux/03.reducers",{"title":2035,"path":2036,"stem":2037},"Комбінування Reducers (Root Reducer)","/javascript/react/redux/classic-redux/data-flow","03.javascript/04.react/06.redux/02.classic-redux/04.data-flow",{"title":2039,"path":2040,"stem":2041},"Підключення до React (React-Redux)","/javascript/react/redux/classic-redux/react-redux-connection","03.javascript/04.react/06.redux/02.classic-redux/05.react-redux-connection",{"title":2043,"path":2044,"stem":2045},"Middleware та Асинхронність (Redux Thunk)","/javascript/react/redux/classic-redux/middleware-thunk","03.javascript/04.react/06.redux/02.classic-redux/06.middleware-thunk",{"title":2047,"icon":132,"path":2048,"stem":2049,"children":2050,"page":59},"Transition To Rtk","/javascript/react/redux/transition-to-rtk","03.javascript/04.react/06.redux/03.transition-to-rtk",[2051],{"title":2052,"path":2053,"stem":2054},"Проблеми класичного Redux","/javascript/react/redux/transition-to-rtk/problems-with-classic","03.javascript/04.react/06.redux/03.transition-to-rtk/01.problems-with-classic",{"title":2056,"icon":132,"path":2057,"stem":2058,"children":2059,"page":59},"Redux Toolkit","/javascript/react/redux/redux-toolkit","03.javascript/04.react/06.redux/04.redux-toolkit",[2060,2064,2068,2072],{"title":2061,"path":2062,"stem":2063},"Налаштування Store з configureStore","/javascript/react/redux/redux-toolkit/configure-store","03.javascript/04.react/06.redux/04.redux-toolkit/01.configure-store",{"title":2065,"path":2066,"stem":2067},"createSlice: Революція в Redux","/javascript/react/redux/redux-toolkit/create-slice","03.javascript/04.react/06.redux/04.redux-toolkit/02.create-slice",{"title":2069,"path":2070,"stem":2071},"Асинхронність з createAsyncThunk","/javascript/react/redux/redux-toolkit/async-thunks","03.javascript/04.react/06.redux/04.redux-toolkit/03.async-thunks",{"title":2073,"path":2074,"stem":2075},"04. Entity Adapter: Керування нормалізованим станом","/javascript/react/redux/redux-toolkit/entity-adapter","03.javascript/04.react/06.redux/04.redux-toolkit/04.entity-adapter",{"title":2077,"icon":92,"path":2078,"stem":2079,"children":2080,"page":59},"Advanced","/javascript/react/redux/advanced","03.javascript/04.react/06.redux/05.advanced",[2081,2085,2089],{"title":2082,"path":2083,"stem":2084},"Мемоізація та Селектори: Повний Гайд по Reselect","/javascript/react/redux/advanced/selectors-reselect","03.javascript/04.react/06.redux/05.advanced/01.selectors-reselect",{"title":2086,"path":2087,"stem":2088},"RTK Query: Архітектура Серверного Кешу","/javascript/react/redux/advanced/rtk-query-intro","03.javascript/04.react/06.redux/05.advanced/02.rtk-query-intro",{"title":1936,"path":2090,"stem":2091},"/javascript/react/redux/advanced/architecture-best-practices","03.javascript/04.react/06.redux/05.advanced/03.architecture-best-practices",{"title":2093,"icon":132,"path":2094,"stem":2095,"children":2096,"page":59},"Project Kanban","/javascript/react/redux/project-kanban","03.javascript/04.react/06.redux/06.project-kanban",[2097,2101,2105,2109,2113,2117],{"title":2098,"path":2099,"stem":2100},"Проєкт: Kanban Board (Trello Clone)","/javascript/react/redux/project-kanban/project-overview","03.javascript/04.react/06.redux/06.project-kanban/01.project-overview",{"title":2102,"path":2103,"stem":2104},"Налаштування та Типізація","/javascript/react/redux/project-kanban/setup-and-types","03.javascript/04.react/06.redux/06.project-kanban/02.setup-and-types",{"title":2106,"path":2107,"stem":2108},"Board Slice: Серце Дошки","/javascript/react/redux/project-kanban/board-slice","03.javascript/04.react/06.redux/06.project-kanban/03.board-slice",{"title":2110,"path":2111,"stem":2112},"Логіка Drag & Drop","/javascript/react/redux/project-kanban/drag-and-drop-logic","03.javascript/04.react/06.redux/06.project-kanban/04.drag-and-drop-logic",{"title":2114,"path":2115,"stem":2116},"Інтеграція з RTK Query","/javascript/react/redux/project-kanban/rtk-query-integration","03.javascript/04.react/06.redux/06.project-kanban/05.rtk-query-integration",{"title":2118,"path":2119,"stem":2120},"Optimistic Updates","/javascript/react/redux/project-kanban/optimistic-updates","03.javascript/04.react/06.redux/06.project-kanban/06.optimistic-updates",{"title":2122,"icon":132,"path":2123,"stem":2124,"children":2125,"page":59},"Testing","/javascript/react/redux/testing","03.javascript/04.react/06.redux/07.testing",[2126,2130,2134,2138,2142],{"title":2127,"path":2128,"stem":2129},"Тестування Redux","/javascript/react/redux/testing/intro-testing","03.javascript/04.react/06.redux/07.testing/01.intro-testing",{"title":2131,"path":2132,"stem":2133},"Тестування Reducers","/javascript/react/redux/testing/testing-reducers","03.javascript/04.react/06.redux/07.testing/02.testing-reducers",{"title":2135,"path":2136,"stem":2137},"Тестування Селекторів","/javascript/react/redux/testing/testing-selectors","03.javascript/04.react/06.redux/07.testing/03.testing-selectors",{"title":2139,"path":2140,"stem":2141},"Тестування Компонентів (Integration)","/javascript/react/redux/testing/testing-components","03.javascript/04.react/06.redux/07.testing/04.testing-components",{"title":2143,"path":2144,"stem":2145},"Тестування Async Thunks","/javascript/react/redux/testing/testing-thunks","03.javascript/04.react/06.redux/07.testing/05.testing-thunks",{"title":2147,"icon":132,"path":2148,"stem":2149,"children":2150},"Ui Libraries","/javascript/react/ui-libraries","03.javascript/04.react/07.ui-libraries/index",[2151,2153,2157,2161,2165,2169,2173],{"title":2152,"path":2148,"stem":2149},"UI Бібліотеки в React",{"title":2154,"path":2155,"stem":2156},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","/javascript/react/ui-libraries/introduction-to-ui-libraries","03.javascript/04.react/07.ui-libraries/01.introduction-to-ui-libraries",{"title":2158,"path":2159,"stem":2160},"Філософія shadcn/ui: \"Not a Component Library\"","/javascript/react/ui-libraries/shadcn-philosophy","03.javascript/04.react/07.ui-libraries/02.shadcn-philosophy",{"title":2162,"path":2163,"stem":2164},"Установка та Налаштування shadcn/ui","/javascript/react/ui-libraries/shadcn-installation","03.javascript/04.react/07.ui-libraries/03.shadcn-installation",{"title":2166,"path":2167,"stem":2168},"Базові Компоненти shadcn/ui: Фундамент Інтерфейсу","/javascript/react/ui-libraries/shadcn-components-basics","03.javascript/04.react/07.ui-libraries/04.shadcn-components-basics",{"title":2170,"path":2171,"stem":2172},"Компоненти Форм: Побудова Інтерактивних Form","/javascript/react/ui-libraries/shadcn-components-forms","03.javascript/04.react/07.ui-libraries/05.shadcn-components-forms",{"title":2174,"path":2175,"stem":2176},"Складні Компоненти: Dialog, Dropdown, Table та Command","/javascript/react/ui-libraries/shadcn-components-advanced","03.javascript/04.react/07.ui-libraries/06.shadcn-components-advanced",{"title":2178,"icon":2179,"path":2180,"stem":2181,"children":2182,"page":59},"TypeScript","i-devicon-typescript","/javascript/typescript","03.javascript/05.typescript",[2183,2187,2191,2195,2199,2203,2207,2211],{"title":2184,"path":2185,"stem":2186},"TypeScript: Броня для вашого коду","/javascript/typescript/intro-and-basic-types","03.javascript/05.typescript/01.intro-and-basic-types",{"title":2188,"path":2189,"stem":2190},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","/javascript/typescript/interfaces-and-advanced-types","03.javascript/05.typescript/02.interfaces-and-advanced-types",{"title":2192,"path":2193,"stem":2194},"Алхімія Типів: Generics та Utility Types","/javascript/typescript/generics-and-utilities","03.javascript/05.typescript/03.generics-and-utilities",{"title":2196,"path":2197,"stem":2198},"Архітектура та Шаблони: Класи в TypeScript","/javascript/typescript/classes-and-oop","03.javascript/05.typescript/04.classes-and-oop",{"title":2200,"path":2201,"stem":2202},"Продакшн та Екосистема: Advanced Config & Workflow","/javascript/typescript/advanced-patterns-and-config","03.javascript/05.typescript/05.advanced-patterns-and-config",{"title":2204,"path":2205,"stem":2206},"TypeScript у світі React","/javascript/typescript/react-basics","03.javascript/05.typescript/06.react-basics",{"title":2208,"path":2209,"stem":2210},"React + TypeScript: Продвинуті патерни","/javascript/typescript/react-advanced","03.javascript/05.typescript/07.react-advanced",{"title":2212,"path":2213,"stem":2214},"React + TypeScript: Екосистема та бібліотеки","/javascript/typescript/react-ecosystem","03.javascript/05.typescript/08.react-ecosystem",{"title":2216,"path":2217,"stem":2218},"Atomic Design","/javascript/atomic-design","03.javascript/2.atomic-design",{"title":2220,"icon":2221,"path":2222,"stem":2223,"children":2224,"page":59},"Java","i-devicon-java","/java","04.java",[2225,2228,2231,2235,2239,2243,2247],{"title":162,"path":2226,"stem":2227},"/java/data-mapper-part1","04.java/01.data-mapper-part1",{"title":166,"path":2229,"stem":2230},"/java/data-mapper-part2","04.java/02.data-mapper-part2",{"title":2232,"path":2233,"stem":2234},"Service Layer: Організація бізнес-логіки","/java/service-layer","04.java/03.service-layer",{"title":2236,"path":2237,"stem":2238},"Rich Domain Model та State Pattern","/java/rich-domain-model","04.java/04.rich-domain-model",{"title":2240,"path":2241,"stem":2242},"Патерни для складної бізнес-логіки","/java/business-logic-patterns","04.java/05.business-logic-patterns",{"title":2244,"path":2245,"stem":2246},"Обробка помилок та валідація","/java/error-handling-validation","04.java/06.error-handling-validation",{"title":2248,"path":2249,"stem":2250,"children":2251,"page":59},"Проектування баз даних","/java/pr2","04.java/pr2",[2252,2256,2260,2264,2268,2272,2276,2280,2284,2288,2292,2296,2300,2304,2308,2312,2316,2320,2324,2328,2332,2336,2340,2344,2348],{"title":2253,"path":2254,"stem":2255},"Концептуальне моделювання: Мистецтво розуміння предметної області","/java/pr2/conceptual-modeling","04.java/pr2/01.conceptual-modeling",{"title":2257,"path":2258,"stem":2259},"Логічне моделювання: Від бізнес-ідей до структур даних","/java/pr2/logical-modeling","04.java/pr2/02.logical-modeling",{"title":2261,"path":2262,"stem":2263},"Нормалізація: Гігієна даних та боротьба з аномаліями","/java/pr2/normalization","04.java/pr2/03.normalization",{"title":2265,"path":2266,"stem":2267},"Фізична схема: Від абстракції до DDL","/java/pr2/physical-schema","04.java/pr2/04.physical-schema",{"title":2269,"path":2270,"stem":2271},"Архітектурна класифікація таблиць","/java/pr2/table-classification","04.java/pr2/05.table-classification",{"title":2273,"path":2274,"stem":2275},"Database Migrations: Версіонування схеми з Flyway","/java/pr2/database-migrations","04.java/pr2/06.database-migrations",{"title":2277,"path":2278,"stem":2279},"А що, якби це була не реляційна БД?","/java/pr2/beyond-relational","04.java/pr2/07.beyond-relational",{"title":2281,"path":2282,"stem":2283},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","/java/pr2/impedance-mismatch","04.java/pr2/09.impedance-mismatch",{"title":2285,"path":2286,"stem":2287},"JDBC: Перший контакт із базою даних","/java/pr2/jdbc-fundamentals","04.java/pr2/10.jdbc-fundamentals",{"title":2289,"path":2290,"stem":2291},"Якість коду: Spotless, SpotBugs та SonarQube","/java/pr2/10a.code-quality","04.java/pr2/10a.code-quality",{"title":2293,"path":2294,"stem":2295},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","/java/pr2/connection-pool","04.java/pr2/11.connection-pool",{"title":2297,"path":2298,"stem":2299},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","/java/pr2/row-data-gateway","04.java/pr2/12.row-data-gateway",{"title":2301,"path":2302,"stem":2303},"Table Data Gateway: Фасад таблиці як архітектурний відступ","/java/pr2/table-data-gateway","04.java/pr2/13.table-data-gateway",{"title":2305,"path":2306,"stem":2307},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","/java/pr2/repository-data-mapper","04.java/pr2/14.repository-data-mapper",{"title":2309,"path":2310,"stem":2311},"Identity Map: Кешування сутностей у рамках сесії","/java/pr2/identity-map","04.java/pr2/15.identity-map",{"title":2313,"path":2314,"stem":2315},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","/java/pr2/unit-of-work","04.java/pr2/16.unit-of-work",{"title":2317,"path":2318,"stem":2319},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","/java/pr2/strategy-sql","04.java/pr2/17.strategy-sql",{"title":2321,"path":2322,"stem":2323},"Proxy: Lazy Loading для One-To-Many колекцій","/java/pr2/proxy-lazy-loading","04.java/pr2/18.proxy-lazy-loading",{"title":2325,"path":2326,"stem":2327},"Generic Repository через Java Reflection: анотації та динамічний SQL","/java/pr2/generic-repository-reflection","04.java/pr2/19.generic-repository-reflection",{"title":2329,"path":2330,"stem":2331},"Specification Pattern: Композиція бізнес-правил для складних запитів","/java/pr2/specification-pattern","04.java/pr2/20.specification-pattern",{"title":2333,"path":2334,"stem":2335},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","/java/pr2/20a.advanced-specifications","04.java/pr2/20a.advanced-specifications",{"title":2337,"path":2338,"stem":2339},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","/java/pr2/asynchronous-jdbc","04.java/pr2/21.asynchronous-jdbc",{"title":2341,"path":2342,"stem":2343},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","/java/pr2/integration-testing-h2","04.java/pr2/22.integration-testing-h2",{"title":2345,"path":2346,"stem":2347},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","/java/pr2/integration-testing-testcontainers","04.java/pr2/23.integration-testing-testcontainers",{"title":2349,"path":2350,"stem":2351},"Модуль \"Проектування реляційних баз даних\" для 04.java/pr2","/java/pr2/implementation_plan","04.java/pr2/implementation_plan",{"title":2353,"icon":2354,"path":2355,"stem":2356,"children":2357,"page":59},"Бази даних","i-lucide-database","/databases","06.databases",[2358,2388,2411,2448,2477,2495,2529,2541,2550],{"title":2359,"icon":2360,"path":2361,"stem":2362,"children":2363,"page":59},"Intro","i-lucide-play","/databases/intro","06.databases/01.intro",[2364,2368,2372,2376,2380,2384],{"title":2365,"path":2366,"stem":2367},"Введення в теорію баз даних","/databases/intro/introduction-to-databases","06.databases/01.intro/01.introduction-to-databases",{"title":2369,"path":2370,"stem":2371},"Реляційна модель даних","/databases/intro/relational-model-theory","06.databases/01.intro/02.relational-model-theory",{"title":2373,"path":2374,"stem":2375},"ER-моделювання","/databases/intro/er-modeling","06.databases/01.intro/03.er-modeling",{"title":2377,"path":2378,"stem":2379},"Логічне проектування БД","/databases/intro/logical-schema","06.databases/01.intro/04.logical-schema",{"title":2381,"path":2382,"stem":2383},"Класифікація таблиць","/databases/intro/table-classification","06.databases/01.intro/05.table-classification",{"title":2385,"path":2386,"stem":2387},"PlantUML для баз даних","/databases/intro/plantuml-diagrams","06.databases/01.intro/06.plantuml-diagrams",{"title":2389,"icon":2354,"path":2390,"stem":2391,"children":2392,"page":59},"MS SQL Server Start","/databases/ms-sql-server-start","06.databases/02.ms-sql-server-start",[2393,2397,2403,2407],{"title":2394,"path":2395,"stem":2396},"Типи даних у MS SQL Server","/databases/ms-sql-server-start/data-types","06.databases/02.ms-sql-server-start/01.data-types",{"title":2398,"path":2399,"stem":2400,"children":2401},"Індекси у MS SQL Server","/databases/ms-sql-server-start/sql-indexes","06.databases/02.ms-sql-server-start/02.sql-indexes",[2402],{"title":2398,"path":2399,"stem":2400},{"title":2404,"path":2405,"stem":2406},"Системні бази даних MS SQL Server","/databases/ms-sql-server-start/system-databases","06.databases/02.ms-sql-server-start/03.system-databases",{"title":2408,"path":2409,"stem":2410},"Огляд мови SQL та запитів","/databases/ms-sql-server-start/sql-queries-overview","06.databases/02.ms-sql-server-start/04.sql-queries-overview",{"title":2412,"icon":2354,"path":2413,"stem":2414,"children":2415,"page":59},"SQL","/databases/sql","06.databases/03.sql",[2416,2420,2424,2428,2432,2436,2440,2444],{"title":2417,"path":2418,"stem":2419},"Налаштування демонстраційної бази даних","/databases/sql/sample-database-setup","06.databases/03.sql/00.sample-database-setup",{"title":2421,"path":2422,"stem":2423},"DDL - Створення таблиць (CREATE TABLE)","/databases/sql/ddl-create-table","06.databases/03.sql/01.ddl-create-table",{"title":2425,"path":2426,"stem":2427},"DDL - Зміна та видалення таблиць (ALTER, DROP)","/databases/sql/ddl-alter-drop-table","06.databases/03.sql/02.ddl-alter-drop-table",{"title":2429,"path":2430,"stem":2431},"SELECT запити - Основи","/databases/sql/select-queries-fundamentals","06.databases/03.sql/03.select-queries-fundamentals",{"title":2433,"path":2434,"stem":2435},"SELECT запити - Розширені можливості","/databases/sql/select-queries-advanced","06.databases/03.sql/04.select-queries-advanced",{"title":2437,"path":2438,"stem":2439},"INSERT запити - Додавання даних","/databases/sql/insert-queries","06.databases/03.sql/05.insert-queries",{"title":2441,"path":2442,"stem":2443},"UPDATE та DELETE запити","/databases/sql/update-delete-queries","06.databases/03.sql/06.update-delete-queries",{"title":2445,"path":2446,"stem":2447},"Транзакції в SQL","/databases/sql/transactions","06.databases/03.sql/07.transactions",{"title":2449,"icon":2354,"path":2450,"stem":2451,"children":2452,"page":59},"Multi Table Databases","/databases/multi-table-databases","06.databases/04.multi-table-databases",[2453,2457,2461,2465,2469,2473],{"title":2454,"path":2455,"stem":2456},"Зв'язки та нормалізація БД","/databases/multi-table-databases/relationships-and-normalization","06.databases/04.multi-table-databases/00.relationships-and-normalization",{"title":2458,"path":2459,"stem":2460},"INNER JOIN - З'єднання таблиць","/databases/multi-table-databases/inner-join","06.databases/04.multi-table-databases/01.inner-join",{"title":2462,"path":2463,"stem":2464},"OUTER JOINs - LEFT, RIGHT, FULL","/databases/multi-table-databases/outer-joins","06.databases/04.multi-table-databases/02.outer-joins",{"title":2466,"path":2467,"stem":2468},"CROSS та SELF JOINs","/databases/multi-table-databases/cross-self-joins","06.databases/04.multi-table-databases/03.cross-self-joins",{"title":2470,"path":2471,"stem":2472},"Підзапити (Subqueries)","/databases/multi-table-databases/subqueries","06.databases/04.multi-table-databases/04.subqueries",{"title":2474,"path":2475,"stem":2476},"Агрегації з JOIN","/databases/multi-table-databases/aggregations-with-joins","06.databases/04.multi-table-databases/05.aggregations-with-joins",{"title":2478,"icon":2479,"path":2480,"stem":2481,"children":2482,"page":59},"Aggregate Functions","i-lucide-calculator","/databases/aggregate-functions","06.databases/05.aggregate-functions",[2483,2487,2491],{"title":2484,"path":2485,"stem":2486},"Функції агрегування в MS SQL Server","/databases/aggregate-functions/introduction-aggregate-functions","06.databases/05.aggregate-functions/01.introduction-aggregate-functions",{"title":2488,"path":2489,"stem":2490},"Групування даних в MS SQL Server","/databases/aggregate-functions/grouping-data","06.databases/05.aggregate-functions/02.grouping-data",{"title":2492,"path":2493,"stem":2494},"Підзапити з агрегатними функціями","/databases/aggregate-functions/subqueries-aggregates","06.databases/05.aggregate-functions/03.subqueries-aggregates",{"title":2496,"icon":2497,"path":2498,"stem":2499,"children":2500,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","/databases/triggers-stored-procedures","06.databases/07.triggers-stored-procedures",[2501,2505,2509,2513,2517,2521,2525],{"title":2502,"path":2503,"stem":2504},"DML-тригери","/databases/triggers-stored-procedures/dml-triggers","06.databases/07.triggers-stored-procedures/01.dml-triggers",{"title":2506,"path":2507,"stem":2508},"DDL-тригери","/databases/triggers-stored-procedures/ddl-triggers","06.databases/07.triggers-stored-procedures/02.ddl-triggers",{"title":2510,"path":2511,"stem":2512},"Transact-SQL розширення","/databases/triggers-stored-procedures/transact-sql-extensions","06.databases/07.triggers-stored-procedures/03.transact-sql-extensions",{"title":2514,"path":2515,"stem":2516},"Транзакції","/databases/triggers-stored-procedures/transactions","06.databases/07.triggers-stored-procedures/04.transactions",{"title":2518,"path":2519,"stem":2520},"Зберігаємі процедури","/databases/triggers-stored-procedures/stored-procedures","06.databases/07.triggers-stored-procedures/05.stored-procedures",{"title":2522,"path":2523,"stem":2524},"Користувацькі функції","/databases/triggers-stored-procedures/user-defined-functions","06.databases/07.triggers-stored-procedures/06.user-defined-functions",{"title":2526,"path":2527,"stem":2528},"Безпека баз даних","/databases/triggers-stored-procedures/security","06.databases/07.triggers-stored-procedures/08.security",{"title":2526,"icon":793,"path":2530,"stem":2531,"children":2532,"page":59},"/databases/security","06.databases/08.security",[2533,2537],{"title":2534,"path":2535,"stem":2536},"Вступ до безпеки баз даних","/databases/security/introduction","06.databases/08.security/01.introduction",{"title":2538,"path":2539,"stem":2540},"Системні представлення та метадані","/databases/security/system-views","06.databases/08.security/02.system-views",{"title":2542,"icon":2543,"path":2544,"stem":2545,"children":2546,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","/databases/backup-recovery","06.databases/09.backup-recovery",[2547],{"title":2542,"path":2548,"stem":2549},"/databases/backup-recovery/backup-restore","06.databases/09.backup-recovery/01.backup-restore",{"title":2551,"icon":2552,"path":2553,"stem":2554,"children":2555,"page":59},"Повнотекстовий пошук","i-lucide-search","/databases/full-text-search","06.databases/10.full-text-search",[2556],{"title":2551,"path":2557,"stem":2558},"/databases/full-text-search/full-text-search","06.databases/10.full-text-search/01.full-text-search",{"title":2560,"icon":2561,"path":2562,"stem":2563,"children":2564,"page":59},"Tools","i-lucide-wrench","/tools","07.tools",[2565],{"title":2566,"icon":2567,"path":2568,"stem":2569,"children":2570},"Docker","i-simple-icons-docker","/tools/docker","07.tools/01.docker/index",[2571,2573,2577,2581,2585,2589,2593,2597,2601,2605,2609,2613,2617,2621,2625,2629,2633,2637],{"title":2572,"path":2568,"stem":2569},"Docker: від нуля до production",{"title":2574,"path":2575,"stem":2576},"Контейнеризація — від проблеми до рішення","/tools/docker/containerization-concept","07.tools/01.docker/01.containerization-concept",{"title":2578,"path":2579,"stem":2580},"Docker — що це і навіщо?","/tools/docker/docker-what-and-why","07.tools/01.docker/02.docker-what-and-why",{"title":2582,"path":2583,"stem":2584},"Архітектура Docker Engine","/tools/docker/docker-architecture","07.tools/01.docker/03.docker-architecture",{"title":2586,"path":2587,"stem":2588},"Встановлення Docker","/tools/docker/installation","07.tools/01.docker/04.installation",{"title":2590,"path":2591,"stem":2592},"Перший контейнер — docker run","/tools/docker/first-container","07.tools/01.docker/05.first-container",{"title":2594,"path":2595,"stem":2596},"Життєвий цикл контейнера","/tools/docker/container-lifecycle","07.tools/01.docker/06.container-lifecycle",{"title":2598,"path":2599,"stem":2600},"Docker Images — фундаментальні концепції","/tools/docker/docker-images-fundamentals","07.tools/01.docker/07.docker-images-fundamentals",{"title":2602,"path":2603,"stem":2604},"Dockerfile — основи","/tools/docker/dockerfile-basics","07.tools/01.docker/08.dockerfile-basics",{"title":2606,"path":2607,"stem":2608},"Dockerfile — просунуті техніки","/tools/docker/dockerfile-advanced","07.tools/01.docker/09.dockerfile-advanced",{"title":2610,"path":2611,"stem":2612},"Build Context та кешування шарів","/tools/docker/build-context-and-cache","07.tools/01.docker/10.build-context-and-cache",{"title":2614,"path":2615,"stem":2616},"Реєстри Docker-образів","/tools/docker/image-registries","07.tools/01.docker/11.image-registries",{"title":2618,"path":2619,"stem":2620},"Контейнеризація .NET додатків","/tools/docker/dotnet-containerization","07.tools/01.docker/12.dotnet-containerization",{"title":2622,"path":2623,"stem":2624},"Томи та збереження даних","/tools/docker/volumes-and-data","07.tools/01.docker/13.volumes-and-data",{"title":2626,"path":2627,"stem":2628},"Основи мережі в Docker","/tools/docker/networking-basics","07.tools/01.docker/14.networking-basics",{"title":2630,"path":2631,"stem":2632},"Змінні оточення та конфігурація","/tools/docker/environment-and-configuration","07.tools/01.docker/15.environment-and-configuration",{"title":2634,"path":2635,"stem":2636},"Docker Compose — оркестрація контейнерів","/tools/docker/docker-compose-basics","07.tools/01.docker/16.docker-compose-basics",{"title":2638,"path":2639,"stem":2640},"Docker Compose — Multi-Service застосунки","/tools/docker/compose-multi-service","07.tools/01.docker/17.compose-multi-service",{"title":2642,"icon":2643,"path":2644,"stem":2645,"children":2646,"page":59},"Software Engineering","i-lucide-code-2","/software-engineering","09.software-engineering",[2647,2651,2655,2659,2663,2667,2671,2675,2679,2683,2687],{"title":2648,"path":2649,"stem":2650},"1. Аналіз предметної області. Експертні знання та складність","/software-engineering/intro.subdomains","09.software-engineering/01.intro.subdomains",{"title":2652,"path":2653,"stem":2654},"2. Обмежені контексти. Інтеграція обмежених контекстів","/software-engineering/integrating-limited-contexts","09.software-engineering/02.integrating-limited-contexts",{"title":2656,"path":2657,"stem":2658},"3. Реалізація простої бізнес-логіки","/software-engineering/simple","09.software-engineering/03.simple",{"title":2660,"path":2661,"stem":2662},"4. Опрацювання складної бізнес-логіки","/software-engineering/complex-business-logic","09.software-engineering/04.complex-business-logic",{"title":2664,"path":2665,"stem":2666},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","/software-engineering/modelling-the-time-factor","09.software-engineering/05.modelling-the-time-factor",{"title":2668,"path":2669,"stem":2670},"6. Архітектурні патерни","/software-engineering/architectural-patterns","09.software-engineering/06.architectural-patterns",{"title":2672,"path":2673,"stem":2674},"Паттерни взаємодії","/software-engineering/patterns-of-interaction","09.software-engineering/07.patterns-of-interaction",{"title":2676,"path":2677,"stem":2678},"Евристика проєктування","/software-engineering/design-heuristics","09.software-engineering/08.design-heuristics",{"title":2680,"path":2681,"stem":2682},"Еволюція проєктних рішень","/software-engineering/evolution-of-design-solutions","09.software-engineering/09.evolution-of-design-solutions",{"title":2684,"path":2685,"stem":2686},"EventStorming","/software-engineering/eventstorming","09.software-engineering/10.eventstorming",{"title":2688,"path":2689,"stem":2690},"DDD на практиці","/software-engineering/ddd-in-practice","09.software-engineering/11.ddd-in-practice",{"title":2692,"icon":943,"path":2693,"stem":2694,"children":2695,"page":59},"DDD","/ddd","10.ddd",[2696,2700,2704,2708,2712,2716,2720,2724,2728,2732,2736,2740,2744],{"title":2697,"path":2698,"stem":2699},"Аналіз предметної області","/ddd/domain-analysis","10.ddd/01.domain-analysis",{"title":2701,"path":2702,"stem":2703},"Експертні знання про предметну область","/ddd/domain-expert-knowledge","10.ddd/02.domain-expert-knowledge",{"title":2705,"path":2706,"stem":2707},"Як осмислити складність предметної області","/ddd/managing-domain-complexity","10.ddd/03.managing-domain-complexity",{"title":2709,"path":2710,"stem":2711},"Інтеграція обмежених контекстів","/ddd/bounded-context-integration","10.ddd/04.bounded-context-integration",{"title":2713,"path":2714,"stem":2715},"Реалізація простої бізнес-логіки","/ddd/simple-business-logic","10.ddd/05.simple-business-logic",{"title":2717,"path":2718,"stem":2719},"Обробка складної бізнес-логіки","/ddd/complex-business-logic","10.ddd/06.complex-business-logic",{"title":2721,"path":2722,"stem":2723},"Моделювання фактора часу","/ddd/time-modeling","10.ddd/07.time-modeling",{"title":2725,"path":2726,"stem":2727},"Глава 8. Архітектурні Патерни","/ddd/architectural-patterns","10.ddd/08.architectural-patterns",{"title":2729,"path":2730,"stem":2731},"Глава 9. Патерни Взаємодії","/ddd/interaction-patterns","10.ddd/09.interaction-patterns",{"title":2733,"path":2734,"stem":2735},"Глава 10. Проектні Евристики","/ddd/design-heuristics","10.ddd/10.design-heuristics",{"title":2737,"path":2738,"stem":2739},"Глава 11. Еволюція Проектних Рішень","/ddd/evolution-of-design-decisions","10.ddd/11.evolution-of-design-decisions",{"title":2741,"path":2742,"stem":2743},"Глава 12. EventStorming","/ddd/event-storming","10.ddd/12.event-storming",{"title":2745,"path":2746,"stem":2747},"Глава 13. DDD на Практиці","/ddd/ddd-in-practice","10.ddd/13.ddd-in-practice",{"title":2749,"icon":2750,"path":2751,"stem":2752,"children":2753,"page":59},"Media Streaming","i-lucide-video","/media-streaming","11.media-streaming",[2754,2758,2762,2766,2770,2774,2778],{"title":2755,"path":2756,"stem":2757},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","/media-streaming/introduction","11.media-streaming/01.introduction",{"title":2759,"path":2760,"stem":2761},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","/media-streaming/audio-video-anatomy","11.media-streaming/02.audio-video-anatomy",{"title":2763,"path":2764,"stem":2765},"03. The Gym: FFmpeg Deep Dive","/media-streaming/ffmpeg-gym","11.media-streaming/03.ffmpeg-gym",{"title":2767,"path":2768,"stem":2769},"04. HLS Protocol: HTTP Live Streaming у Деталях","/media-streaming/hls-protocol","11.media-streaming/04.hls-protocol",{"title":2771,"path":2772,"stem":2773},"05. DASH Protocol: Відкритий Стандарт","/media-streaming/dash-protocol","11.media-streaming/05.dash-protocol",{"title":2775,"path":2776,"stem":2777},"06. Масштабування: CDN та Adaptive Bitrate","/media-streaming/cdn-and-adaptive-bitrate","11.media-streaming/06.cdn-and-adaptive-bitrate",{"title":2779,"path":2780,"stem":2781},"07. Війна із Затримкою (Latency)","/media-streaming/realtime-latency","11.media-streaming/07.realtime-latency",{"title":2783,"icon":2784,"path":2785,"stem":2786,"children":2787,"page":59},"HTML & CSS","i-devicon-html5","/html-css","12.html-css",[2788,2792,2796,2800,2804,2808,2812,2816,2820,2824,2828,2832,2836,2840,2844,2848,2852,2856,2860,2864,2868,2872,2876,2880,2884,2888,2892,2896,2900,2904],{"title":2789,"path":2790,"stem":2791},"Вступ до HTML. Структура документа","/html-css/intro-html-structure","12.html-css/01.intro-html-structure",{"title":2793,"path":2794,"stem":2795},"Форматування тексту в HTML","/html-css/html-text-formatting","12.html-css/02.html-text-formatting",{"title":2797,"path":2798,"stem":2799},"Посилання та зображення в HTML","/html-css/html-links-images","12.html-css/03.html-links-images",{"title":2801,"path":2802,"stem":2803},"Списки та таблиці в HTML","/html-css/html-lists-tables","12.html-css/04.html-lists-tables",{"title":2805,"path":2806,"stem":2807},"Форми в HTML","/html-css/html-forms","12.html-css/05.html-forms",{"title":2809,"path":2810,"stem":2811},"Семантичні елементи HTML5","/html-css/html-semantic-elements","12.html-css/06.html-semantic-elements",{"title":2813,"path":2814,"stem":2815},"Мультимедіа та розширені елементи HTML","/html-css/html-multimedia-advanced","12.html-css/07.html-multimedia-advanced",{"title":2817,"path":2818,"stem":2819},"Мікророзмітка та SEO в HTML","/html-css/html-microdata-seo","12.html-css/08.html-microdata-seo",{"title":2821,"path":2822,"stem":2823},"Вступ до CSS. Селектори та специфічність","/html-css/css-intro-selectors","12.html-css/09.css-intro-selectors",{"title":2825,"path":2826,"stem":2827},"Блокова модель CSS. Відступи. Box Sizing","/html-css/css-box-model","12.html-css/10.css-box-model",{"title":2829,"path":2830,"stem":2831},"Розміри у CSS: повний довідник одиниць і ключових слів","/html-css/10a.css-sizing","12.html-css/10a.css-sizing",{"title":2833,"path":2834,"stem":2835},"Типографіка в CSS. Шрифти та текст","/html-css/css-typography","12.html-css/11.css-typography",{"title":2837,"path":2838,"stem":2839},"Кольори та фони в CSS","/html-css/css-colors-backgrounds","12.html-css/12.css-colors-backgrounds",{"title":2841,"path":2842,"stem":2843},"Тіні та фільтри в CSS","/html-css/12b.css-shadows-filters","12.html-css/12b.css-shadows-filters",{"title":2845,"path":2846,"stem":2847},"CSS Flexbox: Фундамент гнучких макетів","/html-css/css-flexbox-fundamentals","12.html-css/13.css-flexbox-fundamentals",{"title":2849,"path":2850,"stem":2851},"CSS Flexbox: Вирівнювання та Позиціонування","/html-css/css-flexbox-alignment-sizing-and-patterns","12.html-css/14.css-flexbox-alignment-sizing-and-patterns",{"title":2853,"path":2854,"stem":2855},"CSS Grid. Двовимірний макет. Частина 1","/html-css/css-layout-grid","12.html-css/15.css-layout-grid",{"title":2857,"path":2858,"stem":2859},"CSS Grid. Двовимірний макет. Частина 2","/html-css/css-layout-grid-advanced","12.html-css/16.css-layout-grid-advanced",{"title":2861,"path":2862,"stem":2863},"Позиціонування в CSS. Z-index. Stacking Context","/html-css/css-positioning","12.html-css/17.css-positioning",{"title":2865,"path":2866,"stem":2867},"CSS Анімації та Переходи","/html-css/css-animations-transitions","12.html-css/18.css-animations-transitions",{"title":2869,"path":2870,"stem":2871},"Адаптивний дизайн. Media Queries. Частина 1","/html-css/css-responsive-media-queries","12.html-css/19.css-responsive-media-queries",{"title":2873,"path":2874,"stem":2875},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","/html-css/css-responsive-advanced","12.html-css/20.css-responsive-advanced",{"title":2877,"path":2878,"stem":2879},"CSS Custom Properties. Методології. Сучасний CSS","/html-css/css-variables-methodologies","12.html-css/21.css-variables-methodologies",{"title":2881,"path":2882,"stem":2883},"Сучасний CSS 2023–2025: Нові можливості","/html-css/css-modern-features","12.html-css/22.css-modern-features",{"title":2885,"path":2886,"stem":2887},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","/html-css/22a.css-nesting-modern-syntax","12.html-css/22a.css-nesting-modern-syntax",{"title":2889,"path":2890,"stem":2891},"CSS для форм та інтерактивних станів","/html-css/css-forms-interactive-states","12.html-css/23.css-forms-interactive-states",{"title":2893,"path":2894,"stem":2895},"Доступність у CSS (CSS Accessibility)","/html-css/css-accessibility","12.html-css/24.css-accessibility",{"title":2897,"path":2898,"stem":2899},"CSS-функції та сучасні sizing primitives","/html-css/css-functions-sizing","12.html-css/25.css-functions-sizing",{"title":2901,"path":2902,"stem":2903},"Rendering Pipeline і CSS Performance","/html-css/css-rendering-performance","12.html-css/26.css-rendering-performance",{"title":2905,"path":2906,"stem":2907},"CSS Best Practices: типові ситуації та правильні рішення","/html-css/css-best-practices","12.html-css/27.css-best-practices",{"title":2909,"path":2910,"stem":2911,"children":2912,"page":59},"Tailwind","/tailwind","21.tailwind",[2913,2917,2921,2925,2929,2933,2937,2941],{"title":2914,"path":2915,"stem":2916},"Що таке Tailwind CSS і навіщо він потрібен","/tailwind/tailwind-intro-philosophy","21.tailwind/01.tailwind-intro-philosophy",{"title":2918,"path":2919,"stem":2920},"Встановлення та налаштування Tailwind CSS v4","/tailwind/tailwind-installation-setup","21.tailwind/02.tailwind-installation-setup",{"title":2922,"path":2923,"stem":2924},"Utility-класи: основи та система Tailwind","/tailwind/tailwind-utility-classes-core","21.tailwind/03.tailwind-utility-classes-core",{"title":2926,"path":2927,"stem":2928},"Layout: Flexbox та Grid через Tailwind","/tailwind/tailwind-flexbox-grid","21.tailwind/04.tailwind-flexbox-grid",{"title":2930,"path":2931,"stem":2932},"Кастомізація теми через @theme у Tailwind v4","/tailwind/tailwind-theme-customization","21.tailwind/05.tailwind-theme-customization",{"title":2934,"path":2935,"stem":2936},"Варіанти: hover, focus, responsive, dark mode та нові v4","/tailwind/tailwind-variants-states","21.tailwind/06.tailwind-variants-states",{"title":2938,"path":2939,"stem":2940},"Типографіка та система кольорів у Tailwind v4","/tailwind/tailwind-typography-colors","21.tailwind/07.tailwind-typography-colors",{"title":2942,"path":2943,"stem":2944},"Компоненти та повторюваність: @apply, @utility та патерни","/tailwind/tailwind-components-patterns","21.tailwind/08.tailwind-components-patterns",{"title":2946,"path":2947,"stem":2948},"Showcase Компонентів kostyl.dev","/test-new-components","98.test-new-components",{"id":2950,"title":1335,"body":2951,"description":15315,"extension":15316,"links":15317,"meta":15318,"navigation":3021,"path":1336,"seo":15319,"stem":1337,"__hash__":15320},"docs/01.csharp/11.aspnet/12.web-api/11.health-checks-monitoring.md",{"type":2952,"value":2953,"toc":15271},"minimark",[2954,2958,2963,2967,3085,3091,3110,3120,3125,3288,3293,3320,3325,3333,3343,3350,3355,3366,3371,3402,3407,3478,3483,3623,3628,3634,3639,3714,3717,3734,3737,3741,3745,3750,3840,3914,3919,3925,3929,3997,4002,4084,4088,4091,4213,4218,4352,4354,4358,4362,4497,4499,4503,4509,4974,4979,5021,5026,5038,5135,5137,5141,5146,5321,5326,5341,5345,5483,5487,5502,5516,5520,5634,5638,5649,5651,5655,5659,5664,6524,6528,6565,6569,6574,7057,7061,7066,7694,7698,7981,7985,8018,8020,8024,8027,8031,8222,8232,8234,8238,8242,8642,8646,8868,8873,9114,9116,9120,9124,9127,9426,9431,9549,9553,9556,9826,9830,9833,10282,10286,10289,10692,10696,10699,11045,11047,11051,11055,11184,11186,11190,12871,12873,12877,14997,14999,15003,15010,15014,15019,15036,15041,15058,15063,15077,15082,15096,15101,15112,15117,15128,15132,15177,15207,15209,15213,15255,15257,15267],[2955,2956,1335],"h1",{"id":2957},"health-checks-та-моніторинг-api",[2959,2960,2962],"h2",{"id":2961},"вступ-проблема-мертвого-api","Вступ: Проблема \"мертвого\" API",[2964,2965,2966],"p",{},"Уявіть, що ваш API розгорнуто у production:",[2968,2969,2974],"pre",{"className":2970,"code":2971,"language":2972,"meta":2973,"style":2973},"language-bash shiki shiki-themes light-plus dark-plus dark-plus","# Користувачі скаржаться на помилки\ncurl https://api.example.com/products\n→ 500 Internal Server Error\n\n# DevOps перевіряє сервер\nssh production-server\nps aux | grep dotnet\n→ dotnet процес працює ✓\n\n# Але API не відповідає!\n","bash","",[2975,2976,2977,2986,2997,3016,3023,3029,3038,3057,3074,3079],"code",{"__ignoreMap":2973},[2978,2979,2982],"span",{"class":2980,"line":2981},"line",1,[2978,2983,2985],{"class":2984},"spJ8K","# Користувачі скаржаться на помилки\n",[2978,2987,2989,2993],{"class":2980,"line":2988},2,[2978,2990,2992],{"class":2991},"s8Opu","curl",[2978,2994,2996],{"class":2995},"sbdoH"," https://api.example.com/products\n",[2978,2998,3000,3003,3007,3010,3013],{"class":2980,"line":2999},3,[2978,3001,3002],{"class":2991},"→",[2978,3004,3006],{"class":3005},"sJj4R"," 500",[2978,3008,3009],{"class":2995}," Internal",[2978,3011,3012],{"class":2995}," Server",[2978,3014,3015],{"class":2995}," Error\n",[2978,3017,3019],{"class":2980,"line":3018},4,[2978,3020,3022],{"emptyLinePlaceholder":3021},true,"\n",[2978,3024,3026],{"class":2980,"line":3025},5,[2978,3027,3028],{"class":2984},"# DevOps перевіряє сервер\n",[2978,3030,3032,3035],{"class":2980,"line":3031},6,[2978,3033,3034],{"class":2991},"ssh",[2978,3036,3037],{"class":2995}," production-server\n",[2978,3039,3041,3044,3047,3051,3054],{"class":2980,"line":3040},7,[2978,3042,3043],{"class":2991},"ps",[2978,3045,3046],{"class":2995}," aux",[2978,3048,3050],{"class":3049},"sHH4Y"," | ",[2978,3052,3053],{"class":2991},"grep",[2978,3055,3056],{"class":2995}," dotnet\n",[2978,3058,3060,3062,3065,3068,3071],{"class":2980,"line":3059},8,[2978,3061,3002],{"class":2991},[2978,3063,3064],{"class":2995}," dotnet",[2978,3066,3067],{"class":2995}," процес",[2978,3069,3070],{"class":2995}," працює",[2978,3072,3073],{"class":2995}," ✓\n",[2978,3075,3077],{"class":2980,"line":3076},9,[2978,3078,3022],{"emptyLinePlaceholder":3021},[2978,3080,3082],{"class":2980,"line":3081},10,[2978,3083,3084],{"class":2984},"# Але API не відповідає!\n",[2964,3086,3087],{},[3088,3089,3090],"strong",{},"Що сталося?",[3092,3093,3094,3098,3101,3104,3107],"ul",{},[3095,3096,3097],"li",{},"✅ Процес працює",[3095,3099,3100],{},"❌ База даних недоступна",[3095,3102,3103],{},"❌ Redis не відповідає",[3095,3105,3106],{},"❌ Диск заповнений на 100%",[3095,3108,3109],{},"❌ Пам'ять закінчилася",[2964,3111,3112,3115,3116,3119],{},[3088,3113,3114],{},"Проблема:"," Процес \"живий\", але API ",[3088,3117,3118],{},"не функціональний",".",[2964,3121,3122],{},[3088,3123,3124],{},"Типовий підхід — ручна перевірка:",[2968,3126,3128],{"className":2970,"code":3127,"language":2972,"meta":2973,"style":2973},"# DevOps вручну перевіряє кожен компонент\ncurl https://api.example.com/health\n→ 200 OK (але це нічого не каже про залежності!)\n\n# Перевірка БД\npsql -h db-server -U user -c \"SELECT 1\"\n→ Connection refused ❌\n\n# Перевірка Redis\nredis-cli -h redis-server ping\n→ PONG ✓\n\n# Перевірка диску\ndf -h\n→ /dev/sda1  100%  ❌\n",[2975,3129,3130,3135,3142,3176,3180,3185,3209,3222,3226,3231,3244,3254,3259,3265,3274],{"__ignoreMap":2973},[2978,3131,3132],{"class":2980,"line":2981},[2978,3133,3134],{"class":2984},"# DevOps вручну перевіряє кожен компонент\n",[2978,3136,3137,3139],{"class":2980,"line":2988},[2978,3138,2992],{"class":2991},[2978,3140,3141],{"class":2995}," https://api.example.com/health\n",[2978,3143,3144,3146,3149,3152,3155,3158,3161,3164,3167,3170,3173],{"class":2980,"line":2999},[2978,3145,3002],{"class":2991},[2978,3147,3148],{"class":3005}," 200",[2978,3150,3151],{"class":2995}," OK",[2978,3153,3154],{"class":3049}," (але ",[2978,3156,3157],{"class":2995},"це",[2978,3159,3160],{"class":2995}," нічого",[2978,3162,3163],{"class":2995}," не",[2978,3165,3166],{"class":2995}," каже",[2978,3168,3169],{"class":2995}," про",[2978,3171,3172],{"class":2995}," залежності!",[2978,3174,3175],{"class":3049},")\n",[2978,3177,3178],{"class":2980,"line":3018},[2978,3179,3022],{"emptyLinePlaceholder":3021},[2978,3181,3182],{"class":2980,"line":3025},[2978,3183,3184],{"class":2984},"# Перевірка БД\n",[2978,3186,3187,3190,3194,3197,3200,3203,3206],{"class":2980,"line":3031},[2978,3188,3189],{"class":2991},"psql",[2978,3191,3193],{"class":3192},"su1O8"," -h",[2978,3195,3196],{"class":2995}," db-server",[2978,3198,3199],{"class":3192}," -U",[2978,3201,3202],{"class":2995}," user",[2978,3204,3205],{"class":3192}," -c",[2978,3207,3208],{"class":2995}," \"SELECT 1\"\n",[2978,3210,3211,3213,3216,3219],{"class":2980,"line":3040},[2978,3212,3002],{"class":2991},[2978,3214,3215],{"class":2995}," Connection",[2978,3217,3218],{"class":2995}," refused",[2978,3220,3221],{"class":2995}," ❌\n",[2978,3223,3224],{"class":2980,"line":3059},[2978,3225,3022],{"emptyLinePlaceholder":3021},[2978,3227,3228],{"class":2980,"line":3076},[2978,3229,3230],{"class":2984},"# Перевірка Redis\n",[2978,3232,3233,3236,3238,3241],{"class":2980,"line":3081},[2978,3234,3235],{"class":2991},"redis-cli",[2978,3237,3193],{"class":3192},[2978,3239,3240],{"class":2995}," redis-server",[2978,3242,3243],{"class":2995}," ping\n",[2978,3245,3247,3249,3252],{"class":2980,"line":3246},11,[2978,3248,3002],{"class":2991},[2978,3250,3251],{"class":2995}," PONG",[2978,3253,3073],{"class":2995},[2978,3255,3257],{"class":2980,"line":3256},12,[2978,3258,3022],{"emptyLinePlaceholder":3021},[2978,3260,3262],{"class":2980,"line":3261},13,[2978,3263,3264],{"class":2984},"# Перевірка диску\n",[2978,3266,3268,3271],{"class":2980,"line":3267},14,[2978,3269,3270],{"class":2991},"df",[2978,3272,3273],{"class":3192}," -h\n",[2978,3275,3277,3279,3282,3285],{"class":2980,"line":3276},15,[2978,3278,3002],{"class":2991},[2978,3280,3281],{"class":2995}," /dev/sda1",[2978,3283,3284],{"class":2995},"  100%",[2978,3286,3287],{"class":2995},"  ❌\n",[2964,3289,3290],{},[3088,3291,3292],{},"Проблеми:",[3092,3294,3295,3301,3307,3313],{},[3095,3296,3297,3298],{},"❌ Ручна перевірка займає ",[3088,3299,3300],{},"багато часу",[3095,3302,3303,3304],{},"❌ Немає ",[3088,3305,3306],{},"автоматичного моніторингу",[3095,3308,3309,3310],{},"❌ Kubernetes не знає, що API ",[3088,3311,3312],{},"не готовий",[3095,3314,3315,3316,3319],{},"❌ Load balancer продовжує ",[3088,3317,3318],{},"відправляти трафік"," на \"мертвий\" instance",[2964,3321,3322],{},[3088,3323,3324],{},"Реальний сценарій:",[2968,3326,3331],{"className":3327,"code":3329,"language":3330},[3328],"language-text","09:00 - База даних перезапускається (планове обслуговування)\n09:01 - API не може підключитися до БД\n09:01 - Kubernetes думає, що API \"живий\" (процес працює)\n09:01 - Load balancer відправляє 50% трафіку на цей instance\n09:01 - Користувачі отримують 500 помилки\n09:15 - DevOps помічає проблему через алерти\n09:20 - Вручну перезапускають API\n09:25 - API знову працює\n\n❌ 24 хвилини downtime через відсутність health checks!\n","text",[2975,3332,3329],{"__ignoreMap":2973},[2964,3334,3335,3338,3339,3342],{},[3088,3336,3337],{},"Рішення"," — ",[3088,3340,3341],{},"Health Checks"," — автоматична перевірка стану API та його залежностей з можливістю інтеграції з Kubernetes, load balancers та моніторинговими системами.",[3344,3345,3346,3349],"note",{},[3088,3347,3348],{},"Передумови:"," Ця стаття базується на знаннях з попередніх статей Web API Controllers (01-10).",[3351,3352,3354],"h3",{"id":3353},"що-ви-створите-в-цій-статті","Що ви створите в цій статті",[2964,3356,3357,3358,3361,3362,3365],{},"Ми побудуємо ",[3088,3359,3360],{},"E-commerce API"," з ",[3088,3363,3364],{},"комплексною системою health checks",":",[2964,3367,3368],{},[3088,3369,3370],{},"1. Базові health checks:",[2968,3372,3376],{"className":3373,"code":3374,"language":3375,"meta":2973,"style":2973},"language-http shiki shiki-themes light-plus dark-plus dark-plus","GET /health\n→ 200 OK { \"status\": \"Healthy\" }\n\nGET /health/ready\n→ 503 Service Unavailable { \"status\": \"Unhealthy\", \"database\": \"Disconnected\" }\n","http",[2975,3377,3378,3383,3388,3392,3397],{"__ignoreMap":2973},[2978,3379,3380],{"class":2980,"line":2981},[2978,3381,3382],{},"GET /health\n",[2978,3384,3385],{"class":2980,"line":2988},[2978,3386,3387],{},"→ 200 OK { \"status\": \"Healthy\" }\n",[2978,3389,3390],{"class":2980,"line":2999},[2978,3391,3022],{"emptyLinePlaceholder":3021},[2978,3393,3394],{"class":2980,"line":3018},[2978,3395,3396],{},"GET /health/ready\n",[2978,3398,3399],{"class":2980,"line":3025},[2978,3400,3401],{},"→ 503 Service Unavailable { \"status\": \"Unhealthy\", \"database\": \"Disconnected\" }\n",[2964,3403,3404],{},[3088,3405,3406],{},"2. Вбудовані чеки:",[2968,3408,3412],{"className":3409,"code":3410,"language":3411,"meta":2973,"style":2973},"language-csharp shiki shiki-themes light-plus dark-plus dark-plus","builder.Services.AddHealthChecks()\n    .AddSqlServer(connectionString)\n    .AddRedis(redisConnection)\n    .AddRabbitMQ(rabbitConnection);\n","csharp",[2975,3413,3414,3433,3449,3463],{"__ignoreMap":2973},[2978,3415,3416,3420,3422,3425,3427,3430],{"class":2980,"line":2981},[2978,3417,3419],{"class":3418},"siwwj","builder",[2978,3421,3119],{"class":3049},[2978,3423,3424],{"class":3418},"Services",[2978,3426,3119],{"class":3049},[2978,3428,3429],{"class":2991},"AddHealthChecks",[2978,3431,3432],{"class":3049},"()\n",[2978,3434,3435,3438,3441,3444,3447],{"class":2980,"line":2988},[2978,3436,3437],{"class":3049},"    .",[2978,3439,3440],{"class":2991},"AddSqlServer",[2978,3442,3443],{"class":3049},"(",[2978,3445,3446],{"class":3418},"connectionString",[2978,3448,3175],{"class":3049},[2978,3450,3451,3453,3456,3458,3461],{"class":2980,"line":2999},[2978,3452,3437],{"class":3049},[2978,3454,3455],{"class":2991},"AddRedis",[2978,3457,3443],{"class":3049},[2978,3459,3460],{"class":3418},"redisConnection",[2978,3462,3175],{"class":3049},[2978,3464,3465,3467,3470,3472,3475],{"class":2980,"line":3018},[2978,3466,3437],{"class":3049},[2978,3468,3469],{"class":2991},"AddRabbitMQ",[2978,3471,3443],{"class":3049},[2978,3473,3474],{"class":3418},"rabbitConnection",[2978,3476,3477],{"class":3049},");\n",[2964,3479,3480],{},[3088,3481,3482],{},"3. Кастомні чеки:",[2968,3484,3486],{"className":3409,"code":3485,"language":3411,"meta":2973,"style":2973},"public class DiskSpaceHealthCheck : IHealthCheck\n{\n    public Task\u003CHealthCheckResult> CheckHealthAsync(HealthCheckContext context)\n    {\n        var freeSpace = GetFreeSpace();\n        return freeSpace > 1_000_000_000 // 1 GB\n            ? HealthCheckResult.Healthy()\n            : HealthCheckResult.Unhealthy(\"Low disk space\");\n    }\n}\n",[2975,3487,3488,3506,3511,3541,3546,3563,3580,3594,3613,3618],{"__ignoreMap":2973},[2978,3489,3490,3493,3496,3500,3503],{"class":2980,"line":2981},[2978,3491,3492],{"class":3192},"public",[2978,3494,3495],{"class":3192}," class",[2978,3497,3499],{"class":3498},"sN1BT"," DiskSpaceHealthCheck",[2978,3501,3502],{"class":3049}," : ",[2978,3504,3505],{"class":3498},"IHealthCheck\n",[2978,3507,3508],{"class":2980,"line":2988},[2978,3509,3510],{"class":3049},"{\n",[2978,3512,3513,3516,3519,3522,3525,3528,3531,3533,3536,3539],{"class":2980,"line":2999},[2978,3514,3515],{"class":3192},"    public",[2978,3517,3518],{"class":3498}," Task",[2978,3520,3521],{"class":3049},"\u003C",[2978,3523,3524],{"class":3498},"HealthCheckResult",[2978,3526,3527],{"class":3049},"> ",[2978,3529,3530],{"class":2991},"CheckHealthAsync",[2978,3532,3443],{"class":3049},[2978,3534,3535],{"class":3498},"HealthCheckContext",[2978,3537,3538],{"class":3418}," context",[2978,3540,3175],{"class":3049},[2978,3542,3543],{"class":2980,"line":3018},[2978,3544,3545],{"class":3049},"    {\n",[2978,3547,3548,3551,3554,3557,3560],{"class":2980,"line":3025},[2978,3549,3550],{"class":3192},"        var",[2978,3552,3553],{"class":3418}," freeSpace",[2978,3555,3556],{"class":3049}," = ",[2978,3558,3559],{"class":2991},"GetFreeSpace",[2978,3561,3562],{"class":3049},"();\n",[2978,3564,3565,3569,3571,3574,3577],{"class":2980,"line":3031},[2978,3566,3568],{"class":3567},"sCDza","        return",[2978,3570,3553],{"class":3418},[2978,3572,3573],{"class":3049}," > ",[2978,3575,3576],{"class":3005},"1_000_000_000",[2978,3578,3579],{"class":2984}," // 1 GB\n",[2978,3581,3582,3585,3587,3589,3592],{"class":2980,"line":3040},[2978,3583,3584],{"class":3049},"            ? ",[2978,3586,3524],{"class":3418},[2978,3588,3119],{"class":3049},[2978,3590,3591],{"class":2991},"Healthy",[2978,3593,3432],{"class":3049},[2978,3595,3596,3599,3601,3603,3606,3608,3611],{"class":2980,"line":3059},[2978,3597,3598],{"class":3049},"            : ",[2978,3600,3524],{"class":3418},[2978,3602,3119],{"class":3049},[2978,3604,3605],{"class":2991},"Unhealthy",[2978,3607,3443],{"class":3049},[2978,3609,3610],{"class":2995},"\"Low disk space\"",[2978,3612,3477],{"class":3049},[2978,3614,3615],{"class":2980,"line":3076},[2978,3616,3617],{"class":3049},"    }\n",[2978,3619,3620],{"class":2980,"line":3081},[2978,3621,3622],{"class":3049},"}\n",[2964,3624,3625],{},[3088,3626,3627],{},"4. Health Check UI:",[2968,3629,3632],{"className":3630,"code":3631,"language":3330},[3328],"https://api.example.com/health-ui\n→ Інтерактивний dashboard з історією перевірок\n",[2975,3633,3631],{"__ignoreMap":2973},[2964,3635,3636],{},[3088,3637,3638],{},"5. Kubernetes probes:",[2968,3640,3644],{"className":3641,"code":3642,"language":3643,"meta":2973,"style":2973},"language-yaml shiki shiki-themes light-plus dark-plus dark-plus","livenessProbe:\n  httpGet:\n    path: /health/live\n    port: 80\nreadinessProbe:\n  httpGet:\n    path: /health/ready\n    port: 80\n","yaml",[2975,3645,3646,3655,3662,3674,3684,3691,3697,3706],{"__ignoreMap":2973},[2978,3647,3648,3652],{"class":2980,"line":2981},[2978,3649,3651],{"class":3650},"sKtos","livenessProbe",[2978,3653,3654],{"class":3049},":\n",[2978,3656,3657,3660],{"class":2980,"line":2988},[2978,3658,3659],{"class":3650},"  httpGet",[2978,3661,3654],{"class":3049},[2978,3663,3664,3667,3670],{"class":2980,"line":2999},[2978,3665,3666],{"class":3650},"    path",[2978,3668,3669],{"class":3049},": ",[2978,3671,3673],{"class":3672},"su9tN","/health/live\n",[2978,3675,3676,3679,3681],{"class":2980,"line":3018},[2978,3677,3678],{"class":3650},"    port",[2978,3680,3669],{"class":3049},[2978,3682,3683],{"class":3005},"80\n",[2978,3685,3686,3689],{"class":2980,"line":3025},[2978,3687,3688],{"class":3650},"readinessProbe",[2978,3690,3654],{"class":3049},[2978,3692,3693,3695],{"class":2980,"line":3031},[2978,3694,3659],{"class":3650},[2978,3696,3654],{"class":3049},[2978,3698,3699,3701,3703],{"class":2980,"line":3040},[2978,3700,3666],{"class":3650},[2978,3702,3669],{"class":3049},[2978,3704,3705],{"class":3672},"/health/ready\n",[2978,3707,3708,3710,3712],{"class":2980,"line":3059},[2978,3709,3678],{"class":3650},[2978,3711,3669],{"class":3049},[2978,3713,3683],{"class":3005},[2964,3715,3716],{},"До кінця статті ви зможете:",[3092,3718,3719,3722,3725,3728,3731],{},[3095,3720,3721],{},"Створювати базові та кастомні health checks",[3095,3723,3724],{},"Використовувати вбудовані чеки для БД, Redis, RabbitMQ",[3095,3726,3727],{},"Налаштовувати Health Check UI",[3095,3729,3730],{},"Інтегрувати з Kubernetes probes",[3095,3732,3733],{},"Моніторити стан API у реальному часі",[3735,3736],"hr",{},[2959,3738,3740],{"id":3739},"фундаментальні-концепції","Фундаментальні концепції",[3351,3742,3744],{"id":3743},"liveness-vs-readiness-vs-startup","Liveness vs Readiness vs Startup",[2964,3746,3747],{},[3088,3748,3749],{},"Три типи health checks:",[3751,3752,3753],"mermaid",{},[2968,3754,3757],{"className":3755,"code":3756,"language":3751,"meta":2973,"style":2973},"language-mermaid shiki shiki-themes light-plus dark-plus dark-plus","graph TD\n    A[Container Start] --> B[Startup Probe]\n    B -->|Success| C[Liveness Probe]\n    B -->|Failure| D[Restart Container]\n    C -->|Success| E[Readiness Probe]\n    C -->|Failure| D\n    E -->|Success| F[Receive Traffic]\n    E -->|Failure| G[Remove from Load Balancer]\n    \n    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n    style B fill:#f59e0b,stroke:#b45309,color:#ffffff\n    style C fill:#10b981,stroke:#059669,color:#ffffff\n    style E fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n    style F fill:#10b981,stroke:#059669,color:#ffffff\n    style D fill:#ef4444,stroke:#b91c1c,color:#ffffff\n    style G fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[2975,3758,3759,3764,3769,3774,3779,3784,3789,3794,3799,3804,3809,3814,3819,3824,3829,3834],{"__ignoreMap":2973},[2978,3760,3761],{"class":2980,"line":2981},[2978,3762,3763],{},"graph TD\n",[2978,3765,3766],{"class":2980,"line":2988},[2978,3767,3768],{},"    A[Container Start] --> B[Startup Probe]\n",[2978,3770,3771],{"class":2980,"line":2999},[2978,3772,3773],{},"    B -->|Success| C[Liveness Probe]\n",[2978,3775,3776],{"class":2980,"line":3018},[2978,3777,3778],{},"    B -->|Failure| D[Restart Container]\n",[2978,3780,3781],{"class":2980,"line":3025},[2978,3782,3783],{},"    C -->|Success| E[Readiness Probe]\n",[2978,3785,3786],{"class":2980,"line":3031},[2978,3787,3788],{},"    C -->|Failure| D\n",[2978,3790,3791],{"class":2980,"line":3040},[2978,3792,3793],{},"    E -->|Success| F[Receive Traffic]\n",[2978,3795,3796],{"class":2980,"line":3059},[2978,3797,3798],{},"    E -->|Failure| G[Remove from Load Balancer]\n",[2978,3800,3801],{"class":2980,"line":3076},[2978,3802,3803],{},"    \n",[2978,3805,3806],{"class":2980,"line":3081},[2978,3807,3808],{},"    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n",[2978,3810,3811],{"class":2980,"line":3246},[2978,3812,3813],{},"    style B fill:#f59e0b,stroke:#b45309,color:#ffffff\n",[2978,3815,3816],{"class":2980,"line":3256},[2978,3817,3818],{},"    style C fill:#10b981,stroke:#059669,color:#ffffff\n",[2978,3820,3821],{"class":2980,"line":3261},[2978,3822,3823],{},"    style E fill:#8b5cf6,stroke:#6d28d9,color:#ffffff\n",[2978,3825,3826],{"class":2980,"line":3267},[2978,3827,3828],{},"    style F fill:#10b981,stroke:#059669,color:#ffffff\n",[2978,3830,3831],{"class":2980,"line":3276},[2978,3832,3833],{},"    style D fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[2978,3835,3837],{"class":2980,"line":3836},16,[2978,3838,3839],{},"    style G fill:#ef4444,stroke:#b91c1c,color:#ffffff\n",[3841,3842,3843,3862],"table",{},[3844,3845,3846],"thead",{},[3847,3848,3849,3853,3856,3859],"tr",{},[3850,3851,3852],"th",{},"Тип",[3850,3854,3855],{},"Призначення",[3850,3857,3858],{},"Коли використовувати",[3850,3860,3861],{},"Приклад",[3863,3864,3865,3882,3898],"tbody",{},[3847,3866,3867,3873,3876,3879],{},[3868,3869,3870],"td",{},[3088,3871,3872],{},"Startup",[3868,3874,3875],{},"Чи завершився запуск?",[3868,3877,3878],{},"Повільний старт (завантаження даних)",[3868,3880,3881],{},"Міграції БД, warming up cache",[3847,3883,3884,3889,3892,3895],{},[3868,3885,3886],{},[3088,3887,3888],{},"Liveness",[3868,3890,3891],{},"Чи живий процес?",[3868,3893,3894],{},"Deadlock, infinite loop",[3868,3896,3897],{},"Процес працює, але не відповідає",[3847,3899,3900,3905,3908,3911],{},[3868,3901,3902],{},[3088,3903,3904],{},"Readiness",[3868,3906,3907],{},"Чи готовий приймати трафік?",[3868,3909,3910],{},"Залежності недоступні",[3868,3912,3913],{},"БД offline, Redis недоступний",[2964,3915,3916],{},[3088,3917,3918],{},"Приклад:",[2968,3920,3923],{"className":3921,"code":3922,"language":3330},[3328],"Startup:  ✓ Міграції БД завершені\nLiveness: ✓ Процес відповідає на запити\nReadiness: ✗ Redis недоступний → Не приймати трафік\n",[2975,3924,3922],{"__ignoreMap":2973},[3351,3926,3928],{"id":3927},"healthstatus-enum","HealthStatus Enum",[2968,3930,3932],{"className":3409,"code":3931,"language":3411,"meta":2973,"style":2973},"public enum HealthStatus\n{\n    Unhealthy = 0,  // Критична помилка\n    Degraded = 1,   // Працює, але з проблемами\n    Healthy = 2     // Все OK\n}\n",[2975,3933,3934,3944,3948,3964,3980,3993],{"__ignoreMap":2973},[2978,3935,3936,3938,3941],{"class":2980,"line":2981},[2978,3937,3492],{"class":3192},[2978,3939,3940],{"class":3192}," enum",[2978,3942,3943],{"class":3498}," HealthStatus\n",[2978,3945,3946],{"class":2980,"line":2988},[2978,3947,3510],{"class":3049},[2978,3949,3950,3953,3955,3958,3961],{"class":2980,"line":2999},[2978,3951,3952],{"class":3418},"    Unhealthy",[2978,3954,3556],{"class":3049},[2978,3956,3957],{"class":3005},"0",[2978,3959,3960],{"class":3049},",  ",[2978,3962,3963],{"class":2984},"// Критична помилка\n",[2978,3965,3966,3969,3971,3974,3977],{"class":2980,"line":3018},[2978,3967,3968],{"class":3418},"    Degraded",[2978,3970,3556],{"class":3049},[2978,3972,3973],{"class":3005},"1",[2978,3975,3976],{"class":3049},",   ",[2978,3978,3979],{"class":2984},"// Працює, але з проблемами\n",[2978,3981,3982,3985,3987,3990],{"class":2980,"line":3025},[2978,3983,3984],{"class":3418},"    Healthy",[2978,3986,3556],{"class":3049},[2978,3988,3989],{"class":3005},"2",[2978,3991,3992],{"class":2984},"     // Все OK\n",[2978,3994,3995],{"class":2980,"line":3031},[2978,3996,3622],{"class":3049},[2964,3998,3999],{},[3088,4000,4001],{},"Приклад використання:",[2968,4003,4005],{"className":3409,"code":4004,"language":3411,"meta":2973,"style":2973},"// Healthy - все працює\nreturn HealthCheckResult.Healthy(\"Database connected\");\n\n// Degraded - працює повільно\nreturn HealthCheckResult.Degraded(\"Database response time > 1s\");\n\n// Unhealthy - не працює\nreturn HealthCheckResult.Unhealthy(\"Database connection failed\");\n",[2975,4006,4007,4012,4031,4035,4040,4058,4062,4067],{"__ignoreMap":2973},[2978,4008,4009],{"class":2980,"line":2981},[2978,4010,4011],{"class":2984},"// Healthy - все працює\n",[2978,4013,4014,4017,4020,4022,4024,4026,4029],{"class":2980,"line":2988},[2978,4015,4016],{"class":3567},"return",[2978,4018,4019],{"class":3418}," HealthCheckResult",[2978,4021,3119],{"class":3049},[2978,4023,3591],{"class":2991},[2978,4025,3443],{"class":3049},[2978,4027,4028],{"class":2995},"\"Database connected\"",[2978,4030,3477],{"class":3049},[2978,4032,4033],{"class":2980,"line":2999},[2978,4034,3022],{"emptyLinePlaceholder":3021},[2978,4036,4037],{"class":2980,"line":3018},[2978,4038,4039],{"class":2984},"// Degraded - працює повільно\n",[2978,4041,4042,4044,4046,4048,4051,4053,4056],{"class":2980,"line":3025},[2978,4043,4016],{"class":3567},[2978,4045,4019],{"class":3418},[2978,4047,3119],{"class":3049},[2978,4049,4050],{"class":2991},"Degraded",[2978,4052,3443],{"class":3049},[2978,4054,4055],{"class":2995},"\"Database response time > 1s\"",[2978,4057,3477],{"class":3049},[2978,4059,4060],{"class":2980,"line":3031},[2978,4061,3022],{"emptyLinePlaceholder":3021},[2978,4063,4064],{"class":2980,"line":3040},[2978,4065,4066],{"class":2984},"// Unhealthy - не працює\n",[2978,4068,4069,4071,4073,4075,4077,4079,4082],{"class":2980,"line":3059},[2978,4070,4016],{"class":3567},[2978,4072,4019],{"class":3418},[2978,4074,3119],{"class":3049},[2978,4076,3605],{"class":2991},[2978,4078,3443],{"class":3049},[2978,4080,4081],{"class":2995},"\"Database connection failed\"",[2978,4083,3477],{"class":3049},[3351,4085,4087],{"id":4086},"health-check-tags","Health Check Tags",[2964,4089,4090],{},"Групування health checks за категоріями:",[2968,4092,4094],{"className":3409,"code":4093,"language":3411,"meta":2973,"style":2973},"builder.Services.AddHealthChecks()\n    .AddSqlServer(connectionString, tags: new[] { \"database\", \"ready\" })\n    .AddRedis(redisConnection, tags: new[] { \"cache\", \"ready\" })\n    .AddCheck\u003CMemoryHealthCheck>(\"memory\", tags: new[] { \"resources\", \"live\" });\n",[2975,4095,4096,4110,4145,4174],{"__ignoreMap":2973},[2978,4097,4098,4100,4102,4104,4106,4108],{"class":2980,"line":2981},[2978,4099,3419],{"class":3418},[2978,4101,3119],{"class":3049},[2978,4103,3424],{"class":3418},[2978,4105,3119],{"class":3049},[2978,4107,3429],{"class":2991},[2978,4109,3432],{"class":3049},[2978,4111,4112,4114,4116,4118,4120,4123,4126,4128,4131,4134,4137,4139,4142],{"class":2980,"line":2988},[2978,4113,3437],{"class":3049},[2978,4115,3440],{"class":2991},[2978,4117,3443],{"class":3049},[2978,4119,3446],{"class":3418},[2978,4121,4122],{"class":3049},", ",[2978,4124,4125],{"class":3418},"tags",[2978,4127,3669],{"class":3049},[2978,4129,4130],{"class":3192},"new",[2978,4132,4133],{"class":3049},"[] { ",[2978,4135,4136],{"class":2995},"\"database\"",[2978,4138,4122],{"class":3049},[2978,4140,4141],{"class":2995},"\"ready\"",[2978,4143,4144],{"class":3049}," })\n",[2978,4146,4147,4149,4151,4153,4155,4157,4159,4161,4163,4165,4168,4170,4172],{"class":2980,"line":2999},[2978,4148,3437],{"class":3049},[2978,4150,3455],{"class":2991},[2978,4152,3443],{"class":3049},[2978,4154,3460],{"class":3418},[2978,4156,4122],{"class":3049},[2978,4158,4125],{"class":3418},[2978,4160,3669],{"class":3049},[2978,4162,4130],{"class":3192},[2978,4164,4133],{"class":3049},[2978,4166,4167],{"class":2995},"\"cache\"",[2978,4169,4122],{"class":3049},[2978,4171,4141],{"class":2995},[2978,4173,4144],{"class":3049},[2978,4175,4176,4178,4181,4183,4186,4189,4192,4194,4196,4198,4200,4202,4205,4207,4210],{"class":2980,"line":3018},[2978,4177,3437],{"class":3049},[2978,4179,4180],{"class":2991},"AddCheck",[2978,4182,3521],{"class":3049},[2978,4184,4185],{"class":3498},"MemoryHealthCheck",[2978,4187,4188],{"class":3049},">(",[2978,4190,4191],{"class":2995},"\"memory\"",[2978,4193,4122],{"class":3049},[2978,4195,4125],{"class":3418},[2978,4197,3669],{"class":3049},[2978,4199,4130],{"class":3192},[2978,4201,4133],{"class":3049},[2978,4203,4204],{"class":2995},"\"resources\"",[2978,4206,4122],{"class":3049},[2978,4208,4209],{"class":2995},"\"live\"",[2978,4211,4212],{"class":3049}," });\n",[2964,4214,4215],{},[3088,4216,4217],{},"Використання:",[2968,4219,4221],{"className":3409,"code":4220,"language":3411,"meta":2973,"style":2973},"// Тільки \"ready\" чеки для readiness probe\napp.MapHealthChecks(\"/health/ready\", new HealthCheckOptions\n{\n    Predicate = check => check.Tags.Contains(\"ready\")\n});\n\n// Тільки \"live\" чеки для liveness probe\napp.MapHealthChecks(\"/health/live\", new HealthCheckOptions\n{\n    Predicate = check => check.Tags.Contains(\"live\")\n});\n",[2975,4222,4223,4228,4250,4254,4285,4290,4294,4299,4318,4322,4348],{"__ignoreMap":2973},[2978,4224,4225],{"class":2980,"line":2981},[2978,4226,4227],{"class":2984},"// Тільки \"ready\" чеки для readiness probe\n",[2978,4229,4230,4233,4235,4238,4240,4243,4245,4247],{"class":2980,"line":2988},[2978,4231,4232],{"class":3418},"app",[2978,4234,3119],{"class":3049},[2978,4236,4237],{"class":2991},"MapHealthChecks",[2978,4239,3443],{"class":3049},[2978,4241,4242],{"class":2995},"\"/health/ready\"",[2978,4244,4122],{"class":3049},[2978,4246,4130],{"class":3192},[2978,4248,4249],{"class":3498}," HealthCheckOptions\n",[2978,4251,4252],{"class":2980,"line":2999},[2978,4253,3510],{"class":3049},[2978,4255,4256,4259,4261,4264,4267,4269,4271,4274,4276,4279,4281,4283],{"class":2980,"line":3018},[2978,4257,4258],{"class":3418},"    Predicate",[2978,4260,3556],{"class":3049},[2978,4262,4263],{"class":3418},"check",[2978,4265,4266],{"class":3049}," => ",[2978,4268,4263],{"class":3418},[2978,4270,3119],{"class":3049},[2978,4272,4273],{"class":3418},"Tags",[2978,4275,3119],{"class":3049},[2978,4277,4278],{"class":2991},"Contains",[2978,4280,3443],{"class":3049},[2978,4282,4141],{"class":2995},[2978,4284,3175],{"class":3049},[2978,4286,4287],{"class":2980,"line":3025},[2978,4288,4289],{"class":3049},"});\n",[2978,4291,4292],{"class":2980,"line":3031},[2978,4293,3022],{"emptyLinePlaceholder":3021},[2978,4295,4296],{"class":2980,"line":3040},[2978,4297,4298],{"class":2984},"// Тільки \"live\" чеки для liveness probe\n",[2978,4300,4301,4303,4305,4307,4309,4312,4314,4316],{"class":2980,"line":3059},[2978,4302,4232],{"class":3418},[2978,4304,3119],{"class":3049},[2978,4306,4237],{"class":2991},[2978,4308,3443],{"class":3049},[2978,4310,4311],{"class":2995},"\"/health/live\"",[2978,4313,4122],{"class":3049},[2978,4315,4130],{"class":3192},[2978,4317,4249],{"class":3498},[2978,4319,4320],{"class":2980,"line":3076},[2978,4321,3510],{"class":3049},[2978,4323,4324,4326,4328,4330,4332,4334,4336,4338,4340,4342,4344,4346],{"class":2980,"line":3081},[2978,4325,4258],{"class":3418},[2978,4327,3556],{"class":3049},[2978,4329,4263],{"class":3418},[2978,4331,4266],{"class":3049},[2978,4333,4263],{"class":3418},[2978,4335,3119],{"class":3049},[2978,4337,4273],{"class":3418},[2978,4339,3119],{"class":3049},[2978,4341,4278],{"class":2991},[2978,4343,3443],{"class":3049},[2978,4345,4209],{"class":2995},[2978,4347,3175],{"class":3049},[2978,4349,4350],{"class":2980,"line":3246},[2978,4351,4289],{"class":3049},[3735,4353],{},[2959,4355,4357],{"id":4356},"практична-реалізація-e-commerce-api-з-health-checks","Практична реалізація: E-commerce API з Health Checks",[3351,4359,4361],{"id":4360},"крок-1-налаштування-проєкту","Крок 1: Налаштування проєкту",[4363,4364,4365,4369,4491],"steps",{},[3351,4366,4368],{"id":4367},"створення-проєкту","Створення проєкту",[4370,4371,4372,4387,4395,4398,4408,4418,4427,4437,4443,4453,4459,4469,4475,4485],"terminal-preview",{"title":2972},[4373,4374,4376,4381,4382],"div",{"className":4375},[2980],[2978,4377,4380],{"className":4378},[4379],"opacity-40","$"," ",[3088,4383,4386],{"className":4384},[4385],"font-bold","dotnet new webapi -n EcommerceHealthChecksApi",[4373,4388,4390],{"className":4389},[2980],[2978,4391,4394],{"className":4392},[4393,4385],"text-green-400","The template \"ASP.NET Core Web API\" was created successfully.",[4373,4396],{"className":4397},[2980],[4373,4399,4401,4381,4404],{"className":4400},[2980],[2978,4402,4380],{"className":4403},[4379],[3088,4405,4407],{"className":4406},[4385],"cd EcommerceHealthChecksApi",[4373,4409,4411,4381,4414],{"className":4410},[2980],[2978,4412,4380],{"className":4413},[4379],[3088,4415,4417],{"className":4416},[4385],"dotnet add package AspNetCore.HealthChecks.SqlServer",[4373,4419,4421,4426],{"className":4420},[2980],[2978,4422,4425],{"className":4423},[4424],"text-blue-400","info"," : PackageReference added successfully",[4373,4428,4430,4381,4433],{"className":4429},[2980],[2978,4431,4380],{"className":4432},[4379],[3088,4434,4436],{"className":4435},[4385],"dotnet add package AspNetCore.HealthChecks.Redis",[4373,4438,4440,4426],{"className":4439},[2980],[2978,4441,4425],{"className":4442},[4424],[4373,4444,4446,4381,4449],{"className":4445},[2980],[2978,4447,4380],{"className":4448},[4379],[3088,4450,4452],{"className":4451},[4385],"dotnet add package AspNetCore.HealthChecks.UI",[4373,4454,4456,4426],{"className":4455},[2980],[2978,4457,4425],{"className":4458},[4424],[4373,4460,4462,4381,4465],{"className":4461},[2980],[2978,4463,4380],{"className":4464},[4379],[3088,4466,4468],{"className":4467},[4385],"dotnet add package AspNetCore.HealthChecks.UI.Client",[4373,4470,4472,4426],{"className":4471},[2980],[2978,4473,4425],{"className":4474},[4424],[4373,4476,4478,4381,4481],{"className":4477},[2980],[2978,4479,4380],{"className":4480},[4379],[3088,4482,4484],{"className":4483},[4385],"dotnet add package AspNetCore.HealthChecks.UI.InMemory.Storage",[4373,4486,4488,4426],{"className":4487},[2980],[2978,4489,4425],{"className":4490},[4424],[3344,4492,4493,4496],{},[3088,4494,4495],{},"AspNetCore.HealthChecks.","* — офіційна бібліотека з готовими health checks для популярних сервісів (SQL Server, Redis, RabbitMQ, MongoDB, Elasticsearch, тощо).",[3735,4498],{},[3351,4500,4502],{"id":4501},"крок-2-базові-health-checks","Крок 2: Базові Health Checks",[2964,4504,4505,4506,3365],{},"Створіть файл ",[2975,4507,4508],{},"Program.cs",[2968,4510,4512],{"className":3409,"code":4511,"language":3411,"meta":2973,"style":2973},"using Microsoft.AspNetCore.Diagnostics.HealthChecks;\nusing HealthChecks.UI.Client;\nusing Microsoft.Extensions.Diagnostics.HealthChecks;\n\nvar builder = WebApplication.CreateBuilder(args);\n\nbuilder.Services.AddControllers();\n\n// Базові health checks\nbuilder.Services.AddHealthChecks()\n    .AddCheck(\"self\", () => HealthCheckResult.Healthy(\"API is running\"), tags: new[] { \"live\" });\n\nvar app = builder.Build();\n\napp.UseHttpsRedirection();\napp.UseAuthorization();\napp.MapControllers();\n\n// Health check endpoints\napp.MapHealthChecks(\"/health\", new HealthCheckOptions\n{\n    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse\n});\n\napp.MapHealthChecks(\"/health/live\", new HealthCheckOptions\n{\n    Predicate = check => check.Tags.Contains(\"live\"),\n    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse\n});\n\napp.MapHealthChecks(\"/health/ready\", new HealthCheckOptions\n{\n    Predicate = check => check.Tags.Contains(\"ready\"),\n    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse\n});\n\napp.Run();\n",[2975,4513,4514,4540,4559,4580,4584,4609,4613,4628,4632,4637,4651,4691,4695,4713,4717,4728,4739,4751,4756,4762,4782,4787,4803,4808,4813,4832,4837,4865,4878,4883,4888,4907,4912,4939,4952,4957,4962],{"__ignoreMap":2973},[2978,4515,4516,4519,4522,4524,4527,4529,4532,4534,4537],{"class":2980,"line":2981},[2978,4517,4518],{"class":3567},"using",[2978,4520,4521],{"class":3498}," Microsoft",[2978,4523,3119],{"class":3049},[2978,4525,4526],{"class":3498},"AspNetCore",[2978,4528,3119],{"class":3049},[2978,4530,4531],{"class":3498},"Diagnostics",[2978,4533,3119],{"class":3049},[2978,4535,4536],{"class":3498},"HealthChecks",[2978,4538,4539],{"class":3049},";\n",[2978,4541,4542,4544,4547,4549,4552,4554,4557],{"class":2980,"line":2988},[2978,4543,4518],{"class":3567},[2978,4545,4546],{"class":3498}," HealthChecks",[2978,4548,3119],{"class":3049},[2978,4550,4551],{"class":3498},"UI",[2978,4553,3119],{"class":3049},[2978,4555,4556],{"class":3498},"Client",[2978,4558,4539],{"class":3049},[2978,4560,4561,4563,4565,4567,4570,4572,4574,4576,4578],{"class":2980,"line":2999},[2978,4562,4518],{"class":3567},[2978,4564,4521],{"class":3498},[2978,4566,3119],{"class":3049},[2978,4568,4569],{"class":3498},"Extensions",[2978,4571,3119],{"class":3049},[2978,4573,4531],{"class":3498},[2978,4575,3119],{"class":3049},[2978,4577,4536],{"class":3498},[2978,4579,4539],{"class":3049},[2978,4581,4582],{"class":2980,"line":3018},[2978,4583,3022],{"emptyLinePlaceholder":3021},[2978,4585,4586,4589,4592,4594,4597,4599,4602,4604,4607],{"class":2980,"line":3025},[2978,4587,4588],{"class":3192},"var",[2978,4590,4591],{"class":3418}," builder",[2978,4593,3556],{"class":3049},[2978,4595,4596],{"class":3418},"WebApplication",[2978,4598,3119],{"class":3049},[2978,4600,4601],{"class":2991},"CreateBuilder",[2978,4603,3443],{"class":3049},[2978,4605,4606],{"class":3418},"args",[2978,4608,3477],{"class":3049},[2978,4610,4611],{"class":2980,"line":3031},[2978,4612,3022],{"emptyLinePlaceholder":3021},[2978,4614,4615,4617,4619,4621,4623,4626],{"class":2980,"line":3040},[2978,4616,3419],{"class":3418},[2978,4618,3119],{"class":3049},[2978,4620,3424],{"class":3418},[2978,4622,3119],{"class":3049},[2978,4624,4625],{"class":2991},"AddControllers",[2978,4627,3562],{"class":3049},[2978,4629,4630],{"class":2980,"line":3059},[2978,4631,3022],{"emptyLinePlaceholder":3021},[2978,4633,4634],{"class":2980,"line":3076},[2978,4635,4636],{"class":2984},"// Базові health checks\n",[2978,4638,4639,4641,4643,4645,4647,4649],{"class":2980,"line":3081},[2978,4640,3419],{"class":3418},[2978,4642,3119],{"class":3049},[2978,4644,3424],{"class":3418},[2978,4646,3119],{"class":3049},[2978,4648,3429],{"class":2991},[2978,4650,3432],{"class":3049},[2978,4652,4653,4655,4657,4659,4662,4665,4667,4669,4671,4673,4676,4679,4681,4683,4685,4687,4689],{"class":2980,"line":3246},[2978,4654,3437],{"class":3049},[2978,4656,4180],{"class":2991},[2978,4658,3443],{"class":3049},[2978,4660,4661],{"class":2995},"\"self\"",[2978,4663,4664],{"class":3049},", () => ",[2978,4666,3524],{"class":3418},[2978,4668,3119],{"class":3049},[2978,4670,3591],{"class":2991},[2978,4672,3443],{"class":3049},[2978,4674,4675],{"class":2995},"\"API is running\"",[2978,4677,4678],{"class":3049},"), ",[2978,4680,4125],{"class":3418},[2978,4682,3669],{"class":3049},[2978,4684,4130],{"class":3192},[2978,4686,4133],{"class":3049},[2978,4688,4209],{"class":2995},[2978,4690,4212],{"class":3049},[2978,4692,4693],{"class":2980,"line":3256},[2978,4694,3022],{"emptyLinePlaceholder":3021},[2978,4696,4697,4699,4702,4704,4706,4708,4711],{"class":2980,"line":3261},[2978,4698,4588],{"class":3192},[2978,4700,4701],{"class":3418}," app",[2978,4703,3556],{"class":3049},[2978,4705,3419],{"class":3418},[2978,4707,3119],{"class":3049},[2978,4709,4710],{"class":2991},"Build",[2978,4712,3562],{"class":3049},[2978,4714,4715],{"class":2980,"line":3267},[2978,4716,3022],{"emptyLinePlaceholder":3021},[2978,4718,4719,4721,4723,4726],{"class":2980,"line":3276},[2978,4720,4232],{"class":3418},[2978,4722,3119],{"class":3049},[2978,4724,4725],{"class":2991},"UseHttpsRedirection",[2978,4727,3562],{"class":3049},[2978,4729,4730,4732,4734,4737],{"class":2980,"line":3836},[2978,4731,4232],{"class":3418},[2978,4733,3119],{"class":3049},[2978,4735,4736],{"class":2991},"UseAuthorization",[2978,4738,3562],{"class":3049},[2978,4740,4742,4744,4746,4749],{"class":2980,"line":4741},17,[2978,4743,4232],{"class":3418},[2978,4745,3119],{"class":3049},[2978,4747,4748],{"class":2991},"MapControllers",[2978,4750,3562],{"class":3049},[2978,4752,4754],{"class":2980,"line":4753},18,[2978,4755,3022],{"emptyLinePlaceholder":3021},[2978,4757,4759],{"class":2980,"line":4758},19,[2978,4760,4761],{"class":2984},"// Health check endpoints\n",[2978,4763,4765,4767,4769,4771,4773,4776,4778,4780],{"class":2980,"line":4764},20,[2978,4766,4232],{"class":3418},[2978,4768,3119],{"class":3049},[2978,4770,4237],{"class":2991},[2978,4772,3443],{"class":3049},[2978,4774,4775],{"class":2995},"\"/health\"",[2978,4777,4122],{"class":3049},[2978,4779,4130],{"class":3192},[2978,4781,4249],{"class":3498},[2978,4783,4785],{"class":2980,"line":4784},21,[2978,4786,3510],{"class":3049},[2978,4788,4790,4793,4795,4798,4800],{"class":2980,"line":4789},22,[2978,4791,4792],{"class":3418},"    ResponseWriter",[2978,4794,3556],{"class":3049},[2978,4796,4797],{"class":3418},"UIResponseWriter",[2978,4799,3119],{"class":3049},[2978,4801,4802],{"class":3418},"WriteHealthCheckUIResponse\n",[2978,4804,4806],{"class":2980,"line":4805},23,[2978,4807,4289],{"class":3049},[2978,4809,4811],{"class":2980,"line":4810},24,[2978,4812,3022],{"emptyLinePlaceholder":3021},[2978,4814,4816,4818,4820,4822,4824,4826,4828,4830],{"class":2980,"line":4815},25,[2978,4817,4232],{"class":3418},[2978,4819,3119],{"class":3049},[2978,4821,4237],{"class":2991},[2978,4823,3443],{"class":3049},[2978,4825,4311],{"class":2995},[2978,4827,4122],{"class":3049},[2978,4829,4130],{"class":3192},[2978,4831,4249],{"class":3498},[2978,4833,4835],{"class":2980,"line":4834},26,[2978,4836,3510],{"class":3049},[2978,4838,4840,4842,4844,4846,4848,4850,4852,4854,4856,4858,4860,4862],{"class":2980,"line":4839},27,[2978,4841,4258],{"class":3418},[2978,4843,3556],{"class":3049},[2978,4845,4263],{"class":3418},[2978,4847,4266],{"class":3049},[2978,4849,4263],{"class":3418},[2978,4851,3119],{"class":3049},[2978,4853,4273],{"class":3418},[2978,4855,3119],{"class":3049},[2978,4857,4278],{"class":2991},[2978,4859,3443],{"class":3049},[2978,4861,4209],{"class":2995},[2978,4863,4864],{"class":3049},"),\n",[2978,4866,4868,4870,4872,4874,4876],{"class":2980,"line":4867},28,[2978,4869,4792],{"class":3418},[2978,4871,3556],{"class":3049},[2978,4873,4797],{"class":3418},[2978,4875,3119],{"class":3049},[2978,4877,4802],{"class":3418},[2978,4879,4881],{"class":2980,"line":4880},29,[2978,4882,4289],{"class":3049},[2978,4884,4886],{"class":2980,"line":4885},30,[2978,4887,3022],{"emptyLinePlaceholder":3021},[2978,4889,4891,4893,4895,4897,4899,4901,4903,4905],{"class":2980,"line":4890},31,[2978,4892,4232],{"class":3418},[2978,4894,3119],{"class":3049},[2978,4896,4237],{"class":2991},[2978,4898,3443],{"class":3049},[2978,4900,4242],{"class":2995},[2978,4902,4122],{"class":3049},[2978,4904,4130],{"class":3192},[2978,4906,4249],{"class":3498},[2978,4908,4910],{"class":2980,"line":4909},32,[2978,4911,3510],{"class":3049},[2978,4913,4915,4917,4919,4921,4923,4925,4927,4929,4931,4933,4935,4937],{"class":2980,"line":4914},33,[2978,4916,4258],{"class":3418},[2978,4918,3556],{"class":3049},[2978,4920,4263],{"class":3418},[2978,4922,4266],{"class":3049},[2978,4924,4263],{"class":3418},[2978,4926,3119],{"class":3049},[2978,4928,4273],{"class":3418},[2978,4930,3119],{"class":3049},[2978,4932,4278],{"class":2991},[2978,4934,3443],{"class":3049},[2978,4936,4141],{"class":2995},[2978,4938,4864],{"class":3049},[2978,4940,4942,4944,4946,4948,4950],{"class":2980,"line":4941},34,[2978,4943,4792],{"class":3418},[2978,4945,3556],{"class":3049},[2978,4947,4797],{"class":3418},[2978,4949,3119],{"class":3049},[2978,4951,4802],{"class":3418},[2978,4953,4955],{"class":2980,"line":4954},35,[2978,4956,4289],{"class":3049},[2978,4958,4960],{"class":2980,"line":4959},36,[2978,4961,3022],{"emptyLinePlaceholder":3021},[2978,4963,4965,4967,4969,4972],{"class":2980,"line":4964},37,[2978,4966,4232],{"class":3418},[2978,4968,3119],{"class":3049},[2978,4970,4971],{"class":2991},"Run",[2978,4973,3562],{"class":3049},[2964,4975,4976],{},[3088,4977,4978],{},"Декомпозиція:",[4980,4981,4982,4990,4998,5006,5013],"ol",{},[3095,4983,4984,4989],{},[3088,4985,4986],{},[2975,4987,4988],{},"AddHealthChecks()"," — реєструє health checks систему",[3095,4991,4992,4997],{},[3088,4993,4994],{},[2975,4995,4996],{},"AddCheck(\"self\")"," — простий чек \"API працює\"",[3095,4999,5000,5005],{},[3088,5001,5002],{},[2975,5003,5004],{},"MapHealthChecks(\"/health\")"," — endpoint для всіх чеків",[3095,5007,5008,5012],{},[3088,5009,5010],{},[2975,5011,4797],{}," — форматує відповідь у JSON (з бібліотеки UI.Client)",[3095,5014,5015,5020],{},[3088,5016,5017],{},[2975,5018,5019],{},"Predicate"," — фільтрує чеки за tags",[2964,5022,5023],{},[3088,5024,5025],{},"Тестування:",[2968,5027,5029],{"className":2970,"code":5028,"language":2972,"meta":2973,"style":2973},"curl https://localhost:5001/health\n",[2975,5030,5031],{"__ignoreMap":2973},[2978,5032,5033,5035],{"class":2980,"line":2981},[2978,5034,2992],{"class":2991},[2978,5036,5037],{"class":2995}," https://localhost:5001/health\n",[2968,5039,5043],{"className":5040,"code":5041,"language":5042,"meta":2973,"style":2973},"language-json shiki shiki-themes light-plus dark-plus dark-plus","{\n  \"status\": \"Healthy\",\n  \"totalDuration\": \"00:00:00.0012345\",\n  \"entries\": {\n    \"self\": {\n      \"status\": \"Healthy\",\n      \"description\": \"API is running\",\n      \"duration\": \"00:00:00.0001234\"\n    }\n  }\n}\n","json",[2975,5044,5045,5049,5063,5075,5083,5090,5101,5112,5122,5126,5131],{"__ignoreMap":2973},[2978,5046,5047],{"class":2980,"line":2981},[2978,5048,3510],{"class":3049},[2978,5050,5051,5055,5057,5060],{"class":2980,"line":2988},[2978,5052,5054],{"class":5053},"sLwNe","  \"status\"",[2978,5056,3669],{"class":3049},[2978,5058,5059],{"class":2995},"\"Healthy\"",[2978,5061,5062],{"class":3049},",\n",[2978,5064,5065,5068,5070,5073],{"class":2980,"line":2999},[2978,5066,5067],{"class":5053},"  \"totalDuration\"",[2978,5069,3669],{"class":3049},[2978,5071,5072],{"class":2995},"\"00:00:00.0012345\"",[2978,5074,5062],{"class":3049},[2978,5076,5077,5080],{"class":2980,"line":3018},[2978,5078,5079],{"class":5053},"  \"entries\"",[2978,5081,5082],{"class":3049},": {\n",[2978,5084,5085,5088],{"class":2980,"line":3025},[2978,5086,5087],{"class":5053},"    \"self\"",[2978,5089,5082],{"class":3049},[2978,5091,5092,5095,5097,5099],{"class":2980,"line":3031},[2978,5093,5094],{"class":5053},"      \"status\"",[2978,5096,3669],{"class":3049},[2978,5098,5059],{"class":2995},[2978,5100,5062],{"class":3049},[2978,5102,5103,5106,5108,5110],{"class":2980,"line":3040},[2978,5104,5105],{"class":5053},"      \"description\"",[2978,5107,3669],{"class":3049},[2978,5109,4675],{"class":2995},[2978,5111,5062],{"class":3049},[2978,5113,5114,5117,5119],{"class":2980,"line":3059},[2978,5115,5116],{"class":5053},"      \"duration\"",[2978,5118,3669],{"class":3049},[2978,5120,5121],{"class":2995},"\"00:00:00.0001234\"\n",[2978,5123,5124],{"class":2980,"line":3076},[2978,5125,3617],{"class":3049},[2978,5127,5128],{"class":2980,"line":3081},[2978,5129,5130],{"class":3049},"  }\n",[2978,5132,5133],{"class":2980,"line":3246},[2978,5134,3622],{"class":3049},[3735,5136],{},[3351,5138,5140],{"id":5139},"крок-3-вбудовані-health-checks","Крок 3: Вбудовані Health Checks",[5142,5143,5145],"h4",{"id":5144},"sql-server-health-check","SQL Server Health Check",[2968,5147,5149],{"className":3409,"code":5148,"language":3411,"meta":2973,"style":2973},"var connectionString = builder.Configuration.GetConnectionString(\"DefaultConnection\");\n\nbuilder.Services.AddHealthChecks()\n    .AddCheck(\"self\", () => HealthCheckResult.Healthy(), tags: new[] { \"live\" })\n    .AddSqlServer(\n        connectionString: connectionString!,\n        name: \"database\",\n        failureStatus: HealthStatus.Unhealthy,\n        tags: new[] { \"database\", \"ready\" },\n        timeout: TimeSpan.FromSeconds(5));\n",[2975,5150,5151,5179,5183,5197,5230,5239,5251,5262,5278,5298],{"__ignoreMap":2973},[2978,5152,5153,5155,5158,5160,5162,5164,5167,5169,5172,5174,5177],{"class":2980,"line":2981},[2978,5154,4588],{"class":3192},[2978,5156,5157],{"class":3418}," connectionString",[2978,5159,3556],{"class":3049},[2978,5161,3419],{"class":3418},[2978,5163,3119],{"class":3049},[2978,5165,5166],{"class":3418},"Configuration",[2978,5168,3119],{"class":3049},[2978,5170,5171],{"class":2991},"GetConnectionString",[2978,5173,3443],{"class":3049},[2978,5175,5176],{"class":2995},"\"DefaultConnection\"",[2978,5178,3477],{"class":3049},[2978,5180,5181],{"class":2980,"line":2988},[2978,5182,3022],{"emptyLinePlaceholder":3021},[2978,5184,5185,5187,5189,5191,5193,5195],{"class":2980,"line":2999},[2978,5186,3419],{"class":3418},[2978,5188,3119],{"class":3049},[2978,5190,3424],{"class":3418},[2978,5192,3119],{"class":3049},[2978,5194,3429],{"class":2991},[2978,5196,3432],{"class":3049},[2978,5198,5199,5201,5203,5205,5207,5209,5211,5213,5215,5218,5220,5222,5224,5226,5228],{"class":2980,"line":3018},[2978,5200,3437],{"class":3049},[2978,5202,4180],{"class":2991},[2978,5204,3443],{"class":3049},[2978,5206,4661],{"class":2995},[2978,5208,4664],{"class":3049},[2978,5210,3524],{"class":3418},[2978,5212,3119],{"class":3049},[2978,5214,3591],{"class":2991},[2978,5216,5217],{"class":3049},"(), ",[2978,5219,4125],{"class":3418},[2978,5221,3669],{"class":3049},[2978,5223,4130],{"class":3192},[2978,5225,4133],{"class":3049},[2978,5227,4209],{"class":2995},[2978,5229,4144],{"class":3049},[2978,5231,5232,5234,5236],{"class":2980,"line":3025},[2978,5233,3437],{"class":3049},[2978,5235,3440],{"class":2991},[2978,5237,5238],{"class":3049},"(\n",[2978,5240,5241,5244,5246,5248],{"class":2980,"line":3031},[2978,5242,5243],{"class":3418},"        connectionString",[2978,5245,3669],{"class":3049},[2978,5247,3446],{"class":3418},[2978,5249,5250],{"class":3049},"!,\n",[2978,5252,5253,5256,5258,5260],{"class":2980,"line":3040},[2978,5254,5255],{"class":3418},"        name",[2978,5257,3669],{"class":3049},[2978,5259,4136],{"class":2995},[2978,5261,5062],{"class":3049},[2978,5263,5264,5267,5269,5272,5274,5276],{"class":2980,"line":3059},[2978,5265,5266],{"class":3418},"        failureStatus",[2978,5268,3669],{"class":3049},[2978,5270,5271],{"class":3418},"HealthStatus",[2978,5273,3119],{"class":3049},[2978,5275,3605],{"class":3418},[2978,5277,5062],{"class":3049},[2978,5279,5280,5283,5285,5287,5289,5291,5293,5295],{"class":2980,"line":3076},[2978,5281,5282],{"class":3418},"        tags",[2978,5284,3669],{"class":3049},[2978,5286,4130],{"class":3192},[2978,5288,4133],{"class":3049},[2978,5290,4136],{"class":2995},[2978,5292,4122],{"class":3049},[2978,5294,4141],{"class":2995},[2978,5296,5297],{"class":3049}," },\n",[2978,5299,5300,5303,5305,5308,5310,5313,5315,5318],{"class":2980,"line":3081},[2978,5301,5302],{"class":3418},"        timeout",[2978,5304,3669],{"class":3049},[2978,5306,5307],{"class":3418},"TimeSpan",[2978,5309,3119],{"class":3049},[2978,5311,5312],{"class":2991},"FromSeconds",[2978,5314,3443],{"class":3049},[2978,5316,5317],{"class":3005},"5",[2978,5319,5320],{"class":3049},"));\n",[2964,5322,5323],{},[3088,5324,5325],{},"Що перевіряє:",[3092,5327,5328,5331,5338],{},[3095,5329,5330],{},"✓ Підключення до SQL Server",[3095,5332,5333,5334,5337],{},"✓ Виконання простого запиту (",[2975,5335,5336],{},"SELECT 1",")",[3095,5339,5340],{},"✓ Timeout (5 секунд)",[5142,5342,5344],{"id":5343},"redis-health-check","Redis Health Check",[2968,5346,5348],{"className":3409,"code":5347,"language":3411,"meta":2973,"style":2973},"var redisConnection = builder.Configuration.GetConnectionString(\"Redis\");\n\nbuilder.Services.AddHealthChecks()\n    // ... попередні чеки\n    .AddRedis(\n        redisConnectionString: redisConnection!,\n        name: \"redis\",\n        failureStatus: HealthStatus.Degraded, // Не критично\n        tags: new[] { \"cache\", \"ready\" },\n        timeout: TimeSpan.FromSeconds(3));\n",[2975,5349,5350,5376,5380,5394,5399,5407,5418,5429,5446,5464],{"__ignoreMap":2973},[2978,5351,5352,5354,5357,5359,5361,5363,5365,5367,5369,5371,5374],{"class":2980,"line":2981},[2978,5353,4588],{"class":3192},[2978,5355,5356],{"class":3418}," redisConnection",[2978,5358,3556],{"class":3049},[2978,5360,3419],{"class":3418},[2978,5362,3119],{"class":3049},[2978,5364,5166],{"class":3418},[2978,5366,3119],{"class":3049},[2978,5368,5171],{"class":2991},[2978,5370,3443],{"class":3049},[2978,5372,5373],{"class":2995},"\"Redis\"",[2978,5375,3477],{"class":3049},[2978,5377,5378],{"class":2980,"line":2988},[2978,5379,3022],{"emptyLinePlaceholder":3021},[2978,5381,5382,5384,5386,5388,5390,5392],{"class":2980,"line":2999},[2978,5383,3419],{"class":3418},[2978,5385,3119],{"class":3049},[2978,5387,3424],{"class":3418},[2978,5389,3119],{"class":3049},[2978,5391,3429],{"class":2991},[2978,5393,3432],{"class":3049},[2978,5395,5396],{"class":2980,"line":3018},[2978,5397,5398],{"class":2984},"    // ... попередні чеки\n",[2978,5400,5401,5403,5405],{"class":2980,"line":3025},[2978,5402,3437],{"class":3049},[2978,5404,3455],{"class":2991},[2978,5406,5238],{"class":3049},[2978,5408,5409,5412,5414,5416],{"class":2980,"line":3031},[2978,5410,5411],{"class":3418},"        redisConnectionString",[2978,5413,3669],{"class":3049},[2978,5415,3460],{"class":3418},[2978,5417,5250],{"class":3049},[2978,5419,5420,5422,5424,5427],{"class":2980,"line":3040},[2978,5421,5255],{"class":3418},[2978,5423,3669],{"class":3049},[2978,5425,5426],{"class":2995},"\"redis\"",[2978,5428,5062],{"class":3049},[2978,5430,5431,5433,5435,5437,5439,5441,5443],{"class":2980,"line":3059},[2978,5432,5266],{"class":3418},[2978,5434,3669],{"class":3049},[2978,5436,5271],{"class":3418},[2978,5438,3119],{"class":3049},[2978,5440,4050],{"class":3418},[2978,5442,4122],{"class":3049},[2978,5444,5445],{"class":2984},"// Не критично\n",[2978,5447,5448,5450,5452,5454,5456,5458,5460,5462],{"class":2980,"line":3076},[2978,5449,5282],{"class":3418},[2978,5451,3669],{"class":3049},[2978,5453,4130],{"class":3192},[2978,5455,4133],{"class":3049},[2978,5457,4167],{"class":2995},[2978,5459,4122],{"class":3049},[2978,5461,4141],{"class":2995},[2978,5463,5297],{"class":3049},[2978,5465,5466,5468,5470,5472,5474,5476,5478,5481],{"class":2980,"line":3081},[2978,5467,5302],{"class":3418},[2978,5469,3669],{"class":3049},[2978,5471,5307],{"class":3418},[2978,5473,3119],{"class":3049},[2978,5475,5312],{"class":2991},[2978,5477,3443],{"class":3049},[2978,5479,5480],{"class":3005},"3",[2978,5482,5320],{"class":3049},[2964,5484,5485],{},[3088,5486,5325],{},[3092,5488,5489,5492,5499],{},[3095,5490,5491],{},"✓ Підключення до Redis",[3095,5493,5494,5495,5498],{},"✓ Виконання ",[2975,5496,5497],{},"PING"," команди",[3095,5500,5501],{},"✓ Timeout (3 секунди)",[5503,5504,5505,5510,5511,5513,5514,3119],"tip",{},[3088,5506,5507],{},[2975,5508,5509],{},"failureStatus: HealthStatus.Degraded"," — якщо Redis недоступний, API все ще може працювати (без кешу), тому статус ",[2975,5512,4050],{}," замість ",[2975,5515,3605],{},[5142,5517,5519],{"id":5518},"url-health-check-зовнішні-api","URL Health Check (зовнішні API)",[2968,5521,5523],{"className":3409,"code":5522,"language":3411,"meta":2973,"style":2973},"builder.Services.AddHealthChecks()\n    // ... попередні чеки\n    .AddUrlGroup(\n        uri: new Uri(\"https://api.stripe.com/healthcheck\"),\n        name: \"stripe-api\",\n        failureStatus: HealthStatus.Degraded,\n        tags: new[] { \"external\", \"ready\" },\n        timeout: TimeSpan.FromSeconds(10));\n",[2975,5524,5525,5539,5543,5552,5571,5582,5596,5615],{"__ignoreMap":2973},[2978,5526,5527,5529,5531,5533,5535,5537],{"class":2980,"line":2981},[2978,5528,3419],{"class":3418},[2978,5530,3119],{"class":3049},[2978,5532,3424],{"class":3418},[2978,5534,3119],{"class":3049},[2978,5536,3429],{"class":2991},[2978,5538,3432],{"class":3049},[2978,5540,5541],{"class":2980,"line":2988},[2978,5542,5398],{"class":2984},[2978,5544,5545,5547,5550],{"class":2980,"line":2999},[2978,5546,3437],{"class":3049},[2978,5548,5549],{"class":2991},"AddUrlGroup",[2978,5551,5238],{"class":3049},[2978,5553,5554,5557,5559,5561,5564,5566,5569],{"class":2980,"line":3018},[2978,5555,5556],{"class":3418},"        uri",[2978,5558,3669],{"class":3049},[2978,5560,4130],{"class":3192},[2978,5562,5563],{"class":3498}," Uri",[2978,5565,3443],{"class":3049},[2978,5567,5568],{"class":2995},"\"https://api.stripe.com/healthcheck\"",[2978,5570,4864],{"class":3049},[2978,5572,5573,5575,5577,5580],{"class":2980,"line":3025},[2978,5574,5255],{"class":3418},[2978,5576,3669],{"class":3049},[2978,5578,5579],{"class":2995},"\"stripe-api\"",[2978,5581,5062],{"class":3049},[2978,5583,5584,5586,5588,5590,5592,5594],{"class":2980,"line":3031},[2978,5585,5266],{"class":3418},[2978,5587,3669],{"class":3049},[2978,5589,5271],{"class":3418},[2978,5591,3119],{"class":3049},[2978,5593,4050],{"class":3418},[2978,5595,5062],{"class":3049},[2978,5597,5598,5600,5602,5604,5606,5609,5611,5613],{"class":2980,"line":3040},[2978,5599,5282],{"class":3418},[2978,5601,3669],{"class":3049},[2978,5603,4130],{"class":3192},[2978,5605,4133],{"class":3049},[2978,5607,5608],{"class":2995},"\"external\"",[2978,5610,4122],{"class":3049},[2978,5612,4141],{"class":2995},[2978,5614,5297],{"class":3049},[2978,5616,5617,5619,5621,5623,5625,5627,5629,5632],{"class":2980,"line":3059},[2978,5618,5302],{"class":3418},[2978,5620,3669],{"class":3049},[2978,5622,5307],{"class":3418},[2978,5624,3119],{"class":3049},[2978,5626,5312],{"class":2991},[2978,5628,3443],{"class":3049},[2978,5630,5631],{"class":3005},"10",[2978,5633,5320],{"class":3049},[2964,5635,5636],{},[3088,5637,5325],{},[3092,5639,5640,5643,5646],{},[3095,5641,5642],{},"✓ HTTP запит до зовнішнього API",[3095,5644,5645],{},"✓ Статус-код 200-299",[3095,5647,5648],{},"✓ Timeout (10 секунд)",[3735,5650],{},[3351,5652,5654],{"id":5653},"крок-4-кастомні-health-checks","Крок 4: Кастомні Health Checks",[5142,5656,5658],{"id":5657},"_1-diskspacehealthcheck","1. DiskSpaceHealthCheck",[2964,5660,4505,5661,3365],{},[2975,5662,5663],{},"HealthChecks/DiskSpaceHealthCheck.cs",[2968,5665,5667],{"className":3409,"code":5666,"language":3411,"meta":2973,"style":2973},"using Microsoft.Extensions.Diagnostics.HealthChecks;\n\nnamespace EcommerceHealthChecksApi.HealthChecks;\n\npublic class DiskSpaceHealthCheck : IHealthCheck\n{\n    private readonly long _minimumFreeBytesThreshold;\n\n    public DiskSpaceHealthCheck(long minimumFreeBytesThreshold = 1_000_000_000) // 1 GB\n    {\n        _minimumFreeBytesThreshold = minimumFreeBytesThreshold;\n    }\n\n    public Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        try\n        {\n            var drive = DriveInfo.GetDrives()\n                .FirstOrDefault(d => d.IsReady && d.DriveType == DriveType.Fixed);\n\n            if (drive == null)\n            {\n                return Task.FromResult(\n                    HealthCheckResult.Unhealthy(\"No fixed drive found\"));\n            }\n\n            var freeSpaceBytes = drive.AvailableFreeSpace;\n            var freeSpaceGB = freeSpaceBytes / 1_000_000_000.0;\n\n            var data = new Dictionary\u003Cstring, object>\n            {\n                [\"Drive\"] = drive.Name,\n                [\"FreeSpaceGB\"] = Math.Round(freeSpaceGB, 2),\n                [\"TotalSizeGB\"] = Math.Round(drive.TotalSize / 1_000_000_000.0, 2),\n                [\"UsedPercentage\"] = Math.Round((1 - (double)freeSpaceBytes / drive.TotalSize) * 100, 2)\n            };\n\n            if (freeSpaceBytes \u003C _minimumFreeBytesThreshold)\n            {\n                return Task.FromResult(\n                    HealthCheckResult.Unhealthy(\n                        $\"Low disk space: {freeSpaceGB:F2} GB free\",\n                        data: data));\n            }\n\n            if (freeSpaceBytes \u003C _minimumFreeBytesThreshold * 2)\n            {\n                return Task.FromResult(\n                    HealthCheckResult.Degraded(\n                        $\"Disk space getting low: {freeSpaceGB:F2} GB free\",\n                        data: data));\n            }\n\n            return Task.FromResult(\n                HealthCheckResult.Healthy(\n                    $\"Sufficient disk space: {freeSpaceGB:F2} GB free\",\n                    data: data));\n        }\n        catch (Exception ex)\n        {\n            return Task.FromResult(\n                HealthCheckResult.Unhealthy(\n                    \"Error checking disk space\",\n                    exception: ex));\n        }\n    }\n}\n",[2975,5668,5669,5689,5693,5707,5711,5723,5727,5743,5747,5771,5775,5787,5791,5795,5811,5820,5835,5839,5844,5849,5869,5913,5917,5935,5940,5954,5970,5975,5979,5997,6017,6021,6048,6052,6072,6100,6134,6184,6190,6195,6212,6217,6230,6241,6266,6279,6284,6289,6309,6314,6327,6338,6358,6369,6374,6379,6393,6405,6425,6437,6443,6459,6464,6477,6488,6496,6509,6514,6519],{"__ignoreMap":2973},[2978,5670,5671,5673,5675,5677,5679,5681,5683,5685,5687],{"class":2980,"line":2981},[2978,5672,4518],{"class":3567},[2978,5674,4521],{"class":3498},[2978,5676,3119],{"class":3049},[2978,5678,4569],{"class":3498},[2978,5680,3119],{"class":3049},[2978,5682,4531],{"class":3498},[2978,5684,3119],{"class":3049},[2978,5686,4536],{"class":3498},[2978,5688,4539],{"class":3049},[2978,5690,5691],{"class":2980,"line":2988},[2978,5692,3022],{"emptyLinePlaceholder":3021},[2978,5694,5695,5698,5701,5703,5705],{"class":2980,"line":2999},[2978,5696,5697],{"class":3192},"namespace",[2978,5699,5700],{"class":3498}," EcommerceHealthChecksApi",[2978,5702,3119],{"class":3049},[2978,5704,4536],{"class":3498},[2978,5706,4539],{"class":3049},[2978,5708,5709],{"class":2980,"line":3018},[2978,5710,3022],{"emptyLinePlaceholder":3021},[2978,5712,5713,5715,5717,5719,5721],{"class":2980,"line":3025},[2978,5714,3492],{"class":3192},[2978,5716,3495],{"class":3192},[2978,5718,3499],{"class":3498},[2978,5720,3502],{"class":3049},[2978,5722,3505],{"class":3498},[2978,5724,5725],{"class":2980,"line":3031},[2978,5726,3510],{"class":3049},[2978,5728,5729,5732,5735,5738,5741],{"class":2980,"line":3040},[2978,5730,5731],{"class":3192},"    private",[2978,5733,5734],{"class":3192}," readonly",[2978,5736,5737],{"class":3192}," long",[2978,5739,5740],{"class":3418}," _minimumFreeBytesThreshold",[2978,5742,4539],{"class":3049},[2978,5744,5745],{"class":2980,"line":3059},[2978,5746,3022],{"emptyLinePlaceholder":3021},[2978,5748,5749,5751,5753,5755,5758,5761,5763,5765,5768],{"class":2980,"line":3076},[2978,5750,3515],{"class":3192},[2978,5752,3499],{"class":2991},[2978,5754,3443],{"class":3049},[2978,5756,5757],{"class":3192},"long",[2978,5759,5760],{"class":3418}," minimumFreeBytesThreshold",[2978,5762,3556],{"class":3049},[2978,5764,3576],{"class":3005},[2978,5766,5767],{"class":3049},") ",[2978,5769,5770],{"class":2984},"// 1 GB\n",[2978,5772,5773],{"class":2980,"line":3081},[2978,5774,3545],{"class":3049},[2978,5776,5777,5780,5782,5785],{"class":2980,"line":3246},[2978,5778,5779],{"class":3418},"        _minimumFreeBytesThreshold",[2978,5781,3556],{"class":3049},[2978,5783,5784],{"class":3418},"minimumFreeBytesThreshold",[2978,5786,4539],{"class":3049},[2978,5788,5789],{"class":2980,"line":3256},[2978,5790,3617],{"class":3049},[2978,5792,5793],{"class":2980,"line":3261},[2978,5794,3022],{"emptyLinePlaceholder":3021},[2978,5796,5797,5799,5801,5803,5805,5807,5809],{"class":2980,"line":3267},[2978,5798,3515],{"class":3192},[2978,5800,3518],{"class":3498},[2978,5802,3521],{"class":3049},[2978,5804,3524],{"class":3498},[2978,5806,3527],{"class":3049},[2978,5808,3530],{"class":2991},[2978,5810,5238],{"class":3049},[2978,5812,5813,5816,5818],{"class":2980,"line":3276},[2978,5814,5815],{"class":3498},"        HealthCheckContext",[2978,5817,3538],{"class":3418},[2978,5819,5062],{"class":3049},[2978,5821,5822,5825,5828,5830,5833],{"class":2980,"line":3836},[2978,5823,5824],{"class":3498},"        CancellationToken",[2978,5826,5827],{"class":3418}," cancellationToken",[2978,5829,3556],{"class":3049},[2978,5831,5832],{"class":3192},"default",[2978,5834,3175],{"class":3049},[2978,5836,5837],{"class":2980,"line":4741},[2978,5838,3545],{"class":3049},[2978,5840,5841],{"class":2980,"line":4753},[2978,5842,5843],{"class":3567},"        try\n",[2978,5845,5846],{"class":2980,"line":4758},[2978,5847,5848],{"class":3049},"        {\n",[2978,5850,5851,5854,5857,5859,5862,5864,5867],{"class":2980,"line":4764},[2978,5852,5853],{"class":3192},"            var",[2978,5855,5856],{"class":3418}," drive",[2978,5858,3556],{"class":3049},[2978,5860,5861],{"class":3418},"DriveInfo",[2978,5863,3119],{"class":3049},[2978,5865,5866],{"class":2991},"GetDrives",[2978,5868,3432],{"class":3049},[2978,5870,5871,5874,5877,5879,5882,5884,5886,5888,5891,5894,5896,5898,5901,5904,5906,5908,5911],{"class":2980,"line":4784},[2978,5872,5873],{"class":3049},"                .",[2978,5875,5876],{"class":2991},"FirstOrDefault",[2978,5878,3443],{"class":3049},[2978,5880,5881],{"class":3418},"d",[2978,5883,4266],{"class":3049},[2978,5885,5881],{"class":3418},[2978,5887,3119],{"class":3049},[2978,5889,5890],{"class":3418},"IsReady",[2978,5892,5893],{"class":3049}," && ",[2978,5895,5881],{"class":3418},[2978,5897,3119],{"class":3049},[2978,5899,5900],{"class":3418},"DriveType",[2978,5902,5903],{"class":3049}," == ",[2978,5905,5900],{"class":3418},[2978,5907,3119],{"class":3049},[2978,5909,5910],{"class":3418},"Fixed",[2978,5912,3477],{"class":3049},[2978,5914,5915],{"class":2980,"line":4789},[2978,5916,3022],{"emptyLinePlaceholder":3021},[2978,5918,5919,5922,5925,5928,5930,5933],{"class":2980,"line":4805},[2978,5920,5921],{"class":3567},"            if",[2978,5923,5924],{"class":3049}," (",[2978,5926,5927],{"class":3418},"drive",[2978,5929,5903],{"class":3049},[2978,5931,5932],{"class":3192},"null",[2978,5934,3175],{"class":3049},[2978,5936,5937],{"class":2980,"line":4810},[2978,5938,5939],{"class":3049},"            {\n",[2978,5941,5942,5945,5947,5949,5952],{"class":2980,"line":4815},[2978,5943,5944],{"class":3567},"                return",[2978,5946,3518],{"class":3418},[2978,5948,3119],{"class":3049},[2978,5950,5951],{"class":2991},"FromResult",[2978,5953,5238],{"class":3049},[2978,5955,5956,5959,5961,5963,5965,5968],{"class":2980,"line":4834},[2978,5957,5958],{"class":3418},"                    HealthCheckResult",[2978,5960,3119],{"class":3049},[2978,5962,3605],{"class":2991},[2978,5964,3443],{"class":3049},[2978,5966,5967],{"class":2995},"\"No fixed drive found\"",[2978,5969,5320],{"class":3049},[2978,5971,5972],{"class":2980,"line":4839},[2978,5973,5974],{"class":3049},"            }\n",[2978,5976,5977],{"class":2980,"line":4867},[2978,5978,3022],{"emptyLinePlaceholder":3021},[2978,5980,5981,5983,5986,5988,5990,5992,5995],{"class":2980,"line":4880},[2978,5982,5853],{"class":3192},[2978,5984,5985],{"class":3418}," freeSpaceBytes",[2978,5987,3556],{"class":3049},[2978,5989,5927],{"class":3418},[2978,5991,3119],{"class":3049},[2978,5993,5994],{"class":3418},"AvailableFreeSpace",[2978,5996,4539],{"class":3049},[2978,5998,5999,6001,6004,6006,6009,6012,6015],{"class":2980,"line":4885},[2978,6000,5853],{"class":3192},[2978,6002,6003],{"class":3418}," freeSpaceGB",[2978,6005,3556],{"class":3049},[2978,6007,6008],{"class":3418},"freeSpaceBytes",[2978,6010,6011],{"class":3049}," / ",[2978,6013,6014],{"class":3005},"1_000_000_000.0",[2978,6016,4539],{"class":3049},[2978,6018,6019],{"class":2980,"line":4890},[2978,6020,3022],{"emptyLinePlaceholder":3021},[2978,6022,6023,6025,6028,6030,6032,6035,6037,6040,6042,6045],{"class":2980,"line":4909},[2978,6024,5853],{"class":3192},[2978,6026,6027],{"class":3418}," data",[2978,6029,3556],{"class":3049},[2978,6031,4130],{"class":3192},[2978,6033,6034],{"class":3498}," Dictionary",[2978,6036,3521],{"class":3049},[2978,6038,6039],{"class":3192},"string",[2978,6041,4122],{"class":3049},[2978,6043,6044],{"class":3192},"object",[2978,6046,6047],{"class":3049},">\n",[2978,6049,6050],{"class":2980,"line":4914},[2978,6051,5939],{"class":3049},[2978,6053,6054,6057,6060,6063,6065,6067,6070],{"class":2980,"line":4941},[2978,6055,6056],{"class":3049},"                [",[2978,6058,6059],{"class":2995},"\"Drive\"",[2978,6061,6062],{"class":3049},"] = ",[2978,6064,5927],{"class":3418},[2978,6066,3119],{"class":3049},[2978,6068,6069],{"class":3418},"Name",[2978,6071,5062],{"class":3049},[2978,6073,6074,6076,6079,6081,6084,6086,6089,6091,6094,6096,6098],{"class":2980,"line":4954},[2978,6075,6056],{"class":3049},[2978,6077,6078],{"class":2995},"\"FreeSpaceGB\"",[2978,6080,6062],{"class":3049},[2978,6082,6083],{"class":3418},"Math",[2978,6085,3119],{"class":3049},[2978,6087,6088],{"class":2991},"Round",[2978,6090,3443],{"class":3049},[2978,6092,6093],{"class":3418},"freeSpaceGB",[2978,6095,4122],{"class":3049},[2978,6097,3989],{"class":3005},[2978,6099,4864],{"class":3049},[2978,6101,6102,6104,6107,6109,6111,6113,6115,6117,6119,6121,6124,6126,6128,6130,6132],{"class":2980,"line":4959},[2978,6103,6056],{"class":3049},[2978,6105,6106],{"class":2995},"\"TotalSizeGB\"",[2978,6108,6062],{"class":3049},[2978,6110,6083],{"class":3418},[2978,6112,3119],{"class":3049},[2978,6114,6088],{"class":2991},[2978,6116,3443],{"class":3049},[2978,6118,5927],{"class":3418},[2978,6120,3119],{"class":3049},[2978,6122,6123],{"class":3418},"TotalSize",[2978,6125,6011],{"class":3049},[2978,6127,6014],{"class":3005},[2978,6129,4122],{"class":3049},[2978,6131,3989],{"class":3005},[2978,6133,4864],{"class":3049},[2978,6135,6136,6138,6141,6143,6145,6147,6149,6152,6154,6157,6160,6162,6164,6166,6168,6170,6172,6175,6178,6180,6182],{"class":2980,"line":4964},[2978,6137,6056],{"class":3049},[2978,6139,6140],{"class":2995},"\"UsedPercentage\"",[2978,6142,6062],{"class":3049},[2978,6144,6083],{"class":3418},[2978,6146,3119],{"class":3049},[2978,6148,6088],{"class":2991},[2978,6150,6151],{"class":3049},"((",[2978,6153,3973],{"class":3005},[2978,6155,6156],{"class":3049}," - (",[2978,6158,6159],{"class":3192},"double",[2978,6161,5337],{"class":3049},[2978,6163,6008],{"class":3418},[2978,6165,6011],{"class":3049},[2978,6167,5927],{"class":3418},[2978,6169,3119],{"class":3049},[2978,6171,6123],{"class":3418},[2978,6173,6174],{"class":3049},") * ",[2978,6176,6177],{"class":3005},"100",[2978,6179,4122],{"class":3049},[2978,6181,3989],{"class":3005},[2978,6183,3175],{"class":3049},[2978,6185,6187],{"class":2980,"line":6186},38,[2978,6188,6189],{"class":3049},"            };\n",[2978,6191,6193],{"class":2980,"line":6192},39,[2978,6194,3022],{"emptyLinePlaceholder":3021},[2978,6196,6198,6200,6202,6204,6207,6210],{"class":2980,"line":6197},40,[2978,6199,5921],{"class":3567},[2978,6201,5924],{"class":3049},[2978,6203,6008],{"class":3418},[2978,6205,6206],{"class":3049}," \u003C ",[2978,6208,6209],{"class":3418},"_minimumFreeBytesThreshold",[2978,6211,3175],{"class":3049},[2978,6213,6215],{"class":2980,"line":6214},41,[2978,6216,5939],{"class":3049},[2978,6218,6220,6222,6224,6226,6228],{"class":2980,"line":6219},42,[2978,6221,5944],{"class":3567},[2978,6223,3518],{"class":3418},[2978,6225,3119],{"class":3049},[2978,6227,5951],{"class":2991},[2978,6229,5238],{"class":3049},[2978,6231,6233,6235,6237,6239],{"class":2980,"line":6232},43,[2978,6234,5958],{"class":3418},[2978,6236,3119],{"class":3049},[2978,6238,3605],{"class":2991},[2978,6240,5238],{"class":3049},[2978,6242,6244,6247,6251,6253,6255,6258,6261,6264],{"class":2980,"line":6243},44,[2978,6245,6246],{"class":2995},"                        $\"Low disk space: ",[2978,6248,6250],{"class":6249},"sD7JJ","{",[2978,6252,6093],{"class":3418},[2978,6254,3365],{"class":3049},[2978,6256,6257],{"class":3418},"F2",[2978,6259,6260],{"class":6249},"}",[2978,6262,6263],{"class":2995}," GB free\"",[2978,6265,5062],{"class":3049},[2978,6267,6269,6272,6274,6277],{"class":2980,"line":6268},45,[2978,6270,6271],{"class":3418},"                        data",[2978,6273,3669],{"class":3049},[2978,6275,6276],{"class":3418},"data",[2978,6278,5320],{"class":3049},[2978,6280,6282],{"class":2980,"line":6281},46,[2978,6283,5974],{"class":3049},[2978,6285,6287],{"class":2980,"line":6286},47,[2978,6288,3022],{"emptyLinePlaceholder":3021},[2978,6290,6292,6294,6296,6298,6300,6302,6305,6307],{"class":2980,"line":6291},48,[2978,6293,5921],{"class":3567},[2978,6295,5924],{"class":3049},[2978,6297,6008],{"class":3418},[2978,6299,6206],{"class":3049},[2978,6301,6209],{"class":3418},[2978,6303,6304],{"class":3049}," * ",[2978,6306,3989],{"class":3005},[2978,6308,3175],{"class":3049},[2978,6310,6312],{"class":2980,"line":6311},49,[2978,6313,5939],{"class":3049},[2978,6315,6317,6319,6321,6323,6325],{"class":2980,"line":6316},50,[2978,6318,5944],{"class":3567},[2978,6320,3518],{"class":3418},[2978,6322,3119],{"class":3049},[2978,6324,5951],{"class":2991},[2978,6326,5238],{"class":3049},[2978,6328,6330,6332,6334,6336],{"class":2980,"line":6329},51,[2978,6331,5958],{"class":3418},[2978,6333,3119],{"class":3049},[2978,6335,4050],{"class":2991},[2978,6337,5238],{"class":3049},[2978,6339,6341,6344,6346,6348,6350,6352,6354,6356],{"class":2980,"line":6340},52,[2978,6342,6343],{"class":2995},"                        $\"Disk space getting low: ",[2978,6345,6250],{"class":6249},[2978,6347,6093],{"class":3418},[2978,6349,3365],{"class":3049},[2978,6351,6257],{"class":3418},[2978,6353,6260],{"class":6249},[2978,6355,6263],{"class":2995},[2978,6357,5062],{"class":3049},[2978,6359,6361,6363,6365,6367],{"class":2980,"line":6360},53,[2978,6362,6271],{"class":3418},[2978,6364,3669],{"class":3049},[2978,6366,6276],{"class":3418},[2978,6368,5320],{"class":3049},[2978,6370,6372],{"class":2980,"line":6371},54,[2978,6373,5974],{"class":3049},[2978,6375,6377],{"class":2980,"line":6376},55,[2978,6378,3022],{"emptyLinePlaceholder":3021},[2978,6380,6382,6385,6387,6389,6391],{"class":2980,"line":6381},56,[2978,6383,6384],{"class":3567},"            return",[2978,6386,3518],{"class":3418},[2978,6388,3119],{"class":3049},[2978,6390,5951],{"class":2991},[2978,6392,5238],{"class":3049},[2978,6394,6396,6399,6401,6403],{"class":2980,"line":6395},57,[2978,6397,6398],{"class":3418},"                HealthCheckResult",[2978,6400,3119],{"class":3049},[2978,6402,3591],{"class":2991},[2978,6404,5238],{"class":3049},[2978,6406,6408,6411,6413,6415,6417,6419,6421,6423],{"class":2980,"line":6407},58,[2978,6409,6410],{"class":2995},"                    $\"Sufficient disk space: ",[2978,6412,6250],{"class":6249},[2978,6414,6093],{"class":3418},[2978,6416,3365],{"class":3049},[2978,6418,6257],{"class":3418},[2978,6420,6260],{"class":6249},[2978,6422,6263],{"class":2995},[2978,6424,5062],{"class":3049},[2978,6426,6428,6431,6433,6435],{"class":2980,"line":6427},59,[2978,6429,6430],{"class":3418},"                    data",[2978,6432,3669],{"class":3049},[2978,6434,6276],{"class":3418},[2978,6436,5320],{"class":3049},[2978,6438,6440],{"class":2980,"line":6439},60,[2978,6441,6442],{"class":3049},"        }\n",[2978,6444,6446,6449,6451,6454,6457],{"class":2980,"line":6445},61,[2978,6447,6448],{"class":3567},"        catch",[2978,6450,5924],{"class":3049},[2978,6452,6453],{"class":3498},"Exception",[2978,6455,6456],{"class":3418}," ex",[2978,6458,3175],{"class":3049},[2978,6460,6462],{"class":2980,"line":6461},62,[2978,6463,5848],{"class":3049},[2978,6465,6467,6469,6471,6473,6475],{"class":2980,"line":6466},63,[2978,6468,6384],{"class":3567},[2978,6470,3518],{"class":3418},[2978,6472,3119],{"class":3049},[2978,6474,5951],{"class":2991},[2978,6476,5238],{"class":3049},[2978,6478,6480,6482,6484,6486],{"class":2980,"line":6479},64,[2978,6481,6398],{"class":3418},[2978,6483,3119],{"class":3049},[2978,6485,3605],{"class":2991},[2978,6487,5238],{"class":3049},[2978,6489,6491,6494],{"class":2980,"line":6490},65,[2978,6492,6493],{"class":2995},"                    \"Error checking disk space\"",[2978,6495,5062],{"class":3049},[2978,6497,6499,6502,6504,6507],{"class":2980,"line":6498},66,[2978,6500,6501],{"class":3418},"                    exception",[2978,6503,3669],{"class":3049},[2978,6505,6506],{"class":3418},"ex",[2978,6508,5320],{"class":3049},[2978,6510,6512],{"class":2980,"line":6511},67,[2978,6513,6442],{"class":3049},[2978,6515,6517],{"class":2980,"line":6516},68,[2978,6518,3617],{"class":3049},[2978,6520,6522],{"class":2980,"line":6521},69,[2978,6523,3622],{"class":3049},[2964,6525,6526],{},[3088,6527,4978],{},[4980,6529,6530,6538,6545,6552,6559],{},[3095,6531,6532,6537],{},[3088,6533,6534],{},[2975,6535,6536],{},"IHealthCheck"," — інтерфейс для кастомних чеків",[3095,6539,6540,6544],{},[3088,6541,6542],{},[2975,6543,3530],{}," — метод перевірки",[3095,6546,6547,6551],{},[3088,6548,6549],{},[2975,6550,3524],{}," — результат (Healthy/Degraded/Unhealthy)",[3095,6553,6554,6558],{},[3088,6555,6556],{},[2975,6557,6276],{}," — додаткові дані для моніторингу",[3095,6560,6561,6564],{},[3088,6562,6563],{},"Пороги"," — \u003C 1 GB = Unhealthy, \u003C 2 GB = Degraded",[5142,6566,6568],{"id":6567},"_2-memoryhealthcheck","2. MemoryHealthCheck",[2964,6570,4505,6571,3365],{},[2975,6572,6573],{},"HealthChecks/MemoryHealthCheck.cs",[2968,6575,6577],{"className":3409,"code":6576,"language":3411,"meta":2973,"style":2973},"using Microsoft.Extensions.Diagnostics.HealthChecks;\n\nnamespace EcommerceHealthChecksApi.HealthChecks;\n\npublic class MemoryHealthCheck : IHealthCheck\n{\n    private readonly long _thresholdBytes;\n\n    public MemoryHealthCheck(long thresholdBytes = 1_000_000_000) // 1 GB\n    {\n        _thresholdBytes = thresholdBytes;\n    }\n\n    public Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        var allocated = GC.GetTotalMemory(forceFullCollection: false);\n        var allocatedMB = allocated / 1_000_000.0;\n\n        var data = new Dictionary\u003Cstring, object>\n        {\n            [\"AllocatedMB\"] = Math.Round(allocatedMB, 2),\n            [\"Gen0Collections\"] = GC.CollectionCount(0),\n            [\"Gen1Collections\"] = GC.CollectionCount(1),\n            [\"Gen2Collections\"] = GC.CollectionCount(2)\n        };\n\n        if (allocated > _thresholdBytes)\n        {\n            return Task.FromResult(\n                HealthCheckResult.Degraded(\n                    $\"High memory usage: {allocatedMB:F2} MB\",\n                    data: data));\n        }\n\n        return Task.FromResult(\n            HealthCheckResult.Healthy(\n                $\"Memory usage normal: {allocatedMB:F2} MB\",\n                data: data));\n    }\n}\n",[2975,6578,6579,6599,6603,6615,6619,6632,6636,6649,6653,6674,6678,6690,6694,6698,6714,6722,6734,6738,6767,6786,6790,6812,6816,6843,6865,6886,6907,6912,6916,6932,6936,6948,6958,6978,6988,6992,6996,7008,7019,7038,7049,7053],{"__ignoreMap":2973},[2978,6580,6581,6583,6585,6587,6589,6591,6593,6595,6597],{"class":2980,"line":2981},[2978,6582,4518],{"class":3567},[2978,6584,4521],{"class":3498},[2978,6586,3119],{"class":3049},[2978,6588,4569],{"class":3498},[2978,6590,3119],{"class":3049},[2978,6592,4531],{"class":3498},[2978,6594,3119],{"class":3049},[2978,6596,4536],{"class":3498},[2978,6598,4539],{"class":3049},[2978,6600,6601],{"class":2980,"line":2988},[2978,6602,3022],{"emptyLinePlaceholder":3021},[2978,6604,6605,6607,6609,6611,6613],{"class":2980,"line":2999},[2978,6606,5697],{"class":3192},[2978,6608,5700],{"class":3498},[2978,6610,3119],{"class":3049},[2978,6612,4536],{"class":3498},[2978,6614,4539],{"class":3049},[2978,6616,6617],{"class":2980,"line":3018},[2978,6618,3022],{"emptyLinePlaceholder":3021},[2978,6620,6621,6623,6625,6628,6630],{"class":2980,"line":3025},[2978,6622,3492],{"class":3192},[2978,6624,3495],{"class":3192},[2978,6626,6627],{"class":3498}," MemoryHealthCheck",[2978,6629,3502],{"class":3049},[2978,6631,3505],{"class":3498},[2978,6633,6634],{"class":2980,"line":3031},[2978,6635,3510],{"class":3049},[2978,6637,6638,6640,6642,6644,6647],{"class":2980,"line":3040},[2978,6639,5731],{"class":3192},[2978,6641,5734],{"class":3192},[2978,6643,5737],{"class":3192},[2978,6645,6646],{"class":3418}," _thresholdBytes",[2978,6648,4539],{"class":3049},[2978,6650,6651],{"class":2980,"line":3059},[2978,6652,3022],{"emptyLinePlaceholder":3021},[2978,6654,6655,6657,6659,6661,6663,6666,6668,6670,6672],{"class":2980,"line":3076},[2978,6656,3515],{"class":3192},[2978,6658,6627],{"class":2991},[2978,6660,3443],{"class":3049},[2978,6662,5757],{"class":3192},[2978,6664,6665],{"class":3418}," thresholdBytes",[2978,6667,3556],{"class":3049},[2978,6669,3576],{"class":3005},[2978,6671,5767],{"class":3049},[2978,6673,5770],{"class":2984},[2978,6675,6676],{"class":2980,"line":3081},[2978,6677,3545],{"class":3049},[2978,6679,6680,6683,6685,6688],{"class":2980,"line":3246},[2978,6681,6682],{"class":3418},"        _thresholdBytes",[2978,6684,3556],{"class":3049},[2978,6686,6687],{"class":3418},"thresholdBytes",[2978,6689,4539],{"class":3049},[2978,6691,6692],{"class":2980,"line":3256},[2978,6693,3617],{"class":3049},[2978,6695,6696],{"class":2980,"line":3261},[2978,6697,3022],{"emptyLinePlaceholder":3021},[2978,6699,6700,6702,6704,6706,6708,6710,6712],{"class":2980,"line":3267},[2978,6701,3515],{"class":3192},[2978,6703,3518],{"class":3498},[2978,6705,3521],{"class":3049},[2978,6707,3524],{"class":3498},[2978,6709,3527],{"class":3049},[2978,6711,3530],{"class":2991},[2978,6713,5238],{"class":3049},[2978,6715,6716,6718,6720],{"class":2980,"line":3276},[2978,6717,5815],{"class":3498},[2978,6719,3538],{"class":3418},[2978,6721,5062],{"class":3049},[2978,6723,6724,6726,6728,6730,6732],{"class":2980,"line":3836},[2978,6725,5824],{"class":3498},[2978,6727,5827],{"class":3418},[2978,6729,3556],{"class":3049},[2978,6731,5832],{"class":3192},[2978,6733,3175],{"class":3049},[2978,6735,6736],{"class":2980,"line":4741},[2978,6737,3545],{"class":3049},[2978,6739,6740,6742,6745,6747,6750,6752,6755,6757,6760,6762,6765],{"class":2980,"line":4753},[2978,6741,3550],{"class":3192},[2978,6743,6744],{"class":3418}," allocated",[2978,6746,3556],{"class":3049},[2978,6748,6749],{"class":3418},"GC",[2978,6751,3119],{"class":3049},[2978,6753,6754],{"class":2991},"GetTotalMemory",[2978,6756,3443],{"class":3049},[2978,6758,6759],{"class":3418},"forceFullCollection",[2978,6761,3669],{"class":3049},[2978,6763,6764],{"class":3192},"false",[2978,6766,3477],{"class":3049},[2978,6768,6769,6771,6774,6776,6779,6781,6784],{"class":2980,"line":4758},[2978,6770,3550],{"class":3192},[2978,6772,6773],{"class":3418}," allocatedMB",[2978,6775,3556],{"class":3049},[2978,6777,6778],{"class":3418},"allocated",[2978,6780,6011],{"class":3049},[2978,6782,6783],{"class":3005},"1_000_000.0",[2978,6785,4539],{"class":3049},[2978,6787,6788],{"class":2980,"line":4764},[2978,6789,3022],{"emptyLinePlaceholder":3021},[2978,6791,6792,6794,6796,6798,6800,6802,6804,6806,6808,6810],{"class":2980,"line":4784},[2978,6793,3550],{"class":3192},[2978,6795,6027],{"class":3418},[2978,6797,3556],{"class":3049},[2978,6799,4130],{"class":3192},[2978,6801,6034],{"class":3498},[2978,6803,3521],{"class":3049},[2978,6805,6039],{"class":3192},[2978,6807,4122],{"class":3049},[2978,6809,6044],{"class":3192},[2978,6811,6047],{"class":3049},[2978,6813,6814],{"class":2980,"line":4789},[2978,6815,5848],{"class":3049},[2978,6817,6818,6821,6824,6826,6828,6830,6832,6834,6837,6839,6841],{"class":2980,"line":4805},[2978,6819,6820],{"class":3049},"            [",[2978,6822,6823],{"class":2995},"\"AllocatedMB\"",[2978,6825,6062],{"class":3049},[2978,6827,6083],{"class":3418},[2978,6829,3119],{"class":3049},[2978,6831,6088],{"class":2991},[2978,6833,3443],{"class":3049},[2978,6835,6836],{"class":3418},"allocatedMB",[2978,6838,4122],{"class":3049},[2978,6840,3989],{"class":3005},[2978,6842,4864],{"class":3049},[2978,6844,6845,6847,6850,6852,6854,6856,6859,6861,6863],{"class":2980,"line":4810},[2978,6846,6820],{"class":3049},[2978,6848,6849],{"class":2995},"\"Gen0Collections\"",[2978,6851,6062],{"class":3049},[2978,6853,6749],{"class":3418},[2978,6855,3119],{"class":3049},[2978,6857,6858],{"class":2991},"CollectionCount",[2978,6860,3443],{"class":3049},[2978,6862,3957],{"class":3005},[2978,6864,4864],{"class":3049},[2978,6866,6867,6869,6872,6874,6876,6878,6880,6882,6884],{"class":2980,"line":4815},[2978,6868,6820],{"class":3049},[2978,6870,6871],{"class":2995},"\"Gen1Collections\"",[2978,6873,6062],{"class":3049},[2978,6875,6749],{"class":3418},[2978,6877,3119],{"class":3049},[2978,6879,6858],{"class":2991},[2978,6881,3443],{"class":3049},[2978,6883,3973],{"class":3005},[2978,6885,4864],{"class":3049},[2978,6887,6888,6890,6893,6895,6897,6899,6901,6903,6905],{"class":2980,"line":4834},[2978,6889,6820],{"class":3049},[2978,6891,6892],{"class":2995},"\"Gen2Collections\"",[2978,6894,6062],{"class":3049},[2978,6896,6749],{"class":3418},[2978,6898,3119],{"class":3049},[2978,6900,6858],{"class":2991},[2978,6902,3443],{"class":3049},[2978,6904,3989],{"class":3005},[2978,6906,3175],{"class":3049},[2978,6908,6909],{"class":2980,"line":4839},[2978,6910,6911],{"class":3049},"        };\n",[2978,6913,6914],{"class":2980,"line":4867},[2978,6915,3022],{"emptyLinePlaceholder":3021},[2978,6917,6918,6921,6923,6925,6927,6930],{"class":2980,"line":4880},[2978,6919,6920],{"class":3567},"        if",[2978,6922,5924],{"class":3049},[2978,6924,6778],{"class":3418},[2978,6926,3573],{"class":3049},[2978,6928,6929],{"class":3418},"_thresholdBytes",[2978,6931,3175],{"class":3049},[2978,6933,6934],{"class":2980,"line":4885},[2978,6935,5848],{"class":3049},[2978,6937,6938,6940,6942,6944,6946],{"class":2980,"line":4890},[2978,6939,6384],{"class":3567},[2978,6941,3518],{"class":3418},[2978,6943,3119],{"class":3049},[2978,6945,5951],{"class":2991},[2978,6947,5238],{"class":3049},[2978,6949,6950,6952,6954,6956],{"class":2980,"line":4909},[2978,6951,6398],{"class":3418},[2978,6953,3119],{"class":3049},[2978,6955,4050],{"class":2991},[2978,6957,5238],{"class":3049},[2978,6959,6960,6963,6965,6967,6969,6971,6973,6976],{"class":2980,"line":4914},[2978,6961,6962],{"class":2995},"                    $\"High memory usage: ",[2978,6964,6250],{"class":6249},[2978,6966,6836],{"class":3418},[2978,6968,3365],{"class":3049},[2978,6970,6257],{"class":3418},[2978,6972,6260],{"class":6249},[2978,6974,6975],{"class":2995}," MB\"",[2978,6977,5062],{"class":3049},[2978,6979,6980,6982,6984,6986],{"class":2980,"line":4941},[2978,6981,6430],{"class":3418},[2978,6983,3669],{"class":3049},[2978,6985,6276],{"class":3418},[2978,6987,5320],{"class":3049},[2978,6989,6990],{"class":2980,"line":4954},[2978,6991,6442],{"class":3049},[2978,6993,6994],{"class":2980,"line":4959},[2978,6995,3022],{"emptyLinePlaceholder":3021},[2978,6997,6998,7000,7002,7004,7006],{"class":2980,"line":4964},[2978,6999,3568],{"class":3567},[2978,7001,3518],{"class":3418},[2978,7003,3119],{"class":3049},[2978,7005,5951],{"class":2991},[2978,7007,5238],{"class":3049},[2978,7009,7010,7013,7015,7017],{"class":2980,"line":6186},[2978,7011,7012],{"class":3418},"            HealthCheckResult",[2978,7014,3119],{"class":3049},[2978,7016,3591],{"class":2991},[2978,7018,5238],{"class":3049},[2978,7020,7021,7024,7026,7028,7030,7032,7034,7036],{"class":2980,"line":6192},[2978,7022,7023],{"class":2995},"                $\"Memory usage normal: ",[2978,7025,6250],{"class":6249},[2978,7027,6836],{"class":3418},[2978,7029,3365],{"class":3049},[2978,7031,6257],{"class":3418},[2978,7033,6260],{"class":6249},[2978,7035,6975],{"class":2995},[2978,7037,5062],{"class":3049},[2978,7039,7040,7043,7045,7047],{"class":2980,"line":6197},[2978,7041,7042],{"class":3418},"                data",[2978,7044,3669],{"class":3049},[2978,7046,6276],{"class":3418},[2978,7048,5320],{"class":3049},[2978,7050,7051],{"class":2980,"line":6214},[2978,7052,3617],{"class":3049},[2978,7054,7055],{"class":2980,"line":6219},[2978,7056,3622],{"class":3049},[5142,7058,7060],{"id":7059},"_3-externalapihealthcheck","3. ExternalApiHealthCheck",[2964,7062,4505,7063,3365],{},[2975,7064,7065],{},"HealthChecks/ExternalApiHealthCheck.cs",[2968,7067,7069],{"className":3409,"code":7068,"language":3411,"meta":2973,"style":2973},"using Microsoft.Extensions.Diagnostics.HealthChecks;\n\nnamespace EcommerceHealthChecksApi.HealthChecks;\n\npublic class ExternalApiHealthCheck : IHealthCheck\n{\n    private readonly HttpClient _httpClient;\n    private readonly string _url;\n\n    public ExternalApiHealthCheck(HttpClient httpClient, string url)\n    {\n        _httpClient = httpClient;\n        _url = url;\n    }\n\n    public async Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        try\n        {\n            var stopwatch = System.Diagnostics.Stopwatch.StartNew();\n            var response = await _httpClient.GetAsync(_url, cancellationToken);\n            stopwatch.Stop();\n\n            var data = new Dictionary\u003Cstring, object>\n            {\n                [\"Url\"] = _url,\n                [\"StatusCode\"] = (int)response.StatusCode,\n                [\"ResponseTimeMs\"] = stopwatch.ElapsedMilliseconds\n            };\n\n            if (!response.IsSuccessStatusCode)\n            {\n                return HealthCheckResult.Unhealthy(\n                    $\"External API returned {response.StatusCode}\",\n                    data: data);\n            }\n\n            if (stopwatch.ElapsedMilliseconds > 5000)\n            {\n                return HealthCheckResult.Degraded(\n                    $\"External API slow: {stopwatch.ElapsedMilliseconds}ms\",\n                    data: data);\n            }\n\n            return HealthCheckResult.Healthy(\n                $\"External API responsive: {stopwatch.ElapsedMilliseconds}ms\",\n                data: data);\n        }\n        catch (Exception ex)\n        {\n            return HealthCheckResult.Unhealthy(\n                $\"External API unreachable: {ex.Message}\",\n                exception: ex);\n        }\n    }\n}\n",[2975,7070,7071,7091,7095,7107,7111,7124,7128,7142,7156,7160,7183,7187,7199,7211,7215,7219,7238,7246,7258,7262,7266,7270,7298,7329,7341,7345,7367,7371,7384,7409,7426,7430,7434,7450,7454,7466,7486,7496,7500,7504,7524,7528,7540,7560,7570,7574,7578,7590,7609,7619,7623,7635,7639,7651,7671,7682,7686,7690],{"__ignoreMap":2973},[2978,7072,7073,7075,7077,7079,7081,7083,7085,7087,7089],{"class":2980,"line":2981},[2978,7074,4518],{"class":3567},[2978,7076,4521],{"class":3498},[2978,7078,3119],{"class":3049},[2978,7080,4569],{"class":3498},[2978,7082,3119],{"class":3049},[2978,7084,4531],{"class":3498},[2978,7086,3119],{"class":3049},[2978,7088,4536],{"class":3498},[2978,7090,4539],{"class":3049},[2978,7092,7093],{"class":2980,"line":2988},[2978,7094,3022],{"emptyLinePlaceholder":3021},[2978,7096,7097,7099,7101,7103,7105],{"class":2980,"line":2999},[2978,7098,5697],{"class":3192},[2978,7100,5700],{"class":3498},[2978,7102,3119],{"class":3049},[2978,7104,4536],{"class":3498},[2978,7106,4539],{"class":3049},[2978,7108,7109],{"class":2980,"line":3018},[2978,7110,3022],{"emptyLinePlaceholder":3021},[2978,7112,7113,7115,7117,7120,7122],{"class":2980,"line":3025},[2978,7114,3492],{"class":3192},[2978,7116,3495],{"class":3192},[2978,7118,7119],{"class":3498}," ExternalApiHealthCheck",[2978,7121,3502],{"class":3049},[2978,7123,3505],{"class":3498},[2978,7125,7126],{"class":2980,"line":3031},[2978,7127,3510],{"class":3049},[2978,7129,7130,7132,7134,7137,7140],{"class":2980,"line":3040},[2978,7131,5731],{"class":3192},[2978,7133,5734],{"class":3192},[2978,7135,7136],{"class":3498}," HttpClient",[2978,7138,7139],{"class":3418}," _httpClient",[2978,7141,4539],{"class":3049},[2978,7143,7144,7146,7148,7151,7154],{"class":2980,"line":3059},[2978,7145,5731],{"class":3192},[2978,7147,5734],{"class":3192},[2978,7149,7150],{"class":3192}," string",[2978,7152,7153],{"class":3418}," _url",[2978,7155,4539],{"class":3049},[2978,7157,7158],{"class":2980,"line":3076},[2978,7159,3022],{"emptyLinePlaceholder":3021},[2978,7161,7162,7164,7166,7168,7171,7174,7176,7178,7181],{"class":2980,"line":3081},[2978,7163,3515],{"class":3192},[2978,7165,7119],{"class":2991},[2978,7167,3443],{"class":3049},[2978,7169,7170],{"class":3498},"HttpClient",[2978,7172,7173],{"class":3418}," httpClient",[2978,7175,4122],{"class":3049},[2978,7177,6039],{"class":3192},[2978,7179,7180],{"class":3418}," url",[2978,7182,3175],{"class":3049},[2978,7184,7185],{"class":2980,"line":3246},[2978,7186,3545],{"class":3049},[2978,7188,7189,7192,7194,7197],{"class":2980,"line":3256},[2978,7190,7191],{"class":3418},"        _httpClient",[2978,7193,3556],{"class":3049},[2978,7195,7196],{"class":3418},"httpClient",[2978,7198,4539],{"class":3049},[2978,7200,7201,7204,7206,7209],{"class":2980,"line":3261},[2978,7202,7203],{"class":3418},"        _url",[2978,7205,3556],{"class":3049},[2978,7207,7208],{"class":3418},"url",[2978,7210,4539],{"class":3049},[2978,7212,7213],{"class":2980,"line":3267},[2978,7214,3617],{"class":3049},[2978,7216,7217],{"class":2980,"line":3276},[2978,7218,3022],{"emptyLinePlaceholder":3021},[2978,7220,7221,7223,7226,7228,7230,7232,7234,7236],{"class":2980,"line":3836},[2978,7222,3515],{"class":3192},[2978,7224,7225],{"class":3192}," async",[2978,7227,3518],{"class":3498},[2978,7229,3521],{"class":3049},[2978,7231,3524],{"class":3498},[2978,7233,3527],{"class":3049},[2978,7235,3530],{"class":2991},[2978,7237,5238],{"class":3049},[2978,7239,7240,7242,7244],{"class":2980,"line":4741},[2978,7241,5815],{"class":3498},[2978,7243,3538],{"class":3418},[2978,7245,5062],{"class":3049},[2978,7247,7248,7250,7252,7254,7256],{"class":2980,"line":4753},[2978,7249,5824],{"class":3498},[2978,7251,5827],{"class":3418},[2978,7253,3556],{"class":3049},[2978,7255,5832],{"class":3192},[2978,7257,3175],{"class":3049},[2978,7259,7260],{"class":2980,"line":4758},[2978,7261,3545],{"class":3049},[2978,7263,7264],{"class":2980,"line":4764},[2978,7265,5843],{"class":3567},[2978,7267,7268],{"class":2980,"line":4784},[2978,7269,5848],{"class":3049},[2978,7271,7272,7274,7277,7279,7282,7284,7286,7288,7291,7293,7296],{"class":2980,"line":4789},[2978,7273,5853],{"class":3192},[2978,7275,7276],{"class":3418}," stopwatch",[2978,7278,3556],{"class":3049},[2978,7280,7281],{"class":3418},"System",[2978,7283,3119],{"class":3049},[2978,7285,4531],{"class":3418},[2978,7287,3119],{"class":3049},[2978,7289,7290],{"class":3418},"Stopwatch",[2978,7292,3119],{"class":3049},[2978,7294,7295],{"class":2991},"StartNew",[2978,7297,3562],{"class":3049},[2978,7299,7300,7302,7305,7307,7310,7312,7314,7317,7319,7322,7324,7327],{"class":2980,"line":4805},[2978,7301,5853],{"class":3192},[2978,7303,7304],{"class":3418}," response",[2978,7306,3556],{"class":3049},[2978,7308,7309],{"class":3192},"await",[2978,7311,7139],{"class":3418},[2978,7313,3119],{"class":3049},[2978,7315,7316],{"class":2991},"GetAsync",[2978,7318,3443],{"class":3049},[2978,7320,7321],{"class":3418},"_url",[2978,7323,4122],{"class":3049},[2978,7325,7326],{"class":3418},"cancellationToken",[2978,7328,3477],{"class":3049},[2978,7330,7331,7334,7336,7339],{"class":2980,"line":4810},[2978,7332,7333],{"class":3418},"            stopwatch",[2978,7335,3119],{"class":3049},[2978,7337,7338],{"class":2991},"Stop",[2978,7340,3562],{"class":3049},[2978,7342,7343],{"class":2980,"line":4815},[2978,7344,3022],{"emptyLinePlaceholder":3021},[2978,7346,7347,7349,7351,7353,7355,7357,7359,7361,7363,7365],{"class":2980,"line":4834},[2978,7348,5853],{"class":3192},[2978,7350,6027],{"class":3418},[2978,7352,3556],{"class":3049},[2978,7354,4130],{"class":3192},[2978,7356,6034],{"class":3498},[2978,7358,3521],{"class":3049},[2978,7360,6039],{"class":3192},[2978,7362,4122],{"class":3049},[2978,7364,6044],{"class":3192},[2978,7366,6047],{"class":3049},[2978,7368,7369],{"class":2980,"line":4839},[2978,7370,5939],{"class":3049},[2978,7372,7373,7375,7378,7380,7382],{"class":2980,"line":4867},[2978,7374,6056],{"class":3049},[2978,7376,7377],{"class":2995},"\"Url\"",[2978,7379,6062],{"class":3049},[2978,7381,7321],{"class":3418},[2978,7383,5062],{"class":3049},[2978,7385,7386,7388,7391,7394,7397,7399,7402,7404,7407],{"class":2980,"line":4880},[2978,7387,6056],{"class":3049},[2978,7389,7390],{"class":2995},"\"StatusCode\"",[2978,7392,7393],{"class":3049},"] = (",[2978,7395,7396],{"class":3192},"int",[2978,7398,5337],{"class":3049},[2978,7400,7401],{"class":3418},"response",[2978,7403,3119],{"class":3049},[2978,7405,7406],{"class":3418},"StatusCode",[2978,7408,5062],{"class":3049},[2978,7410,7411,7413,7416,7418,7421,7423],{"class":2980,"line":4885},[2978,7412,6056],{"class":3049},[2978,7414,7415],{"class":2995},"\"ResponseTimeMs\"",[2978,7417,6062],{"class":3049},[2978,7419,7420],{"class":3418},"stopwatch",[2978,7422,3119],{"class":3049},[2978,7424,7425],{"class":3418},"ElapsedMilliseconds\n",[2978,7427,7428],{"class":2980,"line":4890},[2978,7429,6189],{"class":3049},[2978,7431,7432],{"class":2980,"line":4909},[2978,7433,3022],{"emptyLinePlaceholder":3021},[2978,7435,7436,7438,7441,7443,7445,7448],{"class":2980,"line":4914},[2978,7437,5921],{"class":3567},[2978,7439,7440],{"class":3049}," (!",[2978,7442,7401],{"class":3418},[2978,7444,3119],{"class":3049},[2978,7446,7447],{"class":3418},"IsSuccessStatusCode",[2978,7449,3175],{"class":3049},[2978,7451,7452],{"class":2980,"line":4941},[2978,7453,5939],{"class":3049},[2978,7455,7456,7458,7460,7462,7464],{"class":2980,"line":4954},[2978,7457,5944],{"class":3567},[2978,7459,4019],{"class":3418},[2978,7461,3119],{"class":3049},[2978,7463,3605],{"class":2991},[2978,7465,5238],{"class":3049},[2978,7467,7468,7471,7473,7475,7477,7479,7481,7484],{"class":2980,"line":4959},[2978,7469,7470],{"class":2995},"                    $\"External API returned ",[2978,7472,6250],{"class":6249},[2978,7474,7401],{"class":3418},[2978,7476,3119],{"class":6249},[2978,7478,7406],{"class":3418},[2978,7480,6260],{"class":6249},[2978,7482,7483],{"class":2995},"\"",[2978,7485,5062],{"class":3049},[2978,7487,7488,7490,7492,7494],{"class":2980,"line":4964},[2978,7489,6430],{"class":3418},[2978,7491,3669],{"class":3049},[2978,7493,6276],{"class":3418},[2978,7495,3477],{"class":3049},[2978,7497,7498],{"class":2980,"line":6186},[2978,7499,5974],{"class":3049},[2978,7501,7502],{"class":2980,"line":6192},[2978,7503,3022],{"emptyLinePlaceholder":3021},[2978,7505,7506,7508,7510,7512,7514,7517,7519,7522],{"class":2980,"line":6197},[2978,7507,5921],{"class":3567},[2978,7509,5924],{"class":3049},[2978,7511,7420],{"class":3418},[2978,7513,3119],{"class":3049},[2978,7515,7516],{"class":3418},"ElapsedMilliseconds",[2978,7518,3573],{"class":3049},[2978,7520,7521],{"class":3005},"5000",[2978,7523,3175],{"class":3049},[2978,7525,7526],{"class":2980,"line":6214},[2978,7527,5939],{"class":3049},[2978,7529,7530,7532,7534,7536,7538],{"class":2980,"line":6219},[2978,7531,5944],{"class":3567},[2978,7533,4019],{"class":3418},[2978,7535,3119],{"class":3049},[2978,7537,4050],{"class":2991},[2978,7539,5238],{"class":3049},[2978,7541,7542,7545,7547,7549,7551,7553,7555,7558],{"class":2980,"line":6232},[2978,7543,7544],{"class":2995},"                    $\"External API slow: ",[2978,7546,6250],{"class":6249},[2978,7548,7420],{"class":3418},[2978,7550,3119],{"class":6249},[2978,7552,7516],{"class":3418},[2978,7554,6260],{"class":6249},[2978,7556,7557],{"class":2995},"ms\"",[2978,7559,5062],{"class":3049},[2978,7561,7562,7564,7566,7568],{"class":2980,"line":6243},[2978,7563,6430],{"class":3418},[2978,7565,3669],{"class":3049},[2978,7567,6276],{"class":3418},[2978,7569,3477],{"class":3049},[2978,7571,7572],{"class":2980,"line":6268},[2978,7573,5974],{"class":3049},[2978,7575,7576],{"class":2980,"line":6281},[2978,7577,3022],{"emptyLinePlaceholder":3021},[2978,7579,7580,7582,7584,7586,7588],{"class":2980,"line":6286},[2978,7581,6384],{"class":3567},[2978,7583,4019],{"class":3418},[2978,7585,3119],{"class":3049},[2978,7587,3591],{"class":2991},[2978,7589,5238],{"class":3049},[2978,7591,7592,7595,7597,7599,7601,7603,7605,7607],{"class":2980,"line":6291},[2978,7593,7594],{"class":2995},"                $\"External API responsive: ",[2978,7596,6250],{"class":6249},[2978,7598,7420],{"class":3418},[2978,7600,3119],{"class":6249},[2978,7602,7516],{"class":3418},[2978,7604,6260],{"class":6249},[2978,7606,7557],{"class":2995},[2978,7608,5062],{"class":3049},[2978,7610,7611,7613,7615,7617],{"class":2980,"line":6311},[2978,7612,7042],{"class":3418},[2978,7614,3669],{"class":3049},[2978,7616,6276],{"class":3418},[2978,7618,3477],{"class":3049},[2978,7620,7621],{"class":2980,"line":6316},[2978,7622,6442],{"class":3049},[2978,7624,7625,7627,7629,7631,7633],{"class":2980,"line":6329},[2978,7626,6448],{"class":3567},[2978,7628,5924],{"class":3049},[2978,7630,6453],{"class":3498},[2978,7632,6456],{"class":3418},[2978,7634,3175],{"class":3049},[2978,7636,7637],{"class":2980,"line":6340},[2978,7638,5848],{"class":3049},[2978,7640,7641,7643,7645,7647,7649],{"class":2980,"line":6360},[2978,7642,6384],{"class":3567},[2978,7644,4019],{"class":3418},[2978,7646,3119],{"class":3049},[2978,7648,3605],{"class":2991},[2978,7650,5238],{"class":3049},[2978,7652,7653,7656,7658,7660,7662,7665,7667,7669],{"class":2980,"line":6371},[2978,7654,7655],{"class":2995},"                $\"External API unreachable: ",[2978,7657,6250],{"class":6249},[2978,7659,6506],{"class":3418},[2978,7661,3119],{"class":6249},[2978,7663,7664],{"class":3418},"Message",[2978,7666,6260],{"class":6249},[2978,7668,7483],{"class":2995},[2978,7670,5062],{"class":3049},[2978,7672,7673,7676,7678,7680],{"class":2980,"line":6376},[2978,7674,7675],{"class":3418},"                exception",[2978,7677,3669],{"class":3049},[2978,7679,6506],{"class":3418},[2978,7681,3477],{"class":3049},[2978,7683,7684],{"class":2980,"line":6381},[2978,7685,6442],{"class":3049},[2978,7687,7688],{"class":2980,"line":6395},[2978,7689,3617],{"class":3049},[2978,7691,7692],{"class":2980,"line":6407},[2978,7693,3622],{"class":3049},[5142,7695,7697],{"id":7696},"реєстрація-кастомних-чеків","Реєстрація кастомних чеків",[2968,7699,7701],{"className":3409,"code":7700,"language":3411,"meta":2973,"style":2973},"builder.Services.AddHealthChecks()\n    .AddCheck(\"self\", () => HealthCheckResult.Healthy(), tags: new[] { \"live\" })\n    .AddSqlServer(connectionString!, tags: new[] { \"database\", \"ready\" })\n    .AddRedis(redisConnection!, tags: new[] { \"cache\", \"ready\" })\n    .AddCheck\u003CDiskSpaceHealthCheck>(\n        \"disk-space\",\n        failureStatus: HealthStatus.Unhealthy,\n        tags: new[] { \"resources\", \"live\" })\n    .AddCheck\u003CMemoryHealthCheck>(\n        \"memory\",\n        failureStatus: HealthStatus.Degraded,\n        tags: new[] { \"resources\", \"live\" })\n    .AddTypeActivatedCheck\u003CExternalApiHealthCheck>(\n        \"stripe-api\",\n        failureStatus: HealthStatus.Degraded,\n        tags: new[] { \"external\", \"ready\" },\n        args: new object[] { \"https://api.stripe.com/healthcheck\" });\n",[2975,7702,7703,7717,7749,7778,7806,7820,7827,7841,7859,7871,7878,7892,7910,7924,7931,7945,7963],{"__ignoreMap":2973},[2978,7704,7705,7707,7709,7711,7713,7715],{"class":2980,"line":2981},[2978,7706,3419],{"class":3418},[2978,7708,3119],{"class":3049},[2978,7710,3424],{"class":3418},[2978,7712,3119],{"class":3049},[2978,7714,3429],{"class":2991},[2978,7716,3432],{"class":3049},[2978,7718,7719,7721,7723,7725,7727,7729,7731,7733,7735,7737,7739,7741,7743,7745,7747],{"class":2980,"line":2988},[2978,7720,3437],{"class":3049},[2978,7722,4180],{"class":2991},[2978,7724,3443],{"class":3049},[2978,7726,4661],{"class":2995},[2978,7728,4664],{"class":3049},[2978,7730,3524],{"class":3418},[2978,7732,3119],{"class":3049},[2978,7734,3591],{"class":2991},[2978,7736,5217],{"class":3049},[2978,7738,4125],{"class":3418},[2978,7740,3669],{"class":3049},[2978,7742,4130],{"class":3192},[2978,7744,4133],{"class":3049},[2978,7746,4209],{"class":2995},[2978,7748,4144],{"class":3049},[2978,7750,7751,7753,7755,7757,7759,7762,7764,7766,7768,7770,7772,7774,7776],{"class":2980,"line":2999},[2978,7752,3437],{"class":3049},[2978,7754,3440],{"class":2991},[2978,7756,3443],{"class":3049},[2978,7758,3446],{"class":3418},[2978,7760,7761],{"class":3049},"!, ",[2978,7763,4125],{"class":3418},[2978,7765,3669],{"class":3049},[2978,7767,4130],{"class":3192},[2978,7769,4133],{"class":3049},[2978,7771,4136],{"class":2995},[2978,7773,4122],{"class":3049},[2978,7775,4141],{"class":2995},[2978,7777,4144],{"class":3049},[2978,7779,7780,7782,7784,7786,7788,7790,7792,7794,7796,7798,7800,7802,7804],{"class":2980,"line":3018},[2978,7781,3437],{"class":3049},[2978,7783,3455],{"class":2991},[2978,7785,3443],{"class":3049},[2978,7787,3460],{"class":3418},[2978,7789,7761],{"class":3049},[2978,7791,4125],{"class":3418},[2978,7793,3669],{"class":3049},[2978,7795,4130],{"class":3192},[2978,7797,4133],{"class":3049},[2978,7799,4167],{"class":2995},[2978,7801,4122],{"class":3049},[2978,7803,4141],{"class":2995},[2978,7805,4144],{"class":3049},[2978,7807,7808,7810,7812,7814,7817],{"class":2980,"line":3025},[2978,7809,3437],{"class":3049},[2978,7811,4180],{"class":2991},[2978,7813,3521],{"class":3049},[2978,7815,7816],{"class":3498},"DiskSpaceHealthCheck",[2978,7818,7819],{"class":3049},">(\n",[2978,7821,7822,7825],{"class":2980,"line":3031},[2978,7823,7824],{"class":2995},"        \"disk-space\"",[2978,7826,5062],{"class":3049},[2978,7828,7829,7831,7833,7835,7837,7839],{"class":2980,"line":3040},[2978,7830,5266],{"class":3418},[2978,7832,3669],{"class":3049},[2978,7834,5271],{"class":3418},[2978,7836,3119],{"class":3049},[2978,7838,3605],{"class":3418},[2978,7840,5062],{"class":3049},[2978,7842,7843,7845,7847,7849,7851,7853,7855,7857],{"class":2980,"line":3059},[2978,7844,5282],{"class":3418},[2978,7846,3669],{"class":3049},[2978,7848,4130],{"class":3192},[2978,7850,4133],{"class":3049},[2978,7852,4204],{"class":2995},[2978,7854,4122],{"class":3049},[2978,7856,4209],{"class":2995},[2978,7858,4144],{"class":3049},[2978,7860,7861,7863,7865,7867,7869],{"class":2980,"line":3076},[2978,7862,3437],{"class":3049},[2978,7864,4180],{"class":2991},[2978,7866,3521],{"class":3049},[2978,7868,4185],{"class":3498},[2978,7870,7819],{"class":3049},[2978,7872,7873,7876],{"class":2980,"line":3081},[2978,7874,7875],{"class":2995},"        \"memory\"",[2978,7877,5062],{"class":3049},[2978,7879,7880,7882,7884,7886,7888,7890],{"class":2980,"line":3246},[2978,7881,5266],{"class":3418},[2978,7883,3669],{"class":3049},[2978,7885,5271],{"class":3418},[2978,7887,3119],{"class":3049},[2978,7889,4050],{"class":3418},[2978,7891,5062],{"class":3049},[2978,7893,7894,7896,7898,7900,7902,7904,7906,7908],{"class":2980,"line":3256},[2978,7895,5282],{"class":3418},[2978,7897,3669],{"class":3049},[2978,7899,4130],{"class":3192},[2978,7901,4133],{"class":3049},[2978,7903,4204],{"class":2995},[2978,7905,4122],{"class":3049},[2978,7907,4209],{"class":2995},[2978,7909,4144],{"class":3049},[2978,7911,7912,7914,7917,7919,7922],{"class":2980,"line":3261},[2978,7913,3437],{"class":3049},[2978,7915,7916],{"class":2991},"AddTypeActivatedCheck",[2978,7918,3521],{"class":3049},[2978,7920,7921],{"class":3498},"ExternalApiHealthCheck",[2978,7923,7819],{"class":3049},[2978,7925,7926,7929],{"class":2980,"line":3267},[2978,7927,7928],{"class":2995},"        \"stripe-api\"",[2978,7930,5062],{"class":3049},[2978,7932,7933,7935,7937,7939,7941,7943],{"class":2980,"line":3276},[2978,7934,5266],{"class":3418},[2978,7936,3669],{"class":3049},[2978,7938,5271],{"class":3418},[2978,7940,3119],{"class":3049},[2978,7942,4050],{"class":3418},[2978,7944,5062],{"class":3049},[2978,7946,7947,7949,7951,7953,7955,7957,7959,7961],{"class":2980,"line":3836},[2978,7948,5282],{"class":3418},[2978,7950,3669],{"class":3049},[2978,7952,4130],{"class":3192},[2978,7954,4133],{"class":3049},[2978,7956,5608],{"class":2995},[2978,7958,4122],{"class":3049},[2978,7960,4141],{"class":2995},[2978,7962,5297],{"class":3049},[2978,7964,7965,7968,7970,7972,7975,7977,7979],{"class":2980,"line":4741},[2978,7966,7967],{"class":3418},"        args",[2978,7969,3669],{"class":3049},[2978,7971,4130],{"class":3192},[2978,7973,7974],{"class":3192}," object",[2978,7976,4133],{"class":3049},[2978,7978,5568],{"class":2995},[2978,7980,4212],{"class":3049},[2964,7982,7983],{},[3088,7984,4978],{},[4980,7986,7987,7995,8003,8011],{},[3095,7988,7989,7994],{},[3088,7990,7991],{},[2975,7992,7993],{},"AddCheck\u003CT>"," — для чеків без параметрів конструктора",[3095,7996,7997,8002],{},[3088,7998,7999],{},[2975,8000,8001],{},"AddTypeActivatedCheck\u003CT>"," — для чеків з параметрами (DI + args)",[3095,8004,8005,8010],{},[3088,8006,8007],{},[2975,8008,8009],{},"failureStatus"," — який статус при помилці",[3095,8012,8013,8017],{},[3088,8014,8015],{},[2975,8016,4125],{}," — для фільтрації (live/ready)",[3735,8019],{},[3351,8021,8023],{"id":8022},"крок-5-health-check-ui","Крок 5: Health Check UI",[2964,8025,8026],{},"Health Check UI надає інтерактивний dashboard для моніторингу:",[5142,8028,8030],{"id":8029},"конфігурація","Конфігурація",[2968,8032,8034],{"className":3409,"code":8033,"language":3411,"meta":2973,"style":2973},"// Program.cs\nbuilder.Services\n    .AddHealthChecksUI(options =>\n    {\n        options.SetEvaluationTimeInSeconds(10); // Перевірка кожні 10 секунд\n        options.MaximumHistoryEntriesPerEndpoint(50); // Зберігати 50 записів історії\n        options.AddHealthCheckEndpoint(\"API Health\", \"/health\");\n    })\n    .AddInMemoryStorage(); // Зберігання історії у пам'яті\n\n// ... після app.Build()\n\napp.MapHealthChecksUI(options =>\n{\n    options.UIPath = \"/health-ui\"; // UI доступний на /health-ui\n    options.ApiPath = \"/health-ui-api\"; // API для UI\n});\n",[2975,8035,8036,8041,8050,8065,8069,8089,8108,8128,8133,8146,8150,8155,8159,8174,8178,8199,8218],{"__ignoreMap":2973},[2978,8037,8038],{"class":2980,"line":2981},[2978,8039,8040],{"class":2984},"// Program.cs\n",[2978,8042,8043,8045,8047],{"class":2980,"line":2988},[2978,8044,3419],{"class":3418},[2978,8046,3119],{"class":3049},[2978,8048,8049],{"class":3418},"Services\n",[2978,8051,8052,8054,8057,8059,8062],{"class":2980,"line":2999},[2978,8053,3437],{"class":3049},[2978,8055,8056],{"class":2991},"AddHealthChecksUI",[2978,8058,3443],{"class":3049},[2978,8060,8061],{"class":3418},"options",[2978,8063,8064],{"class":3049}," =>\n",[2978,8066,8067],{"class":2980,"line":3018},[2978,8068,3545],{"class":3049},[2978,8070,8071,8074,8076,8079,8081,8083,8086],{"class":2980,"line":3025},[2978,8072,8073],{"class":3418},"        options",[2978,8075,3119],{"class":3049},[2978,8077,8078],{"class":2991},"SetEvaluationTimeInSeconds",[2978,8080,3443],{"class":3049},[2978,8082,5631],{"class":3005},[2978,8084,8085],{"class":3049},"); ",[2978,8087,8088],{"class":2984},"// Перевірка кожні 10 секунд\n",[2978,8090,8091,8093,8095,8098,8100,8103,8105],{"class":2980,"line":3031},[2978,8092,8073],{"class":3418},[2978,8094,3119],{"class":3049},[2978,8096,8097],{"class":2991},"MaximumHistoryEntriesPerEndpoint",[2978,8099,3443],{"class":3049},[2978,8101,8102],{"class":3005},"50",[2978,8104,8085],{"class":3049},[2978,8106,8107],{"class":2984},"// Зберігати 50 записів історії\n",[2978,8109,8110,8112,8114,8117,8119,8122,8124,8126],{"class":2980,"line":3040},[2978,8111,8073],{"class":3418},[2978,8113,3119],{"class":3049},[2978,8115,8116],{"class":2991},"AddHealthCheckEndpoint",[2978,8118,3443],{"class":3049},[2978,8120,8121],{"class":2995},"\"API Health\"",[2978,8123,4122],{"class":3049},[2978,8125,4775],{"class":2995},[2978,8127,3477],{"class":3049},[2978,8129,8130],{"class":2980,"line":3059},[2978,8131,8132],{"class":3049},"    })\n",[2978,8134,8135,8137,8140,8143],{"class":2980,"line":3076},[2978,8136,3437],{"class":3049},[2978,8138,8139],{"class":2991},"AddInMemoryStorage",[2978,8141,8142],{"class":3049},"(); ",[2978,8144,8145],{"class":2984},"// Зберігання історії у пам'яті\n",[2978,8147,8148],{"class":2980,"line":3081},[2978,8149,3022],{"emptyLinePlaceholder":3021},[2978,8151,8152],{"class":2980,"line":3246},[2978,8153,8154],{"class":2984},"// ... після app.Build()\n",[2978,8156,8157],{"class":2980,"line":3256},[2978,8158,3022],{"emptyLinePlaceholder":3021},[2978,8160,8161,8163,8165,8168,8170,8172],{"class":2980,"line":3261},[2978,8162,4232],{"class":3418},[2978,8164,3119],{"class":3049},[2978,8166,8167],{"class":2991},"MapHealthChecksUI",[2978,8169,3443],{"class":3049},[2978,8171,8061],{"class":3418},[2978,8173,8064],{"class":3049},[2978,8175,8176],{"class":2980,"line":3267},[2978,8177,3510],{"class":3049},[2978,8179,8180,8183,8185,8188,8190,8193,8196],{"class":2980,"line":3276},[2978,8181,8182],{"class":3418},"    options",[2978,8184,3119],{"class":3049},[2978,8186,8187],{"class":3418},"UIPath",[2978,8189,3556],{"class":3049},[2978,8191,8192],{"class":2995},"\"/health-ui\"",[2978,8194,8195],{"class":3049},"; ",[2978,8197,8198],{"class":2984},"// UI доступний на /health-ui\n",[2978,8200,8201,8203,8205,8208,8210,8213,8215],{"class":2980,"line":3836},[2978,8202,8182],{"class":3418},[2978,8204,3119],{"class":3049},[2978,8206,8207],{"class":3418},"ApiPath",[2978,8209,3556],{"class":3049},[2978,8211,8212],{"class":2995},"\"/health-ui-api\"",[2978,8214,8195],{"class":3049},[2978,8216,8217],{"class":2984},"// API для UI\n",[2978,8219,8220],{"class":2980,"line":4741},[2978,8221,4289],{"class":3049},[2964,8223,8224,8227,8228,8231],{},[3088,8225,8226],{},"Результат:"," Відкрийте ",[2975,8229,8230],{},"https://localhost:5001/health-ui"," для інтерактивного dashboard.",[3735,8233],{},[3351,8235,8237],{"id":8236},"крок-6-kubernetes-integration","Крок 6: Kubernetes Integration",[5142,8239,8241],{"id":8240},"deployment-yaml","Deployment YAML",[2968,8243,8245],{"className":3641,"code":8244,"language":3643,"meta":2973,"style":2973},"apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: ecommerce-api\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: ecommerce-api\n  template:\n    metadata:\n      labels:\n        app: ecommerce-api\n    spec:\n      containers:\n      - name: api\n        image: ecommerce-api:latest\n        ports:\n        - containerPort: 80\n        \n        # Startup Probe - чи завершився запуск?\n        startupProbe:\n          httpGet:\n            path: /health/startup\n            port: 80\n          initialDelaySeconds: 0\n          periodSeconds: 5\n          timeoutSeconds: 3\n          failureThreshold: 30 # 30 * 5s = 150s максимум на старт\n        \n        # Liveness Probe - чи живий процес?\n        livenessProbe:\n          httpGet:\n            path: /health/live\n            port: 80\n          initialDelaySeconds: 0\n          periodSeconds: 10\n          timeoutSeconds: 3\n          failureThreshold: 3 # 3 невдалі спроби → restart\n        \n        # Readiness Probe - чи готовий приймати трафік?\n        readinessProbe:\n          httpGet:\n            path: /health/ready\n            port: 80\n          initialDelaySeconds: 0\n          periodSeconds: 5\n          timeoutSeconds: 3\n          failureThreshold: 3 # 3 невдалі спроби → remove from service\n",[2975,8246,8247,8257,8267,8274,8284,8291,8301,8308,8315,8324,8331,8338,8345,8354,8361,8368,8381,8391,8398,8410,8415,8420,8427,8434,8444,8453,8463,8473,8482,8495,8499,8504,8511,8517,8525,8533,8541,8550,8558,8569,8573,8578,8585,8591,8599,8607,8615,8623,8631],{"__ignoreMap":2973},[2978,8248,8249,8252,8254],{"class":2980,"line":2981},[2978,8250,8251],{"class":3650},"apiVersion",[2978,8253,3669],{"class":3049},[2978,8255,8256],{"class":3672},"apps/v1\n",[2978,8258,8259,8262,8264],{"class":2980,"line":2988},[2978,8260,8261],{"class":3650},"kind",[2978,8263,3669],{"class":3049},[2978,8265,8266],{"class":3672},"Deployment\n",[2978,8268,8269,8272],{"class":2980,"line":2999},[2978,8270,8271],{"class":3650},"metadata",[2978,8273,3654],{"class":3049},[2978,8275,8276,8279,8281],{"class":2980,"line":3018},[2978,8277,8278],{"class":3650},"  name",[2978,8280,3669],{"class":3049},[2978,8282,8283],{"class":3672},"ecommerce-api\n",[2978,8285,8286,8289],{"class":2980,"line":3025},[2978,8287,8288],{"class":3650},"spec",[2978,8290,3654],{"class":3049},[2978,8292,8293,8296,8298],{"class":2980,"line":3031},[2978,8294,8295],{"class":3650},"  replicas",[2978,8297,3669],{"class":3049},[2978,8299,8300],{"class":3005},"3\n",[2978,8302,8303,8306],{"class":2980,"line":3040},[2978,8304,8305],{"class":3650},"  selector",[2978,8307,3654],{"class":3049},[2978,8309,8310,8313],{"class":2980,"line":3059},[2978,8311,8312],{"class":3650},"    matchLabels",[2978,8314,3654],{"class":3049},[2978,8316,8317,8320,8322],{"class":2980,"line":3076},[2978,8318,8319],{"class":3650},"      app",[2978,8321,3669],{"class":3049},[2978,8323,8283],{"class":3672},[2978,8325,8326,8329],{"class":2980,"line":3081},[2978,8327,8328],{"class":3650},"  template",[2978,8330,3654],{"class":3049},[2978,8332,8333,8336],{"class":2980,"line":3246},[2978,8334,8335],{"class":3650},"    metadata",[2978,8337,3654],{"class":3049},[2978,8339,8340,8343],{"class":2980,"line":3256},[2978,8341,8342],{"class":3650},"      labels",[2978,8344,3654],{"class":3049},[2978,8346,8347,8350,8352],{"class":2980,"line":3261},[2978,8348,8349],{"class":3650},"        app",[2978,8351,3669],{"class":3049},[2978,8353,8283],{"class":3672},[2978,8355,8356,8359],{"class":2980,"line":3267},[2978,8357,8358],{"class":3650},"    spec",[2978,8360,3654],{"class":3049},[2978,8362,8363,8366],{"class":2980,"line":3276},[2978,8364,8365],{"class":3650},"      containers",[2978,8367,3654],{"class":3049},[2978,8369,8370,8373,8376,8378],{"class":2980,"line":3836},[2978,8371,8372],{"class":3049},"      - ",[2978,8374,8375],{"class":3650},"name",[2978,8377,3669],{"class":3049},[2978,8379,8380],{"class":3672},"api\n",[2978,8382,8383,8386,8388],{"class":2980,"line":4741},[2978,8384,8385],{"class":3650},"        image",[2978,8387,3669],{"class":3049},[2978,8389,8390],{"class":3672},"ecommerce-api:latest\n",[2978,8392,8393,8396],{"class":2980,"line":4753},[2978,8394,8395],{"class":3650},"        ports",[2978,8397,3654],{"class":3049},[2978,8399,8400,8403,8406,8408],{"class":2980,"line":4758},[2978,8401,8402],{"class":3049},"        - ",[2978,8404,8405],{"class":3650},"containerPort",[2978,8407,3669],{"class":3049},[2978,8409,3683],{"class":3005},[2978,8411,8412],{"class":2980,"line":4764},[2978,8413,8414],{"class":3049},"        \n",[2978,8416,8417],{"class":2980,"line":4784},[2978,8418,8419],{"class":2984},"        # Startup Probe - чи завершився запуск?\n",[2978,8421,8422,8425],{"class":2980,"line":4789},[2978,8423,8424],{"class":3650},"        startupProbe",[2978,8426,3654],{"class":3049},[2978,8428,8429,8432],{"class":2980,"line":4805},[2978,8430,8431],{"class":3650},"          httpGet",[2978,8433,3654],{"class":3049},[2978,8435,8436,8439,8441],{"class":2980,"line":4810},[2978,8437,8438],{"class":3650},"            path",[2978,8440,3669],{"class":3049},[2978,8442,8443],{"class":3672},"/health/startup\n",[2978,8445,8446,8449,8451],{"class":2980,"line":4815},[2978,8447,8448],{"class":3650},"            port",[2978,8450,3669],{"class":3049},[2978,8452,3683],{"class":3005},[2978,8454,8455,8458,8460],{"class":2980,"line":4834},[2978,8456,8457],{"class":3650},"          initialDelaySeconds",[2978,8459,3669],{"class":3049},[2978,8461,8462],{"class":3005},"0\n",[2978,8464,8465,8468,8470],{"class":2980,"line":4839},[2978,8466,8467],{"class":3650},"          periodSeconds",[2978,8469,3669],{"class":3049},[2978,8471,8472],{"class":3005},"5\n",[2978,8474,8475,8478,8480],{"class":2980,"line":4867},[2978,8476,8477],{"class":3650},"          timeoutSeconds",[2978,8479,3669],{"class":3049},[2978,8481,8300],{"class":3005},[2978,8483,8484,8487,8489,8492],{"class":2980,"line":4880},[2978,8485,8486],{"class":3650},"          failureThreshold",[2978,8488,3669],{"class":3049},[2978,8490,8491],{"class":3005},"30",[2978,8493,8494],{"class":2984}," # 30 * 5s = 150s максимум на старт\n",[2978,8496,8497],{"class":2980,"line":4885},[2978,8498,8414],{"class":3049},[2978,8500,8501],{"class":2980,"line":4890},[2978,8502,8503],{"class":2984},"        # Liveness Probe - чи живий процес?\n",[2978,8505,8506,8509],{"class":2980,"line":4909},[2978,8507,8508],{"class":3650},"        livenessProbe",[2978,8510,3654],{"class":3049},[2978,8512,8513,8515],{"class":2980,"line":4914},[2978,8514,8431],{"class":3650},[2978,8516,3654],{"class":3049},[2978,8518,8519,8521,8523],{"class":2980,"line":4941},[2978,8520,8438],{"class":3650},[2978,8522,3669],{"class":3049},[2978,8524,3673],{"class":3672},[2978,8526,8527,8529,8531],{"class":2980,"line":4954},[2978,8528,8448],{"class":3650},[2978,8530,3669],{"class":3049},[2978,8532,3683],{"class":3005},[2978,8534,8535,8537,8539],{"class":2980,"line":4959},[2978,8536,8457],{"class":3650},[2978,8538,3669],{"class":3049},[2978,8540,8462],{"class":3005},[2978,8542,8543,8545,8547],{"class":2980,"line":4964},[2978,8544,8467],{"class":3650},[2978,8546,3669],{"class":3049},[2978,8548,8549],{"class":3005},"10\n",[2978,8551,8552,8554,8556],{"class":2980,"line":6186},[2978,8553,8477],{"class":3650},[2978,8555,3669],{"class":3049},[2978,8557,8300],{"class":3005},[2978,8559,8560,8562,8564,8566],{"class":2980,"line":6192},[2978,8561,8486],{"class":3650},[2978,8563,3669],{"class":3049},[2978,8565,5480],{"class":3005},[2978,8567,8568],{"class":2984}," # 3 невдалі спроби → restart\n",[2978,8570,8571],{"class":2980,"line":6197},[2978,8572,8414],{"class":3049},[2978,8574,8575],{"class":2980,"line":6214},[2978,8576,8577],{"class":2984},"        # Readiness Probe - чи готовий приймати трафік?\n",[2978,8579,8580,8583],{"class":2980,"line":6219},[2978,8581,8582],{"class":3650},"        readinessProbe",[2978,8584,3654],{"class":3049},[2978,8586,8587,8589],{"class":2980,"line":6232},[2978,8588,8431],{"class":3650},[2978,8590,3654],{"class":3049},[2978,8592,8593,8595,8597],{"class":2980,"line":6243},[2978,8594,8438],{"class":3650},[2978,8596,3669],{"class":3049},[2978,8598,3705],{"class":3672},[2978,8600,8601,8603,8605],{"class":2980,"line":6268},[2978,8602,8448],{"class":3650},[2978,8604,3669],{"class":3049},[2978,8606,3683],{"class":3005},[2978,8608,8609,8611,8613],{"class":2980,"line":6281},[2978,8610,8457],{"class":3650},[2978,8612,3669],{"class":3049},[2978,8614,8462],{"class":3005},[2978,8616,8617,8619,8621],{"class":2980,"line":6286},[2978,8618,8467],{"class":3650},[2978,8620,3669],{"class":3049},[2978,8622,8472],{"class":3005},[2978,8624,8625,8627,8629],{"class":2980,"line":6291},[2978,8626,8477],{"class":3650},[2978,8628,3669],{"class":3049},[2978,8630,8300],{"class":3005},[2978,8632,8633,8635,8637,8639],{"class":2980,"line":6311},[2978,8634,8486],{"class":3650},[2978,8636,3669],{"class":3049},[2978,8638,5480],{"class":3005},[2978,8640,8641],{"class":2984}," # 3 невдалі спроби → remove from service\n",[5142,8643,8645],{"id":8644},"endpoints-для-kubernetes","Endpoints для Kubernetes",[2968,8647,8649],{"className":3409,"code":8648,"language":3411,"meta":2973,"style":2973},"// Startup probe - перевіряє тільки базові речі\napp.MapHealthChecks(\"/health/startup\", new HealthCheckOptions\n{\n    Predicate = check => check.Tags.Contains(\"startup\"),\n    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse\n});\n\n// Liveness probe - перевіряє, чи процес не \"завис\"\napp.MapHealthChecks(\"/health/live\", new HealthCheckOptions\n{\n    Predicate = check => check.Tags.Contains(\"live\"),\n    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse\n});\n\n// Readiness probe - перевіряє всі залежності\napp.MapHealthChecks(\"/health/ready\", new HealthCheckOptions\n{\n    Predicate = check => check.Tags.Contains(\"ready\"),\n    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse\n});\n",[2975,8650,8651,8656,8675,8679,8706,8718,8722,8726,8731,8749,8753,8779,8791,8795,8799,8804,8822,8826,8852,8864],{"__ignoreMap":2973},[2978,8652,8653],{"class":2980,"line":2981},[2978,8654,8655],{"class":2984},"// Startup probe - перевіряє тільки базові речі\n",[2978,8657,8658,8660,8662,8664,8666,8669,8671,8673],{"class":2980,"line":2988},[2978,8659,4232],{"class":3418},[2978,8661,3119],{"class":3049},[2978,8663,4237],{"class":2991},[2978,8665,3443],{"class":3049},[2978,8667,8668],{"class":2995},"\"/health/startup\"",[2978,8670,4122],{"class":3049},[2978,8672,4130],{"class":3192},[2978,8674,4249],{"class":3498},[2978,8676,8677],{"class":2980,"line":2999},[2978,8678,3510],{"class":3049},[2978,8680,8681,8683,8685,8687,8689,8691,8693,8695,8697,8699,8701,8704],{"class":2980,"line":3018},[2978,8682,4258],{"class":3418},[2978,8684,3556],{"class":3049},[2978,8686,4263],{"class":3418},[2978,8688,4266],{"class":3049},[2978,8690,4263],{"class":3418},[2978,8692,3119],{"class":3049},[2978,8694,4273],{"class":3418},[2978,8696,3119],{"class":3049},[2978,8698,4278],{"class":2991},[2978,8700,3443],{"class":3049},[2978,8702,8703],{"class":2995},"\"startup\"",[2978,8705,4864],{"class":3049},[2978,8707,8708,8710,8712,8714,8716],{"class":2980,"line":3025},[2978,8709,4792],{"class":3418},[2978,8711,3556],{"class":3049},[2978,8713,4797],{"class":3418},[2978,8715,3119],{"class":3049},[2978,8717,4802],{"class":3418},[2978,8719,8720],{"class":2980,"line":3031},[2978,8721,4289],{"class":3049},[2978,8723,8724],{"class":2980,"line":3040},[2978,8725,3022],{"emptyLinePlaceholder":3021},[2978,8727,8728],{"class":2980,"line":3059},[2978,8729,8730],{"class":2984},"// Liveness probe - перевіряє, чи процес не \"завис\"\n",[2978,8732,8733,8735,8737,8739,8741,8743,8745,8747],{"class":2980,"line":3076},[2978,8734,4232],{"class":3418},[2978,8736,3119],{"class":3049},[2978,8738,4237],{"class":2991},[2978,8740,3443],{"class":3049},[2978,8742,4311],{"class":2995},[2978,8744,4122],{"class":3049},[2978,8746,4130],{"class":3192},[2978,8748,4249],{"class":3498},[2978,8750,8751],{"class":2980,"line":3081},[2978,8752,3510],{"class":3049},[2978,8754,8755,8757,8759,8761,8763,8765,8767,8769,8771,8773,8775,8777],{"class":2980,"line":3246},[2978,8756,4258],{"class":3418},[2978,8758,3556],{"class":3049},[2978,8760,4263],{"class":3418},[2978,8762,4266],{"class":3049},[2978,8764,4263],{"class":3418},[2978,8766,3119],{"class":3049},[2978,8768,4273],{"class":3418},[2978,8770,3119],{"class":3049},[2978,8772,4278],{"class":2991},[2978,8774,3443],{"class":3049},[2978,8776,4209],{"class":2995},[2978,8778,4864],{"class":3049},[2978,8780,8781,8783,8785,8787,8789],{"class":2980,"line":3256},[2978,8782,4792],{"class":3418},[2978,8784,3556],{"class":3049},[2978,8786,4797],{"class":3418},[2978,8788,3119],{"class":3049},[2978,8790,4802],{"class":3418},[2978,8792,8793],{"class":2980,"line":3261},[2978,8794,4289],{"class":3049},[2978,8796,8797],{"class":2980,"line":3267},[2978,8798,3022],{"emptyLinePlaceholder":3021},[2978,8800,8801],{"class":2980,"line":3276},[2978,8802,8803],{"class":2984},"// Readiness probe - перевіряє всі залежності\n",[2978,8805,8806,8808,8810,8812,8814,8816,8818,8820],{"class":2980,"line":3836},[2978,8807,4232],{"class":3418},[2978,8809,3119],{"class":3049},[2978,8811,4237],{"class":2991},[2978,8813,3443],{"class":3049},[2978,8815,4242],{"class":2995},[2978,8817,4122],{"class":3049},[2978,8819,4130],{"class":3192},[2978,8821,4249],{"class":3498},[2978,8823,8824],{"class":2980,"line":4741},[2978,8825,3510],{"class":3049},[2978,8827,8828,8830,8832,8834,8836,8838,8840,8842,8844,8846,8848,8850],{"class":2980,"line":4753},[2978,8829,4258],{"class":3418},[2978,8831,3556],{"class":3049},[2978,8833,4263],{"class":3418},[2978,8835,4266],{"class":3049},[2978,8837,4263],{"class":3418},[2978,8839,3119],{"class":3049},[2978,8841,4273],{"class":3418},[2978,8843,3119],{"class":3049},[2978,8845,4278],{"class":2991},[2978,8847,3443],{"class":3049},[2978,8849,4141],{"class":2995},[2978,8851,4864],{"class":3049},[2978,8853,8854,8856,8858,8860,8862],{"class":2980,"line":4758},[2978,8855,4792],{"class":3418},[2978,8857,3556],{"class":3049},[2978,8859,4797],{"class":3418},[2978,8861,3119],{"class":3049},[2978,8863,4802],{"class":3418},[2978,8865,8866],{"class":2980,"line":4764},[2978,8867,4289],{"class":3049},[2964,8869,8870],{},[3088,8871,8872],{},"Реєстрація чеків з правильними tags:",[2968,8874,8876],{"className":3409,"code":8875,"language":3411,"meta":2973,"style":2973},"builder.Services.AddHealthChecks()\n    // Startup - тільки критичні речі для старту\n    .AddCheck(\"self\", () => HealthCheckResult.Healthy(), \n        tags: new[] { \"startup\", \"live\" })\n    \n    // Live - перевірка deadlock, infinite loops\n    .AddCheck\u003CMemoryHealthCheck>(\"memory\", \n        tags: new[] { \"live\" })\n    .AddCheck\u003CDiskSpaceHealthCheck>(\"disk-space\", \n        tags: new[] { \"live\" })\n    \n    // Ready - всі залежності\n    .AddSqlServer(connectionString!, \n        tags: new[] { \"database\", \"ready\" })\n    .AddRedis(redisConnection!, \n        tags: new[] { \"cache\", \"ready\" })\n    .AddUrlGroup(new Uri(\"https://api.stripe.com/healthcheck\"), \n        tags: new[] { \"external\", \"ready\" });\n",[2975,8877,8878,8892,8897,8918,8936,8940,8945,8962,8976,8993,9007,9011,9016,9029,9047,9059,9077,9096],{"__ignoreMap":2973},[2978,8879,8880,8882,8884,8886,8888,8890],{"class":2980,"line":2981},[2978,8881,3419],{"class":3418},[2978,8883,3119],{"class":3049},[2978,8885,3424],{"class":3418},[2978,8887,3119],{"class":3049},[2978,8889,3429],{"class":2991},[2978,8891,3432],{"class":3049},[2978,8893,8894],{"class":2980,"line":2988},[2978,8895,8896],{"class":2984},"    // Startup - тільки критичні речі для старту\n",[2978,8898,8899,8901,8903,8905,8907,8909,8911,8913,8915],{"class":2980,"line":2999},[2978,8900,3437],{"class":3049},[2978,8902,4180],{"class":2991},[2978,8904,3443],{"class":3049},[2978,8906,4661],{"class":2995},[2978,8908,4664],{"class":3049},[2978,8910,3524],{"class":3418},[2978,8912,3119],{"class":3049},[2978,8914,3591],{"class":2991},[2978,8916,8917],{"class":3049},"(), \n",[2978,8919,8920,8922,8924,8926,8928,8930,8932,8934],{"class":2980,"line":3018},[2978,8921,5282],{"class":3418},[2978,8923,3669],{"class":3049},[2978,8925,4130],{"class":3192},[2978,8927,4133],{"class":3049},[2978,8929,8703],{"class":2995},[2978,8931,4122],{"class":3049},[2978,8933,4209],{"class":2995},[2978,8935,4144],{"class":3049},[2978,8937,8938],{"class":2980,"line":3025},[2978,8939,3803],{"class":3049},[2978,8941,8942],{"class":2980,"line":3031},[2978,8943,8944],{"class":2984},"    // Live - перевірка deadlock, infinite loops\n",[2978,8946,8947,8949,8951,8953,8955,8957,8959],{"class":2980,"line":3040},[2978,8948,3437],{"class":3049},[2978,8950,4180],{"class":2991},[2978,8952,3521],{"class":3049},[2978,8954,4185],{"class":3498},[2978,8956,4188],{"class":3049},[2978,8958,4191],{"class":2995},[2978,8960,8961],{"class":3049},", \n",[2978,8963,8964,8966,8968,8970,8972,8974],{"class":2980,"line":3059},[2978,8965,5282],{"class":3418},[2978,8967,3669],{"class":3049},[2978,8969,4130],{"class":3192},[2978,8971,4133],{"class":3049},[2978,8973,4209],{"class":2995},[2978,8975,4144],{"class":3049},[2978,8977,8978,8980,8982,8984,8986,8988,8991],{"class":2980,"line":3076},[2978,8979,3437],{"class":3049},[2978,8981,4180],{"class":2991},[2978,8983,3521],{"class":3049},[2978,8985,7816],{"class":3498},[2978,8987,4188],{"class":3049},[2978,8989,8990],{"class":2995},"\"disk-space\"",[2978,8992,8961],{"class":3049},[2978,8994,8995,8997,8999,9001,9003,9005],{"class":2980,"line":3081},[2978,8996,5282],{"class":3418},[2978,8998,3669],{"class":3049},[2978,9000,4130],{"class":3192},[2978,9002,4133],{"class":3049},[2978,9004,4209],{"class":2995},[2978,9006,4144],{"class":3049},[2978,9008,9009],{"class":2980,"line":3246},[2978,9010,3803],{"class":3049},[2978,9012,9013],{"class":2980,"line":3256},[2978,9014,9015],{"class":2984},"    // Ready - всі залежності\n",[2978,9017,9018,9020,9022,9024,9026],{"class":2980,"line":3261},[2978,9019,3437],{"class":3049},[2978,9021,3440],{"class":2991},[2978,9023,3443],{"class":3049},[2978,9025,3446],{"class":3418},[2978,9027,9028],{"class":3049},"!, \n",[2978,9030,9031,9033,9035,9037,9039,9041,9043,9045],{"class":2980,"line":3267},[2978,9032,5282],{"class":3418},[2978,9034,3669],{"class":3049},[2978,9036,4130],{"class":3192},[2978,9038,4133],{"class":3049},[2978,9040,4136],{"class":2995},[2978,9042,4122],{"class":3049},[2978,9044,4141],{"class":2995},[2978,9046,4144],{"class":3049},[2978,9048,9049,9051,9053,9055,9057],{"class":2980,"line":3276},[2978,9050,3437],{"class":3049},[2978,9052,3455],{"class":2991},[2978,9054,3443],{"class":3049},[2978,9056,3460],{"class":3418},[2978,9058,9028],{"class":3049},[2978,9060,9061,9063,9065,9067,9069,9071,9073,9075],{"class":2980,"line":3836},[2978,9062,5282],{"class":3418},[2978,9064,3669],{"class":3049},[2978,9066,4130],{"class":3192},[2978,9068,4133],{"class":3049},[2978,9070,4167],{"class":2995},[2978,9072,4122],{"class":3049},[2978,9074,4141],{"class":2995},[2978,9076,4144],{"class":3049},[2978,9078,9079,9081,9083,9085,9087,9089,9091,9093],{"class":2980,"line":4741},[2978,9080,3437],{"class":3049},[2978,9082,5549],{"class":2991},[2978,9084,3443],{"class":3049},[2978,9086,4130],{"class":3192},[2978,9088,5563],{"class":3498},[2978,9090,3443],{"class":3049},[2978,9092,5568],{"class":2995},[2978,9094,9095],{"class":3049},"), \n",[2978,9097,9098,9100,9102,9104,9106,9108,9110,9112],{"class":2980,"line":4753},[2978,9099,5282],{"class":3418},[2978,9101,3669],{"class":3049},[2978,9103,4130],{"class":3192},[2978,9105,4133],{"class":3049},[2978,9107,5608],{"class":2995},[2978,9109,4122],{"class":3049},[2978,9111,4141],{"class":2995},[2978,9113,4212],{"class":3049},[3735,9115],{},[2959,9117,9119],{"id":9118},"просунуті-техніки","Просунуті техніки",[3351,9121,9123],{"id":9122},"_1-health-check-publisher","1. Health Check Publisher",[2964,9125,9126],{},"Автоматична публікація результатів у зовнішні системи:",[2968,9128,9130],{"className":3409,"code":9129,"language":3411,"meta":2973,"style":2973},"public class CloudWatchHealthCheckPublisher : IHealthCheckPublisher\n{\n    private readonly ILogger\u003CCloudWatchHealthCheckPublisher> _logger;\n\n    public CloudWatchHealthCheckPublisher(ILogger\u003CCloudWatchHealthCheckPublisher> logger)\n    {\n        _logger = logger;\n    }\n\n    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)\n    {\n        _logger.LogInformation(\n            \"Health Check Status: {Status}, Duration: {Duration}ms\",\n            report.Status,\n            report.TotalDuration.TotalMilliseconds);\n\n        // Відправка метрик у CloudWatch, Prometheus, тощо\n        foreach (var entry in report.Entries)\n        {\n            _logger.LogInformation(\n                \"  {Name}: {Status} ({Duration}ms)\",\n                entry.Key,\n                entry.Value.Status,\n                entry.Value.Duration.TotalMilliseconds);\n        }\n\n        return Task.CompletedTask;\n    }\n}\n",[2975,9131,9132,9146,9150,9171,9175,9197,9201,9212,9216,9220,9246,9250,9261,9268,9280,9296,9300,9305,9329,9333,9344,9351,9363,9378,9397,9401,9405,9418,9422],{"__ignoreMap":2973},[2978,9133,9134,9136,9138,9141,9143],{"class":2980,"line":2981},[2978,9135,3492],{"class":3192},[2978,9137,3495],{"class":3192},[2978,9139,9140],{"class":3498}," CloudWatchHealthCheckPublisher",[2978,9142,3502],{"class":3049},[2978,9144,9145],{"class":3498},"IHealthCheckPublisher\n",[2978,9147,9148],{"class":2980,"line":2988},[2978,9149,3510],{"class":3049},[2978,9151,9152,9154,9156,9159,9161,9164,9166,9169],{"class":2980,"line":2999},[2978,9153,5731],{"class":3192},[2978,9155,5734],{"class":3192},[2978,9157,9158],{"class":3498}," ILogger",[2978,9160,3521],{"class":3049},[2978,9162,9163],{"class":3498},"CloudWatchHealthCheckPublisher",[2978,9165,3527],{"class":3049},[2978,9167,9168],{"class":3418},"_logger",[2978,9170,4539],{"class":3049},[2978,9172,9173],{"class":2980,"line":3018},[2978,9174,3022],{"emptyLinePlaceholder":3021},[2978,9176,9177,9179,9181,9183,9186,9188,9190,9192,9195],{"class":2980,"line":3025},[2978,9178,3515],{"class":3192},[2978,9180,9140],{"class":2991},[2978,9182,3443],{"class":3049},[2978,9184,9185],{"class":3498},"ILogger",[2978,9187,3521],{"class":3049},[2978,9189,9163],{"class":3498},[2978,9191,3527],{"class":3049},[2978,9193,9194],{"class":3418},"logger",[2978,9196,3175],{"class":3049},[2978,9198,9199],{"class":2980,"line":3031},[2978,9200,3545],{"class":3049},[2978,9202,9203,9206,9208,9210],{"class":2980,"line":3040},[2978,9204,9205],{"class":3418},"        _logger",[2978,9207,3556],{"class":3049},[2978,9209,9194],{"class":3418},[2978,9211,4539],{"class":3049},[2978,9213,9214],{"class":2980,"line":3059},[2978,9215,3617],{"class":3049},[2978,9217,9218],{"class":2980,"line":3076},[2978,9219,3022],{"emptyLinePlaceholder":3021},[2978,9221,9222,9224,9226,9229,9231,9234,9237,9239,9242,9244],{"class":2980,"line":3081},[2978,9223,3515],{"class":3192},[2978,9225,3518],{"class":3498},[2978,9227,9228],{"class":2991}," PublishAsync",[2978,9230,3443],{"class":3049},[2978,9232,9233],{"class":3498},"HealthReport",[2978,9235,9236],{"class":3418}," report",[2978,9238,4122],{"class":3049},[2978,9240,9241],{"class":3498},"CancellationToken",[2978,9243,5827],{"class":3418},[2978,9245,3175],{"class":3049},[2978,9247,9248],{"class":2980,"line":3246},[2978,9249,3545],{"class":3049},[2978,9251,9252,9254,9256,9259],{"class":2980,"line":3256},[2978,9253,9205],{"class":3418},[2978,9255,3119],{"class":3049},[2978,9257,9258],{"class":2991},"LogInformation",[2978,9260,5238],{"class":3049},[2978,9262,9263,9266],{"class":2980,"line":3261},[2978,9264,9265],{"class":2995},"            \"Health Check Status: {Status}, Duration: {Duration}ms\"",[2978,9267,5062],{"class":3049},[2978,9269,9270,9273,9275,9278],{"class":2980,"line":3267},[2978,9271,9272],{"class":3418},"            report",[2978,9274,3119],{"class":3049},[2978,9276,9277],{"class":3418},"Status",[2978,9279,5062],{"class":3049},[2978,9281,9282,9284,9286,9289,9291,9294],{"class":2980,"line":3276},[2978,9283,9272],{"class":3418},[2978,9285,3119],{"class":3049},[2978,9287,9288],{"class":3418},"TotalDuration",[2978,9290,3119],{"class":3049},[2978,9292,9293],{"class":3418},"TotalMilliseconds",[2978,9295,3477],{"class":3049},[2978,9297,9298],{"class":2980,"line":3836},[2978,9299,3022],{"emptyLinePlaceholder":3021},[2978,9301,9302],{"class":2980,"line":4741},[2978,9303,9304],{"class":2984},"        // Відправка метрик у CloudWatch, Prometheus, тощо\n",[2978,9306,9307,9310,9312,9314,9317,9320,9322,9324,9327],{"class":2980,"line":4753},[2978,9308,9309],{"class":3567},"        foreach",[2978,9311,5924],{"class":3049},[2978,9313,4588],{"class":3192},[2978,9315,9316],{"class":3418}," entry",[2978,9318,9319],{"class":3567}," in",[2978,9321,9236],{"class":3418},[2978,9323,3119],{"class":3049},[2978,9325,9326],{"class":3418},"Entries",[2978,9328,3175],{"class":3049},[2978,9330,9331],{"class":2980,"line":4758},[2978,9332,5848],{"class":3049},[2978,9334,9335,9338,9340,9342],{"class":2980,"line":4764},[2978,9336,9337],{"class":3418},"            _logger",[2978,9339,3119],{"class":3049},[2978,9341,9258],{"class":2991},[2978,9343,5238],{"class":3049},[2978,9345,9346,9349],{"class":2980,"line":4784},[2978,9347,9348],{"class":2995},"                \"  {Name}: {Status} ({Duration}ms)\"",[2978,9350,5062],{"class":3049},[2978,9352,9353,9356,9358,9361],{"class":2980,"line":4789},[2978,9354,9355],{"class":3418},"                entry",[2978,9357,3119],{"class":3049},[2978,9359,9360],{"class":3418},"Key",[2978,9362,5062],{"class":3049},[2978,9364,9365,9367,9369,9372,9374,9376],{"class":2980,"line":4805},[2978,9366,9355],{"class":3418},[2978,9368,3119],{"class":3049},[2978,9370,9371],{"class":3418},"Value",[2978,9373,3119],{"class":3049},[2978,9375,9277],{"class":3418},[2978,9377,5062],{"class":3049},[2978,9379,9380,9382,9384,9386,9388,9391,9393,9395],{"class":2980,"line":4810},[2978,9381,9355],{"class":3418},[2978,9383,3119],{"class":3049},[2978,9385,9371],{"class":3418},[2978,9387,3119],{"class":3049},[2978,9389,9390],{"class":3418},"Duration",[2978,9392,3119],{"class":3049},[2978,9394,9293],{"class":3418},[2978,9396,3477],{"class":3049},[2978,9398,9399],{"class":2980,"line":4815},[2978,9400,6442],{"class":3049},[2978,9402,9403],{"class":2980,"line":4834},[2978,9404,3022],{"emptyLinePlaceholder":3021},[2978,9406,9407,9409,9411,9413,9416],{"class":2980,"line":4839},[2978,9408,3568],{"class":3567},[2978,9410,3518],{"class":3418},[2978,9412,3119],{"class":3049},[2978,9414,9415],{"class":3418},"CompletedTask",[2978,9417,4539],{"class":3049},[2978,9419,9420],{"class":2980,"line":4867},[2978,9421,3617],{"class":3049},[2978,9423,9424],{"class":2980,"line":4880},[2978,9425,3622],{"class":3049},[2964,9427,9428],{},[3088,9429,9430],{},"Реєстрація:",[2968,9432,9434],{"className":3409,"code":9433,"language":3411,"meta":2973,"style":2973},"builder.Services.AddSingleton\u003CIHealthCheckPublisher, CloudWatchHealthCheckPublisher>();\n\nbuilder.Services.Configure\u003CHealthCheckPublisherOptions>(options =>\n{\n    options.Delay = TimeSpan.FromSeconds(10); // Публікувати кожні 10 секунд\n    options.Period = TimeSpan.FromSeconds(30); // Період між публікаціями\n});\n",[2975,9435,9436,9461,9465,9489,9493,9519,9545],{"__ignoreMap":2973},[2978,9437,9438,9440,9442,9444,9446,9449,9451,9454,9456,9458],{"class":2980,"line":2981},[2978,9439,3419],{"class":3418},[2978,9441,3119],{"class":3049},[2978,9443,3424],{"class":3418},[2978,9445,3119],{"class":3049},[2978,9447,9448],{"class":2991},"AddSingleton",[2978,9450,3521],{"class":3049},[2978,9452,9453],{"class":3498},"IHealthCheckPublisher",[2978,9455,4122],{"class":3049},[2978,9457,9163],{"class":3498},[2978,9459,9460],{"class":3049},">();\n",[2978,9462,9463],{"class":2980,"line":2988},[2978,9464,3022],{"emptyLinePlaceholder":3021},[2978,9466,9467,9469,9471,9473,9475,9478,9480,9483,9485,9487],{"class":2980,"line":2999},[2978,9468,3419],{"class":3418},[2978,9470,3119],{"class":3049},[2978,9472,3424],{"class":3418},[2978,9474,3119],{"class":3049},[2978,9476,9477],{"class":2991},"Configure",[2978,9479,3521],{"class":3049},[2978,9481,9482],{"class":3498},"HealthCheckPublisherOptions",[2978,9484,4188],{"class":3049},[2978,9486,8061],{"class":3418},[2978,9488,8064],{"class":3049},[2978,9490,9491],{"class":2980,"line":3018},[2978,9492,3510],{"class":3049},[2978,9494,9495,9497,9499,9502,9504,9506,9508,9510,9512,9514,9516],{"class":2980,"line":3025},[2978,9496,8182],{"class":3418},[2978,9498,3119],{"class":3049},[2978,9500,9501],{"class":3418},"Delay",[2978,9503,3556],{"class":3049},[2978,9505,5307],{"class":3418},[2978,9507,3119],{"class":3049},[2978,9509,5312],{"class":2991},[2978,9511,3443],{"class":3049},[2978,9513,5631],{"class":3005},[2978,9515,8085],{"class":3049},[2978,9517,9518],{"class":2984},"// Публікувати кожні 10 секунд\n",[2978,9520,9521,9523,9525,9528,9530,9532,9534,9536,9538,9540,9542],{"class":2980,"line":3031},[2978,9522,8182],{"class":3418},[2978,9524,3119],{"class":3049},[2978,9526,9527],{"class":3418},"Period",[2978,9529,3556],{"class":3049},[2978,9531,5307],{"class":3418},[2978,9533,3119],{"class":3049},[2978,9535,5312],{"class":2991},[2978,9537,3443],{"class":3049},[2978,9539,8491],{"class":3005},[2978,9541,8085],{"class":3049},[2978,9543,9544],{"class":2984},"// Період між публікаціями\n",[2978,9546,9547],{"class":2980,"line":3040},[2978,9548,4289],{"class":3049},[3351,9550,9552],{"id":9551},"_2-conditional-health-checks","2. Conditional Health Checks",[2964,9554,9555],{},"Вимкнення чеків у Development:",[2968,9557,9559],{"className":3409,"code":9558,"language":3411,"meta":2973,"style":2973},"var healthChecksBuilder = builder.Services.AddHealthChecks()\n    .AddCheck(\"self\", () => HealthCheckResult.Healthy(), tags: new[] { \"live\" });\n\nif (!builder.Environment.IsDevelopment())\n{\n    // Production-only checks\n    healthChecksBuilder\n        .AddSqlServer(connectionString!, tags: new[] { \"database\", \"ready\" })\n        .AddRedis(redisConnection!, tags: new[] { \"cache\", \"ready\" });\n}\nelse\n{\n    // Development - mock checks\n    healthChecksBuilder\n        .AddCheck(\"database-mock\", () => HealthCheckResult.Healthy(\"Mock DB\"), \n            tags: new[] { \"database\", \"ready\" })\n        .AddCheck(\"redis-mock\", () => HealthCheckResult.Healthy(\"Mock Redis\"), \n            tags: new[] { \"cache\", \"ready\" });\n}\n",[2975,9560,9561,9582,9614,9618,9640,9644,9649,9654,9683,9711,9715,9720,9724,9729,9733,9759,9778,9804,9822],{"__ignoreMap":2973},[2978,9562,9563,9565,9568,9570,9572,9574,9576,9578,9580],{"class":2980,"line":2981},[2978,9564,4588],{"class":3192},[2978,9566,9567],{"class":3418}," healthChecksBuilder",[2978,9569,3556],{"class":3049},[2978,9571,3419],{"class":3418},[2978,9573,3119],{"class":3049},[2978,9575,3424],{"class":3418},[2978,9577,3119],{"class":3049},[2978,9579,3429],{"class":2991},[2978,9581,3432],{"class":3049},[2978,9583,9584,9586,9588,9590,9592,9594,9596,9598,9600,9602,9604,9606,9608,9610,9612],{"class":2980,"line":2988},[2978,9585,3437],{"class":3049},[2978,9587,4180],{"class":2991},[2978,9589,3443],{"class":3049},[2978,9591,4661],{"class":2995},[2978,9593,4664],{"class":3049},[2978,9595,3524],{"class":3418},[2978,9597,3119],{"class":3049},[2978,9599,3591],{"class":2991},[2978,9601,5217],{"class":3049},[2978,9603,4125],{"class":3418},[2978,9605,3669],{"class":3049},[2978,9607,4130],{"class":3192},[2978,9609,4133],{"class":3049},[2978,9611,4209],{"class":2995},[2978,9613,4212],{"class":3049},[2978,9615,9616],{"class":2980,"line":2999},[2978,9617,3022],{"emptyLinePlaceholder":3021},[2978,9619,9620,9623,9625,9627,9629,9632,9634,9637],{"class":2980,"line":3018},[2978,9621,9622],{"class":3567},"if",[2978,9624,7440],{"class":3049},[2978,9626,3419],{"class":3418},[2978,9628,3119],{"class":3049},[2978,9630,9631],{"class":3418},"Environment",[2978,9633,3119],{"class":3049},[2978,9635,9636],{"class":2991},"IsDevelopment",[2978,9638,9639],{"class":3049},"())\n",[2978,9641,9642],{"class":2980,"line":3025},[2978,9643,3510],{"class":3049},[2978,9645,9646],{"class":2980,"line":3031},[2978,9647,9648],{"class":2984},"    // Production-only checks\n",[2978,9650,9651],{"class":2980,"line":3040},[2978,9652,9653],{"class":3418},"    healthChecksBuilder\n",[2978,9655,9656,9659,9661,9663,9665,9667,9669,9671,9673,9675,9677,9679,9681],{"class":2980,"line":3059},[2978,9657,9658],{"class":3049},"        .",[2978,9660,3440],{"class":2991},[2978,9662,3443],{"class":3049},[2978,9664,3446],{"class":3418},[2978,9666,7761],{"class":3049},[2978,9668,4125],{"class":3418},[2978,9670,3669],{"class":3049},[2978,9672,4130],{"class":3192},[2978,9674,4133],{"class":3049},[2978,9676,4136],{"class":2995},[2978,9678,4122],{"class":3049},[2978,9680,4141],{"class":2995},[2978,9682,4144],{"class":3049},[2978,9684,9685,9687,9689,9691,9693,9695,9697,9699,9701,9703,9705,9707,9709],{"class":2980,"line":3076},[2978,9686,9658],{"class":3049},[2978,9688,3455],{"class":2991},[2978,9690,3443],{"class":3049},[2978,9692,3460],{"class":3418},[2978,9694,7761],{"class":3049},[2978,9696,4125],{"class":3418},[2978,9698,3669],{"class":3049},[2978,9700,4130],{"class":3192},[2978,9702,4133],{"class":3049},[2978,9704,4167],{"class":2995},[2978,9706,4122],{"class":3049},[2978,9708,4141],{"class":2995},[2978,9710,4212],{"class":3049},[2978,9712,9713],{"class":2980,"line":3081},[2978,9714,3622],{"class":3049},[2978,9716,9717],{"class":2980,"line":3246},[2978,9718,9719],{"class":3567},"else\n",[2978,9721,9722],{"class":2980,"line":3256},[2978,9723,3510],{"class":3049},[2978,9725,9726],{"class":2980,"line":3261},[2978,9727,9728],{"class":2984},"    // Development - mock checks\n",[2978,9730,9731],{"class":2980,"line":3267},[2978,9732,9653],{"class":3418},[2978,9734,9735,9737,9739,9741,9744,9746,9748,9750,9752,9754,9757],{"class":2980,"line":3276},[2978,9736,9658],{"class":3049},[2978,9738,4180],{"class":2991},[2978,9740,3443],{"class":3049},[2978,9742,9743],{"class":2995},"\"database-mock\"",[2978,9745,4664],{"class":3049},[2978,9747,3524],{"class":3418},[2978,9749,3119],{"class":3049},[2978,9751,3591],{"class":2991},[2978,9753,3443],{"class":3049},[2978,9755,9756],{"class":2995},"\"Mock DB\"",[2978,9758,9095],{"class":3049},[2978,9760,9761,9764,9766,9768,9770,9772,9774,9776],{"class":2980,"line":3836},[2978,9762,9763],{"class":3418},"            tags",[2978,9765,3669],{"class":3049},[2978,9767,4130],{"class":3192},[2978,9769,4133],{"class":3049},[2978,9771,4136],{"class":2995},[2978,9773,4122],{"class":3049},[2978,9775,4141],{"class":2995},[2978,9777,4144],{"class":3049},[2978,9779,9780,9782,9784,9786,9789,9791,9793,9795,9797,9799,9802],{"class":2980,"line":4741},[2978,9781,9658],{"class":3049},[2978,9783,4180],{"class":2991},[2978,9785,3443],{"class":3049},[2978,9787,9788],{"class":2995},"\"redis-mock\"",[2978,9790,4664],{"class":3049},[2978,9792,3524],{"class":3418},[2978,9794,3119],{"class":3049},[2978,9796,3591],{"class":2991},[2978,9798,3443],{"class":3049},[2978,9800,9801],{"class":2995},"\"Mock Redis\"",[2978,9803,9095],{"class":3049},[2978,9805,9806,9808,9810,9812,9814,9816,9818,9820],{"class":2980,"line":4753},[2978,9807,9763],{"class":3418},[2978,9809,3669],{"class":3049},[2978,9811,4130],{"class":3192},[2978,9813,4133],{"class":3049},[2978,9815,4167],{"class":2995},[2978,9817,4122],{"class":3049},[2978,9819,4141],{"class":2995},[2978,9821,4212],{"class":3049},[2978,9823,9824],{"class":2980,"line":4758},[2978,9825,3622],{"class":3049},[3351,9827,9829],{"id":9828},"_3-graceful-degradation","3. Graceful Degradation",[2964,9831,9832],{},"API продовжує працювати навіть якщо деякі залежності недоступні:",[2968,9834,9836],{"className":3409,"code":9835,"language":3411,"meta":2973,"style":2973},"public class GracefulDegradationHealthCheck : IHealthCheck\n{\n    private readonly IProductService _productService;\n\n    public GracefulDegradationHealthCheck(IProductService productService)\n    {\n        _productService = productService;\n    }\n\n    public async Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        var canUseCache = await _productService.CanUseCacheAsync();\n        var canUseDatabase = await _productService.CanUseDatabaseAsync();\n\n        if (canUseDatabase && canUseCache)\n        {\n            return HealthCheckResult.Healthy(\"All systems operational\");\n        }\n\n        if (canUseDatabase && !canUseCache)\n        {\n            return HealthCheckResult.Degraded(\n                \"Cache unavailable, using database only\",\n                data: new Dictionary\u003Cstring, object>\n                {\n                    [\"Cache\"] = \"Unavailable\",\n                    [\"Database\"] = \"Available\",\n                    [\"Mode\"] = \"Degraded\"\n                });\n        }\n\n        if (!canUseDatabase)\n        {\n            return HealthCheckResult.Unhealthy(\n                \"Database unavailable\",\n                data: new Dictionary\u003Cstring, object>\n                {\n                    [\"Cache\"] = canUseCache ? \"Available\" : \"Unavailable\",\n                    [\"Database\"] = \"Unavailable\"\n                });\n        }\n\n        return HealthCheckResult.Healthy();\n    }\n}\n",[2975,9837,9838,9851,9855,9869,9873,9889,9893,9905,9909,9913,9931,9939,9951,9955,9975,9995,9999,10015,10019,10036,10040,10044,10059,10063,10075,10082,10102,10107,10122,10136,10148,10153,10157,10161,10171,10175,10187,10194,10214,10218,10239,10250,10254,10258,10262,10274,10278],{"__ignoreMap":2973},[2978,9839,9840,9842,9844,9847,9849],{"class":2980,"line":2981},[2978,9841,3492],{"class":3192},[2978,9843,3495],{"class":3192},[2978,9845,9846],{"class":3498}," GracefulDegradationHealthCheck",[2978,9848,3502],{"class":3049},[2978,9850,3505],{"class":3498},[2978,9852,9853],{"class":2980,"line":2988},[2978,9854,3510],{"class":3049},[2978,9856,9857,9859,9861,9864,9867],{"class":2980,"line":2999},[2978,9858,5731],{"class":3192},[2978,9860,5734],{"class":3192},[2978,9862,9863],{"class":3498}," IProductService",[2978,9865,9866],{"class":3418}," _productService",[2978,9868,4539],{"class":3049},[2978,9870,9871],{"class":2980,"line":3018},[2978,9872,3022],{"emptyLinePlaceholder":3021},[2978,9874,9875,9877,9879,9881,9884,9887],{"class":2980,"line":3025},[2978,9876,3515],{"class":3192},[2978,9878,9846],{"class":2991},[2978,9880,3443],{"class":3049},[2978,9882,9883],{"class":3498},"IProductService",[2978,9885,9886],{"class":3418}," productService",[2978,9888,3175],{"class":3049},[2978,9890,9891],{"class":2980,"line":3031},[2978,9892,3545],{"class":3049},[2978,9894,9895,9898,9900,9903],{"class":2980,"line":3040},[2978,9896,9897],{"class":3418},"        _productService",[2978,9899,3556],{"class":3049},[2978,9901,9902],{"class":3418},"productService",[2978,9904,4539],{"class":3049},[2978,9906,9907],{"class":2980,"line":3059},[2978,9908,3617],{"class":3049},[2978,9910,9911],{"class":2980,"line":3076},[2978,9912,3022],{"emptyLinePlaceholder":3021},[2978,9914,9915,9917,9919,9921,9923,9925,9927,9929],{"class":2980,"line":3081},[2978,9916,3515],{"class":3192},[2978,9918,7225],{"class":3192},[2978,9920,3518],{"class":3498},[2978,9922,3521],{"class":3049},[2978,9924,3524],{"class":3498},[2978,9926,3527],{"class":3049},[2978,9928,3530],{"class":2991},[2978,9930,5238],{"class":3049},[2978,9932,9933,9935,9937],{"class":2980,"line":3246},[2978,9934,5815],{"class":3498},[2978,9936,3538],{"class":3418},[2978,9938,5062],{"class":3049},[2978,9940,9941,9943,9945,9947,9949],{"class":2980,"line":3256},[2978,9942,5824],{"class":3498},[2978,9944,5827],{"class":3418},[2978,9946,3556],{"class":3049},[2978,9948,5832],{"class":3192},[2978,9950,3175],{"class":3049},[2978,9952,9953],{"class":2980,"line":3261},[2978,9954,3545],{"class":3049},[2978,9956,9957,9959,9962,9964,9966,9968,9970,9973],{"class":2980,"line":3267},[2978,9958,3550],{"class":3192},[2978,9960,9961],{"class":3418}," canUseCache",[2978,9963,3556],{"class":3049},[2978,9965,7309],{"class":3192},[2978,9967,9866],{"class":3418},[2978,9969,3119],{"class":3049},[2978,9971,9972],{"class":2991},"CanUseCacheAsync",[2978,9974,3562],{"class":3049},[2978,9976,9977,9979,9982,9984,9986,9988,9990,9993],{"class":2980,"line":3276},[2978,9978,3550],{"class":3192},[2978,9980,9981],{"class":3418}," canUseDatabase",[2978,9983,3556],{"class":3049},[2978,9985,7309],{"class":3192},[2978,9987,9866],{"class":3418},[2978,9989,3119],{"class":3049},[2978,9991,9992],{"class":2991},"CanUseDatabaseAsync",[2978,9994,3562],{"class":3049},[2978,9996,9997],{"class":2980,"line":3836},[2978,9998,3022],{"emptyLinePlaceholder":3021},[2978,10000,10001,10003,10005,10008,10010,10013],{"class":2980,"line":4741},[2978,10002,6920],{"class":3567},[2978,10004,5924],{"class":3049},[2978,10006,10007],{"class":3418},"canUseDatabase",[2978,10009,5893],{"class":3049},[2978,10011,10012],{"class":3418},"canUseCache",[2978,10014,3175],{"class":3049},[2978,10016,10017],{"class":2980,"line":4753},[2978,10018,5848],{"class":3049},[2978,10020,10021,10023,10025,10027,10029,10031,10034],{"class":2980,"line":4758},[2978,10022,6384],{"class":3567},[2978,10024,4019],{"class":3418},[2978,10026,3119],{"class":3049},[2978,10028,3591],{"class":2991},[2978,10030,3443],{"class":3049},[2978,10032,10033],{"class":2995},"\"All systems operational\"",[2978,10035,3477],{"class":3049},[2978,10037,10038],{"class":2980,"line":4764},[2978,10039,6442],{"class":3049},[2978,10041,10042],{"class":2980,"line":4784},[2978,10043,3022],{"emptyLinePlaceholder":3021},[2978,10045,10046,10048,10050,10052,10055,10057],{"class":2980,"line":4789},[2978,10047,6920],{"class":3567},[2978,10049,5924],{"class":3049},[2978,10051,10007],{"class":3418},[2978,10053,10054],{"class":3049}," && !",[2978,10056,10012],{"class":3418},[2978,10058,3175],{"class":3049},[2978,10060,10061],{"class":2980,"line":4805},[2978,10062,5848],{"class":3049},[2978,10064,10065,10067,10069,10071,10073],{"class":2980,"line":4810},[2978,10066,6384],{"class":3567},[2978,10068,4019],{"class":3418},[2978,10070,3119],{"class":3049},[2978,10072,4050],{"class":2991},[2978,10074,5238],{"class":3049},[2978,10076,10077,10080],{"class":2980,"line":4815},[2978,10078,10079],{"class":2995},"                \"Cache unavailable, using database only\"",[2978,10081,5062],{"class":3049},[2978,10083,10084,10086,10088,10090,10092,10094,10096,10098,10100],{"class":2980,"line":4834},[2978,10085,7042],{"class":3418},[2978,10087,3669],{"class":3049},[2978,10089,4130],{"class":3192},[2978,10091,6034],{"class":3498},[2978,10093,3521],{"class":3049},[2978,10095,6039],{"class":3192},[2978,10097,4122],{"class":3049},[2978,10099,6044],{"class":3192},[2978,10101,6047],{"class":3049},[2978,10103,10104],{"class":2980,"line":4839},[2978,10105,10106],{"class":3049},"                {\n",[2978,10108,10109,10112,10115,10117,10120],{"class":2980,"line":4867},[2978,10110,10111],{"class":3049},"                    [",[2978,10113,10114],{"class":2995},"\"Cache\"",[2978,10116,6062],{"class":3049},[2978,10118,10119],{"class":2995},"\"Unavailable\"",[2978,10121,5062],{"class":3049},[2978,10123,10124,10126,10129,10131,10134],{"class":2980,"line":4880},[2978,10125,10111],{"class":3049},[2978,10127,10128],{"class":2995},"\"Database\"",[2978,10130,6062],{"class":3049},[2978,10132,10133],{"class":2995},"\"Available\"",[2978,10135,5062],{"class":3049},[2978,10137,10138,10140,10143,10145],{"class":2980,"line":4885},[2978,10139,10111],{"class":3049},[2978,10141,10142],{"class":2995},"\"Mode\"",[2978,10144,6062],{"class":3049},[2978,10146,10147],{"class":2995},"\"Degraded\"\n",[2978,10149,10150],{"class":2980,"line":4890},[2978,10151,10152],{"class":3049},"                });\n",[2978,10154,10155],{"class":2980,"line":4909},[2978,10156,6442],{"class":3049},[2978,10158,10159],{"class":2980,"line":4914},[2978,10160,3022],{"emptyLinePlaceholder":3021},[2978,10162,10163,10165,10167,10169],{"class":2980,"line":4941},[2978,10164,6920],{"class":3567},[2978,10166,7440],{"class":3049},[2978,10168,10007],{"class":3418},[2978,10170,3175],{"class":3049},[2978,10172,10173],{"class":2980,"line":4954},[2978,10174,5848],{"class":3049},[2978,10176,10177,10179,10181,10183,10185],{"class":2980,"line":4959},[2978,10178,6384],{"class":3567},[2978,10180,4019],{"class":3418},[2978,10182,3119],{"class":3049},[2978,10184,3605],{"class":2991},[2978,10186,5238],{"class":3049},[2978,10188,10189,10192],{"class":2980,"line":4964},[2978,10190,10191],{"class":2995},"                \"Database unavailable\"",[2978,10193,5062],{"class":3049},[2978,10195,10196,10198,10200,10202,10204,10206,10208,10210,10212],{"class":2980,"line":6186},[2978,10197,7042],{"class":3418},[2978,10199,3669],{"class":3049},[2978,10201,4130],{"class":3192},[2978,10203,6034],{"class":3498},[2978,10205,3521],{"class":3049},[2978,10207,6039],{"class":3192},[2978,10209,4122],{"class":3049},[2978,10211,6044],{"class":3192},[2978,10213,6047],{"class":3049},[2978,10215,10216],{"class":2980,"line":6192},[2978,10217,10106],{"class":3049},[2978,10219,10220,10222,10224,10226,10228,10231,10233,10235,10237],{"class":2980,"line":6197},[2978,10221,10111],{"class":3049},[2978,10223,10114],{"class":2995},[2978,10225,6062],{"class":3049},[2978,10227,10012],{"class":3418},[2978,10229,10230],{"class":3049}," ? ",[2978,10232,10133],{"class":2995},[2978,10234,3502],{"class":3049},[2978,10236,10119],{"class":2995},[2978,10238,5062],{"class":3049},[2978,10240,10241,10243,10245,10247],{"class":2980,"line":6214},[2978,10242,10111],{"class":3049},[2978,10244,10128],{"class":2995},[2978,10246,6062],{"class":3049},[2978,10248,10249],{"class":2995},"\"Unavailable\"\n",[2978,10251,10252],{"class":2980,"line":6219},[2978,10253,10152],{"class":3049},[2978,10255,10256],{"class":2980,"line":6232},[2978,10257,6442],{"class":3049},[2978,10259,10260],{"class":2980,"line":6243},[2978,10261,3022],{"emptyLinePlaceholder":3021},[2978,10263,10264,10266,10268,10270,10272],{"class":2980,"line":6268},[2978,10265,3568],{"class":3567},[2978,10267,4019],{"class":3418},[2978,10269,3119],{"class":3049},[2978,10271,3591],{"class":2991},[2978,10273,3562],{"class":3049},[2978,10275,10276],{"class":2980,"line":6281},[2978,10277,3617],{"class":3049},[2978,10279,10280],{"class":2980,"line":6286},[2978,10281,3622],{"class":3049},[3351,10283,10285],{"id":10284},"_4-circuit-breaker-integration","4. Circuit Breaker Integration",[2964,10287,10288],{},"Інтеграція з Polly Circuit Breaker:",[2968,10290,10292],{"className":3409,"code":10291,"language":3411,"meta":2973,"style":2973},"public class CircuitBreakerHealthCheck : IHealthCheck\n{\n    private readonly ICircuitBreakerPolicy _circuitBreaker;\n\n    public CircuitBreakerHealthCheck(ICircuitBreakerPolicy circuitBreaker)\n    {\n        _circuitBreaker = circuitBreaker;\n    }\n\n    public Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        var state = _circuitBreaker.CircuitState;\n\n        var data = new Dictionary\u003Cstring, object>\n        {\n            [\"State\"] = state.ToString(),\n            [\"FailureCount\"] = _circuitBreaker.FailureCount\n        };\n\n        return state switch\n        {\n            CircuitState.Closed => Task.FromResult(\n                HealthCheckResult.Healthy(\"Circuit breaker closed\", data)),\n            \n            CircuitState.HalfOpen => Task.FromResult(\n                HealthCheckResult.Degraded(\"Circuit breaker half-open\", data)),\n            \n            CircuitState.Open => Task.FromResult(\n                HealthCheckResult.Unhealthy(\"Circuit breaker open\", data)),\n            \n            _ => Task.FromResult(\n                HealthCheckResult.Unhealthy(\"Unknown circuit breaker state\", data))\n        };\n    }\n}\n",[2975,10293,10294,10307,10311,10325,10329,10345,10349,10361,10365,10369,10385,10393,10405,10409,10428,10432,10454,10458,10478,10494,10498,10502,10511,10515,10536,10556,10561,10580,10599,10603,10622,10641,10645,10660,10680,10684,10688],{"__ignoreMap":2973},[2978,10295,10296,10298,10300,10303,10305],{"class":2980,"line":2981},[2978,10297,3492],{"class":3192},[2978,10299,3495],{"class":3192},[2978,10301,10302],{"class":3498}," CircuitBreakerHealthCheck",[2978,10304,3502],{"class":3049},[2978,10306,3505],{"class":3498},[2978,10308,10309],{"class":2980,"line":2988},[2978,10310,3510],{"class":3049},[2978,10312,10313,10315,10317,10320,10323],{"class":2980,"line":2999},[2978,10314,5731],{"class":3192},[2978,10316,5734],{"class":3192},[2978,10318,10319],{"class":3498}," ICircuitBreakerPolicy",[2978,10321,10322],{"class":3418}," _circuitBreaker",[2978,10324,4539],{"class":3049},[2978,10326,10327],{"class":2980,"line":3018},[2978,10328,3022],{"emptyLinePlaceholder":3021},[2978,10330,10331,10333,10335,10337,10340,10343],{"class":2980,"line":3025},[2978,10332,3515],{"class":3192},[2978,10334,10302],{"class":2991},[2978,10336,3443],{"class":3049},[2978,10338,10339],{"class":3498},"ICircuitBreakerPolicy",[2978,10341,10342],{"class":3418}," circuitBreaker",[2978,10344,3175],{"class":3049},[2978,10346,10347],{"class":2980,"line":3031},[2978,10348,3545],{"class":3049},[2978,10350,10351,10354,10356,10359],{"class":2980,"line":3040},[2978,10352,10353],{"class":3418},"        _circuitBreaker",[2978,10355,3556],{"class":3049},[2978,10357,10358],{"class":3418},"circuitBreaker",[2978,10360,4539],{"class":3049},[2978,10362,10363],{"class":2980,"line":3059},[2978,10364,3617],{"class":3049},[2978,10366,10367],{"class":2980,"line":3076},[2978,10368,3022],{"emptyLinePlaceholder":3021},[2978,10370,10371,10373,10375,10377,10379,10381,10383],{"class":2980,"line":3081},[2978,10372,3515],{"class":3192},[2978,10374,3518],{"class":3498},[2978,10376,3521],{"class":3049},[2978,10378,3524],{"class":3498},[2978,10380,3527],{"class":3049},[2978,10382,3530],{"class":2991},[2978,10384,5238],{"class":3049},[2978,10386,10387,10389,10391],{"class":2980,"line":3246},[2978,10388,5815],{"class":3498},[2978,10390,3538],{"class":3418},[2978,10392,5062],{"class":3049},[2978,10394,10395,10397,10399,10401,10403],{"class":2980,"line":3256},[2978,10396,5824],{"class":3498},[2978,10398,5827],{"class":3418},[2978,10400,3556],{"class":3049},[2978,10402,5832],{"class":3192},[2978,10404,3175],{"class":3049},[2978,10406,10407],{"class":2980,"line":3261},[2978,10408,3545],{"class":3049},[2978,10410,10411,10413,10416,10418,10421,10423,10426],{"class":2980,"line":3267},[2978,10412,3550],{"class":3192},[2978,10414,10415],{"class":3418}," state",[2978,10417,3556],{"class":3049},[2978,10419,10420],{"class":3418},"_circuitBreaker",[2978,10422,3119],{"class":3049},[2978,10424,10425],{"class":3418},"CircuitState",[2978,10427,4539],{"class":3049},[2978,10429,10430],{"class":2980,"line":3276},[2978,10431,3022],{"emptyLinePlaceholder":3021},[2978,10433,10434,10436,10438,10440,10442,10444,10446,10448,10450,10452],{"class":2980,"line":3836},[2978,10435,3550],{"class":3192},[2978,10437,6027],{"class":3418},[2978,10439,3556],{"class":3049},[2978,10441,4130],{"class":3192},[2978,10443,6034],{"class":3498},[2978,10445,3521],{"class":3049},[2978,10447,6039],{"class":3192},[2978,10449,4122],{"class":3049},[2978,10451,6044],{"class":3192},[2978,10453,6047],{"class":3049},[2978,10455,10456],{"class":2980,"line":4741},[2978,10457,5848],{"class":3049},[2978,10459,10460,10462,10465,10467,10470,10472,10475],{"class":2980,"line":4753},[2978,10461,6820],{"class":3049},[2978,10463,10464],{"class":2995},"\"State\"",[2978,10466,6062],{"class":3049},[2978,10468,10469],{"class":3418},"state",[2978,10471,3119],{"class":3049},[2978,10473,10474],{"class":2991},"ToString",[2978,10476,10477],{"class":3049},"(),\n",[2978,10479,10480,10482,10485,10487,10489,10491],{"class":2980,"line":4758},[2978,10481,6820],{"class":3049},[2978,10483,10484],{"class":2995},"\"FailureCount\"",[2978,10486,6062],{"class":3049},[2978,10488,10420],{"class":3418},[2978,10490,3119],{"class":3049},[2978,10492,10493],{"class":3418},"FailureCount\n",[2978,10495,10496],{"class":2980,"line":4764},[2978,10497,6911],{"class":3049},[2978,10499,10500],{"class":2980,"line":4784},[2978,10501,3022],{"emptyLinePlaceholder":3021},[2978,10503,10504,10506,10508],{"class":2980,"line":4789},[2978,10505,3568],{"class":3567},[2978,10507,10415],{"class":3418},[2978,10509,10510],{"class":3567}," switch\n",[2978,10512,10513],{"class":2980,"line":4805},[2978,10514,5848],{"class":3049},[2978,10516,10517,10520,10522,10525,10527,10530,10532,10534],{"class":2980,"line":4810},[2978,10518,10519],{"class":3498},"            CircuitState",[2978,10521,3119],{"class":3049},[2978,10523,10524],{"class":3498},"Closed",[2978,10526,4266],{"class":3049},[2978,10528,10529],{"class":3418},"Task",[2978,10531,3119],{"class":3049},[2978,10533,5951],{"class":2991},[2978,10535,5238],{"class":3049},[2978,10537,10538,10540,10542,10544,10546,10549,10551,10553],{"class":2980,"line":4815},[2978,10539,6398],{"class":3418},[2978,10541,3119],{"class":3049},[2978,10543,3591],{"class":2991},[2978,10545,3443],{"class":3049},[2978,10547,10548],{"class":2995},"\"Circuit breaker closed\"",[2978,10550,4122],{"class":3049},[2978,10552,6276],{"class":3418},[2978,10554,10555],{"class":3049},")),\n",[2978,10557,10558],{"class":2980,"line":4834},[2978,10559,10560],{"class":3049},"            \n",[2978,10562,10563,10565,10567,10570,10572,10574,10576,10578],{"class":2980,"line":4839},[2978,10564,10519],{"class":3498},[2978,10566,3119],{"class":3049},[2978,10568,10569],{"class":3498},"HalfOpen",[2978,10571,4266],{"class":3049},[2978,10573,10529],{"class":3418},[2978,10575,3119],{"class":3049},[2978,10577,5951],{"class":2991},[2978,10579,5238],{"class":3049},[2978,10581,10582,10584,10586,10588,10590,10593,10595,10597],{"class":2980,"line":4867},[2978,10583,6398],{"class":3418},[2978,10585,3119],{"class":3049},[2978,10587,4050],{"class":2991},[2978,10589,3443],{"class":3049},[2978,10591,10592],{"class":2995},"\"Circuit breaker half-open\"",[2978,10594,4122],{"class":3049},[2978,10596,6276],{"class":3418},[2978,10598,10555],{"class":3049},[2978,10600,10601],{"class":2980,"line":4880},[2978,10602,10560],{"class":3049},[2978,10604,10605,10607,10609,10612,10614,10616,10618,10620],{"class":2980,"line":4885},[2978,10606,10519],{"class":3498},[2978,10608,3119],{"class":3049},[2978,10610,10611],{"class":3498},"Open",[2978,10613,4266],{"class":3049},[2978,10615,10529],{"class":3418},[2978,10617,3119],{"class":3049},[2978,10619,5951],{"class":2991},[2978,10621,5238],{"class":3049},[2978,10623,10624,10626,10628,10630,10632,10635,10637,10639],{"class":2980,"line":4890},[2978,10625,6398],{"class":3418},[2978,10627,3119],{"class":3049},[2978,10629,3605],{"class":2991},[2978,10631,3443],{"class":3049},[2978,10633,10634],{"class":2995},"\"Circuit breaker open\"",[2978,10636,4122],{"class":3049},[2978,10638,6276],{"class":3418},[2978,10640,10555],{"class":3049},[2978,10642,10643],{"class":2980,"line":4909},[2978,10644,10560],{"class":3049},[2978,10646,10647,10650,10652,10654,10656,10658],{"class":2980,"line":4914},[2978,10648,10649],{"class":3192},"            _",[2978,10651,4266],{"class":3049},[2978,10653,10529],{"class":3418},[2978,10655,3119],{"class":3049},[2978,10657,5951],{"class":2991},[2978,10659,5238],{"class":3049},[2978,10661,10662,10664,10666,10668,10670,10673,10675,10677],{"class":2980,"line":4941},[2978,10663,6398],{"class":3418},[2978,10665,3119],{"class":3049},[2978,10667,3605],{"class":2991},[2978,10669,3443],{"class":3049},[2978,10671,10672],{"class":2995},"\"Unknown circuit breaker state\"",[2978,10674,4122],{"class":3049},[2978,10676,6276],{"class":3418},[2978,10678,10679],{"class":3049},"))\n",[2978,10681,10682],{"class":2980,"line":4954},[2978,10683,6911],{"class":3049},[2978,10685,10686],{"class":2980,"line":4959},[2978,10687,3617],{"class":3049},[2978,10689,10690],{"class":2980,"line":4964},[2978,10691,3622],{"class":3049},[3351,10693,10695],{"id":10694},"_5-custom-response-format","5. Custom Response Format",[2964,10697,10698],{},"Кастомний формат відповіді:",[2968,10700,10702],{"className":3409,"code":10701,"language":3411,"meta":2973,"style":2973},"app.MapHealthChecks(\"/health/custom\", new HealthCheckOptions\n{\n    ResponseWriter = async (context, report) =>\n    {\n        context.Response.ContentType = \"application/json\";\n\n        var response = new\n        {\n            status = report.Status.ToString(),\n            timestamp = DateTime.UtcNow,\n            duration = report.TotalDuration.TotalMilliseconds,\n            checks = report.Entries.Select(e => new\n            {\n                name = e.Key,\n                status = e.Value.Status.ToString(),\n                duration = e.Value.Duration.TotalMilliseconds,\n                description = e.Value.Description,\n                data = e.Value.Data,\n                exception = e.Value.Exception?.Message\n            })\n        };\n\n        await context.Response.WriteAsJsonAsync(response);\n    }\n});\n",[2975,10703,10704,10723,10727,10749,10753,10775,10779,10790,10794,10813,10830,10849,10876,10880,10895,10918,10941,10961,10980,11002,11007,11011,11015,11037,11041],{"__ignoreMap":2973},[2978,10705,10706,10708,10710,10712,10714,10717,10719,10721],{"class":2980,"line":2981},[2978,10707,4232],{"class":3418},[2978,10709,3119],{"class":3049},[2978,10711,4237],{"class":2991},[2978,10713,3443],{"class":3049},[2978,10715,10716],{"class":2995},"\"/health/custom\"",[2978,10718,4122],{"class":3049},[2978,10720,4130],{"class":3192},[2978,10722,4249],{"class":3498},[2978,10724,10725],{"class":2980,"line":2988},[2978,10726,3510],{"class":3049},[2978,10728,10729,10731,10733,10736,10738,10741,10743,10746],{"class":2980,"line":2999},[2978,10730,4792],{"class":3418},[2978,10732,3556],{"class":3049},[2978,10734,10735],{"class":3192},"async",[2978,10737,5924],{"class":3049},[2978,10739,10740],{"class":3418},"context",[2978,10742,4122],{"class":3049},[2978,10744,10745],{"class":3418},"report",[2978,10747,10748],{"class":3049},") =>\n",[2978,10750,10751],{"class":2980,"line":3018},[2978,10752,3545],{"class":3049},[2978,10754,10755,10758,10760,10763,10765,10768,10770,10773],{"class":2980,"line":3025},[2978,10756,10757],{"class":3418},"        context",[2978,10759,3119],{"class":3049},[2978,10761,10762],{"class":3418},"Response",[2978,10764,3119],{"class":3049},[2978,10766,10767],{"class":3418},"ContentType",[2978,10769,3556],{"class":3049},[2978,10771,10772],{"class":2995},"\"application/json\"",[2978,10774,4539],{"class":3049},[2978,10776,10777],{"class":2980,"line":3031},[2978,10778,3022],{"emptyLinePlaceholder":3021},[2978,10780,10781,10783,10785,10787],{"class":2980,"line":3040},[2978,10782,3550],{"class":3192},[2978,10784,7304],{"class":3418},[2978,10786,3556],{"class":3049},[2978,10788,10789],{"class":3192},"new\n",[2978,10791,10792],{"class":2980,"line":3059},[2978,10793,5848],{"class":3049},[2978,10795,10796,10799,10801,10803,10805,10807,10809,10811],{"class":2980,"line":3076},[2978,10797,10798],{"class":3418},"            status",[2978,10800,3556],{"class":3049},[2978,10802,10745],{"class":3418},[2978,10804,3119],{"class":3049},[2978,10806,9277],{"class":3418},[2978,10808,3119],{"class":3049},[2978,10810,10474],{"class":2991},[2978,10812,10477],{"class":3049},[2978,10814,10815,10818,10820,10823,10825,10828],{"class":2980,"line":3081},[2978,10816,10817],{"class":3418},"            timestamp",[2978,10819,3556],{"class":3049},[2978,10821,10822],{"class":3418},"DateTime",[2978,10824,3119],{"class":3049},[2978,10826,10827],{"class":3418},"UtcNow",[2978,10829,5062],{"class":3049},[2978,10831,10832,10835,10837,10839,10841,10843,10845,10847],{"class":2980,"line":3246},[2978,10833,10834],{"class":3418},"            duration",[2978,10836,3556],{"class":3049},[2978,10838,10745],{"class":3418},[2978,10840,3119],{"class":3049},[2978,10842,9288],{"class":3418},[2978,10844,3119],{"class":3049},[2978,10846,9293],{"class":3418},[2978,10848,5062],{"class":3049},[2978,10850,10851,10854,10856,10858,10860,10862,10864,10867,10869,10872,10874],{"class":2980,"line":3256},[2978,10852,10853],{"class":3418},"            checks",[2978,10855,3556],{"class":3049},[2978,10857,10745],{"class":3418},[2978,10859,3119],{"class":3049},[2978,10861,9326],{"class":3418},[2978,10863,3119],{"class":3049},[2978,10865,10866],{"class":2991},"Select",[2978,10868,3443],{"class":3049},[2978,10870,10871],{"class":3418},"e",[2978,10873,4266],{"class":3049},[2978,10875,10789],{"class":3192},[2978,10877,10878],{"class":2980,"line":3261},[2978,10879,5939],{"class":3049},[2978,10881,10882,10885,10887,10889,10891,10893],{"class":2980,"line":3267},[2978,10883,10884],{"class":3418},"                name",[2978,10886,3556],{"class":3049},[2978,10888,10871],{"class":3418},[2978,10890,3119],{"class":3049},[2978,10892,9360],{"class":3418},[2978,10894,5062],{"class":3049},[2978,10896,10897,10900,10902,10904,10906,10908,10910,10912,10914,10916],{"class":2980,"line":3276},[2978,10898,10899],{"class":3418},"                status",[2978,10901,3556],{"class":3049},[2978,10903,10871],{"class":3418},[2978,10905,3119],{"class":3049},[2978,10907,9371],{"class":3418},[2978,10909,3119],{"class":3049},[2978,10911,9277],{"class":3418},[2978,10913,3119],{"class":3049},[2978,10915,10474],{"class":2991},[2978,10917,10477],{"class":3049},[2978,10919,10920,10923,10925,10927,10929,10931,10933,10935,10937,10939],{"class":2980,"line":3836},[2978,10921,10922],{"class":3418},"                duration",[2978,10924,3556],{"class":3049},[2978,10926,10871],{"class":3418},[2978,10928,3119],{"class":3049},[2978,10930,9371],{"class":3418},[2978,10932,3119],{"class":3049},[2978,10934,9390],{"class":3418},[2978,10936,3119],{"class":3049},[2978,10938,9293],{"class":3418},[2978,10940,5062],{"class":3049},[2978,10942,10943,10946,10948,10950,10952,10954,10956,10959],{"class":2980,"line":4741},[2978,10944,10945],{"class":3418},"                description",[2978,10947,3556],{"class":3049},[2978,10949,10871],{"class":3418},[2978,10951,3119],{"class":3049},[2978,10953,9371],{"class":3418},[2978,10955,3119],{"class":3049},[2978,10957,10958],{"class":3418},"Description",[2978,10960,5062],{"class":3049},[2978,10962,10963,10965,10967,10969,10971,10973,10975,10978],{"class":2980,"line":4753},[2978,10964,7042],{"class":3418},[2978,10966,3556],{"class":3049},[2978,10968,10871],{"class":3418},[2978,10970,3119],{"class":3049},[2978,10972,9371],{"class":3418},[2978,10974,3119],{"class":3049},[2978,10976,10977],{"class":3418},"Data",[2978,10979,5062],{"class":3049},[2978,10981,10982,10984,10986,10988,10990,10992,10994,10996,10999],{"class":2980,"line":4758},[2978,10983,7675],{"class":3418},[2978,10985,3556],{"class":3049},[2978,10987,10871],{"class":3418},[2978,10989,3119],{"class":3049},[2978,10991,9371],{"class":3418},[2978,10993,3119],{"class":3049},[2978,10995,6453],{"class":3418},[2978,10997,10998],{"class":3049},"?.",[2978,11000,11001],{"class":3418},"Message\n",[2978,11003,11004],{"class":2980,"line":4764},[2978,11005,11006],{"class":3049},"            })\n",[2978,11008,11009],{"class":2980,"line":4784},[2978,11010,6911],{"class":3049},[2978,11012,11013],{"class":2980,"line":4789},[2978,11014,3022],{"emptyLinePlaceholder":3021},[2978,11016,11017,11020,11022,11024,11026,11028,11031,11033,11035],{"class":2980,"line":4805},[2978,11018,11019],{"class":3192},"        await",[2978,11021,3538],{"class":3418},[2978,11023,3119],{"class":3049},[2978,11025,10762],{"class":3418},[2978,11027,3119],{"class":3049},[2978,11029,11030],{"class":2991},"WriteAsJsonAsync",[2978,11032,3443],{"class":3049},[2978,11034,7401],{"class":3418},[2978,11036,3477],{"class":3049},[2978,11038,11039],{"class":2980,"line":4810},[2978,11040,3617],{"class":3049},[2978,11042,11043],{"class":2980,"line":4815},[2978,11044,4289],{"class":3049},[3735,11046],{},[2959,11048,11050],{"id":11049},"практичні-завдання","Практичні завдання",[3351,11052,11054],{"id":11053},"рівень-1-базове-розуміння","Рівень 1: Базове розуміння",[4363,11056,11057,11061,11064,11081,11136,11140,11146,11160],{},[3351,11058,11060],{"id":11059},"завдання-11-liveness-vs-readiness","Завдання 1.1: Liveness vs Readiness",[2964,11062,11063],{},"Які health checks мають бути у liveness probe, а які у readiness probe?",[4980,11065,11066,11069,11072,11075,11078],{},[3095,11067,11068],{},"Перевірка підключення до БД",[3095,11070,11071],{},"Перевірка використання пам'яті",[3095,11073,11074],{},"Перевірка вільного місця на диску",[3095,11076,11077],{},"Перевірка доступності Redis",[3095,11079,11080],{},"Перевірка зовнішнього API",[11082,11083,11085,11090,11102,11107,11130],"collapsible",{"title":11084},"Показати відповіді",[2964,11086,11087],{},[3088,11088,11089],{},"Liveness (чи процес живий?):",[3092,11091,11092,11095],{},[3095,11093,11094],{},"2. Перевірка використання пам'яті (deadlock detection)",[3095,11096,11097],{},[4980,11098,11099],{"start":2999},[3095,11100,11101],{},"Перевірка вільного місця на диску (критичний ресурс)",[2964,11103,11104],{},[3088,11105,11106],{},"Readiness (чи готовий приймати трафік?):",[3092,11108,11109,11116,11123],{},[3095,11110,11111],{},[4980,11112,11113],{},[3095,11114,11115],{},"Перевірка підключення до БД (залежність)",[3095,11117,11118],{},[4980,11119,11120],{"start":3018},[3095,11121,11122],{},"Перевірка доступності Redis (залежність)",[3095,11124,11125],{},[4980,11126,11127],{"start":3025},[3095,11128,11129],{},"Перевірка зовнішнього API (залежність)",[2964,11131,11132,11135],{},[3088,11133,11134],{},"Правило:"," Liveness перевіряє сам процес, Readiness перевіряє залежності.",[3351,11137,11139],{"id":11138},"завдання-12-healthstatus","Завдання 1.2: HealthStatus",[2964,11141,11142,11143,11145],{},"Який ",[2975,11144,5271],{}," повернути у кожному сценарії?",[4980,11147,11148,11151,11154,11157],{},[3095,11149,11150],{},"База даних недоступна",[3095,11152,11153],{},"Redis недоступний (API може працювати без кешу)",[3095,11155,11156],{},"Зовнішній API відповідає повільно (> 5 секунд)",[3095,11158,11159],{},"Вільно 500 MB на диску (поріг 1 GB)",[11082,11161,11162],{"title":11084},[4980,11163,11164,11169,11174,11179],{},[3095,11165,11166,11168],{},[3088,11167,3605],{}," — БД критична для роботи",[3095,11170,11171,11173],{},[3088,11172,4050],{}," — API працює, але повільніше без кешу",[3095,11175,11176,11178],{},[3088,11177,4050],{}," — працює, але повільно",[3095,11180,11181,11183],{},[3088,11182,4050],{}," — працює, але скоро буде проблема",[3735,11185],{},[3351,11187,11189],{"id":11188},"рівень-2-логіка-та-розширення","Рівень 2: Логіка та розширення",[4363,11191,11192,11196,11199,11745,11749,11752,12245,12249,12252],{},[3351,11193,11195],{"id":11194},"завдання-21-database-connection-pool-health-check","Завдання 2.1: Database Connection Pool Health Check",[2964,11197,11198],{},"Створіть health check для перевірки connection pool:",[11082,11200,11202],{"title":11201},"Показати рішення",[2968,11203,11205],{"className":3409,"code":11204,"language":3411,"meta":2973,"style":2973},"public class DatabaseConnectionPoolHealthCheck : IHealthCheck\n{\n    private readonly string _connectionString;\n\n    public DatabaseConnectionPoolHealthCheck(string connectionString)\n    {\n        _connectionString = connectionString;\n    }\n\n    public async Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        try\n        {\n            using var connection = new SqlConnection(_connectionString);\n            await connection.OpenAsync(cancellationToken);\n\n            // Перевіряємо connection pool statistics\n            var poolSize = connection.Database; // Simplified - у production використовуйте performance counters\n\n            var data = new Dictionary\u003Cstring, object>\n            {\n                [\"ConnectionState\"] = connection.State.ToString(),\n                [\"Database\"] = connection.Database,\n                [\"ServerVersion\"] = connection.ServerVersion\n            };\n\n            // Виконуємо тестовий запит\n            using var command = connection.CreateCommand();\n            command.CommandText = \"SELECT @@VERSION\";\n            command.CommandTimeout = 5;\n            \n            var version = await command.ExecuteScalarAsync(cancellationToken);\n\n            return HealthCheckResult.Healthy(\n                \"Database connection pool healthy\",\n                data: data);\n        }\n        catch (SqlException ex) when (ex.Number == -2) // Timeout\n        {\n            return HealthCheckResult.Degraded(\n                \"Database connection timeout\",\n                exception: ex);\n        }\n        catch (Exception ex)\n        {\n            return HealthCheckResult.Unhealthy(\n                \"Database connection failed\",\n                exception: ex);\n        }\n    }\n}\n",[2975,11206,11207,11220,11224,11237,11241,11255,11259,11270,11274,11278,11296,11304,11316,11320,11324,11328,11353,11371,11375,11380,11402,11406,11428,11432,11454,11470,11486,11490,11494,11499,11519,11536,11551,11555,11579,11583,11595,11602,11612,11616,11651,11655,11667,11674,11684,11688,11700,11704,11716,11723,11733,11737,11741],{"__ignoreMap":2973},[2978,11208,11209,11211,11213,11216,11218],{"class":2980,"line":2981},[2978,11210,3492],{"class":3192},[2978,11212,3495],{"class":3192},[2978,11214,11215],{"class":3498}," DatabaseConnectionPoolHealthCheck",[2978,11217,3502],{"class":3049},[2978,11219,3505],{"class":3498},[2978,11221,11222],{"class":2980,"line":2988},[2978,11223,3510],{"class":3049},[2978,11225,11226,11228,11230,11232,11235],{"class":2980,"line":2999},[2978,11227,5731],{"class":3192},[2978,11229,5734],{"class":3192},[2978,11231,7150],{"class":3192},[2978,11233,11234],{"class":3418}," _connectionString",[2978,11236,4539],{"class":3049},[2978,11238,11239],{"class":2980,"line":3018},[2978,11240,3022],{"emptyLinePlaceholder":3021},[2978,11242,11243,11245,11247,11249,11251,11253],{"class":2980,"line":3025},[2978,11244,3515],{"class":3192},[2978,11246,11215],{"class":2991},[2978,11248,3443],{"class":3049},[2978,11250,6039],{"class":3192},[2978,11252,5157],{"class":3418},[2978,11254,3175],{"class":3049},[2978,11256,11257],{"class":2980,"line":3031},[2978,11258,3545],{"class":3049},[2978,11260,11261,11264,11266,11268],{"class":2980,"line":3040},[2978,11262,11263],{"class":3418},"        _connectionString",[2978,11265,3556],{"class":3049},[2978,11267,3446],{"class":3418},[2978,11269,4539],{"class":3049},[2978,11271,11272],{"class":2980,"line":3059},[2978,11273,3617],{"class":3049},[2978,11275,11276],{"class":2980,"line":3076},[2978,11277,3022],{"emptyLinePlaceholder":3021},[2978,11279,11280,11282,11284,11286,11288,11290,11292,11294],{"class":2980,"line":3081},[2978,11281,3515],{"class":3192},[2978,11283,7225],{"class":3192},[2978,11285,3518],{"class":3498},[2978,11287,3521],{"class":3049},[2978,11289,3524],{"class":3498},[2978,11291,3527],{"class":3049},[2978,11293,3530],{"class":2991},[2978,11295,5238],{"class":3049},[2978,11297,11298,11300,11302],{"class":2980,"line":3246},[2978,11299,5815],{"class":3498},[2978,11301,3538],{"class":3418},[2978,11303,5062],{"class":3049},[2978,11305,11306,11308,11310,11312,11314],{"class":2980,"line":3256},[2978,11307,5824],{"class":3498},[2978,11309,5827],{"class":3418},[2978,11311,3556],{"class":3049},[2978,11313,5832],{"class":3192},[2978,11315,3175],{"class":3049},[2978,11317,11318],{"class":2980,"line":3261},[2978,11319,3545],{"class":3049},[2978,11321,11322],{"class":2980,"line":3267},[2978,11323,5843],{"class":3567},[2978,11325,11326],{"class":2980,"line":3276},[2978,11327,5848],{"class":3049},[2978,11329,11330,11333,11336,11339,11341,11343,11346,11348,11351],{"class":2980,"line":3836},[2978,11331,11332],{"class":3567},"            using",[2978,11334,11335],{"class":3192}," var",[2978,11337,11338],{"class":3418}," connection",[2978,11340,3556],{"class":3049},[2978,11342,4130],{"class":3192},[2978,11344,11345],{"class":3498}," SqlConnection",[2978,11347,3443],{"class":3049},[2978,11349,11350],{"class":3418},"_connectionString",[2978,11352,3477],{"class":3049},[2978,11354,11355,11358,11360,11362,11365,11367,11369],{"class":2980,"line":4741},[2978,11356,11357],{"class":3192},"            await",[2978,11359,11338],{"class":3418},[2978,11361,3119],{"class":3049},[2978,11363,11364],{"class":2991},"OpenAsync",[2978,11366,3443],{"class":3049},[2978,11368,7326],{"class":3418},[2978,11370,3477],{"class":3049},[2978,11372,11373],{"class":2980,"line":4753},[2978,11374,3022],{"emptyLinePlaceholder":3021},[2978,11376,11377],{"class":2980,"line":4758},[2978,11378,11379],{"class":2984},"            // Перевіряємо connection pool statistics\n",[2978,11381,11382,11384,11387,11389,11392,11394,11397,11399],{"class":2980,"line":4764},[2978,11383,5853],{"class":3192},[2978,11385,11386],{"class":3418}," poolSize",[2978,11388,3556],{"class":3049},[2978,11390,11391],{"class":3418},"connection",[2978,11393,3119],{"class":3049},[2978,11395,11396],{"class":3418},"Database",[2978,11398,8195],{"class":3049},[2978,11400,11401],{"class":2984},"// Simplified - у production використовуйте performance counters\n",[2978,11403,11404],{"class":2980,"line":4784},[2978,11405,3022],{"emptyLinePlaceholder":3021},[2978,11407,11408,11410,11412,11414,11416,11418,11420,11422,11424,11426],{"class":2980,"line":4789},[2978,11409,5853],{"class":3192},[2978,11411,6027],{"class":3418},[2978,11413,3556],{"class":3049},[2978,11415,4130],{"class":3192},[2978,11417,6034],{"class":3498},[2978,11419,3521],{"class":3049},[2978,11421,6039],{"class":3192},[2978,11423,4122],{"class":3049},[2978,11425,6044],{"class":3192},[2978,11427,6047],{"class":3049},[2978,11429,11430],{"class":2980,"line":4805},[2978,11431,5939],{"class":3049},[2978,11433,11434,11436,11439,11441,11443,11445,11448,11450,11452],{"class":2980,"line":4810},[2978,11435,6056],{"class":3049},[2978,11437,11438],{"class":2995},"\"ConnectionState\"",[2978,11440,6062],{"class":3049},[2978,11442,11391],{"class":3418},[2978,11444,3119],{"class":3049},[2978,11446,11447],{"class":3418},"State",[2978,11449,3119],{"class":3049},[2978,11451,10474],{"class":2991},[2978,11453,10477],{"class":3049},[2978,11455,11456,11458,11460,11462,11464,11466,11468],{"class":2980,"line":4815},[2978,11457,6056],{"class":3049},[2978,11459,10128],{"class":2995},[2978,11461,6062],{"class":3049},[2978,11463,11391],{"class":3418},[2978,11465,3119],{"class":3049},[2978,11467,11396],{"class":3418},[2978,11469,5062],{"class":3049},[2978,11471,11472,11474,11477,11479,11481,11483],{"class":2980,"line":4834},[2978,11473,6056],{"class":3049},[2978,11475,11476],{"class":2995},"\"ServerVersion\"",[2978,11478,6062],{"class":3049},[2978,11480,11391],{"class":3418},[2978,11482,3119],{"class":3049},[2978,11484,11485],{"class":3418},"ServerVersion\n",[2978,11487,11488],{"class":2980,"line":4839},[2978,11489,6189],{"class":3049},[2978,11491,11492],{"class":2980,"line":4867},[2978,11493,3022],{"emptyLinePlaceholder":3021},[2978,11495,11496],{"class":2980,"line":4880},[2978,11497,11498],{"class":2984},"            // Виконуємо тестовий запит\n",[2978,11500,11501,11503,11505,11508,11510,11512,11514,11517],{"class":2980,"line":4885},[2978,11502,11332],{"class":3567},[2978,11504,11335],{"class":3192},[2978,11506,11507],{"class":3418}," command",[2978,11509,3556],{"class":3049},[2978,11511,11391],{"class":3418},[2978,11513,3119],{"class":3049},[2978,11515,11516],{"class":2991},"CreateCommand",[2978,11518,3562],{"class":3049},[2978,11520,11521,11524,11526,11529,11531,11534],{"class":2980,"line":4890},[2978,11522,11523],{"class":3418},"            command",[2978,11525,3119],{"class":3049},[2978,11527,11528],{"class":3418},"CommandText",[2978,11530,3556],{"class":3049},[2978,11532,11533],{"class":2995},"\"SELECT @@VERSION\"",[2978,11535,4539],{"class":3049},[2978,11537,11538,11540,11542,11545,11547,11549],{"class":2980,"line":4909},[2978,11539,11523],{"class":3418},[2978,11541,3119],{"class":3049},[2978,11543,11544],{"class":3418},"CommandTimeout",[2978,11546,3556],{"class":3049},[2978,11548,5317],{"class":3005},[2978,11550,4539],{"class":3049},[2978,11552,11553],{"class":2980,"line":4914},[2978,11554,10560],{"class":3049},[2978,11556,11557,11559,11562,11564,11566,11568,11570,11573,11575,11577],{"class":2980,"line":4941},[2978,11558,5853],{"class":3192},[2978,11560,11561],{"class":3418}," version",[2978,11563,3556],{"class":3049},[2978,11565,7309],{"class":3192},[2978,11567,11507],{"class":3418},[2978,11569,3119],{"class":3049},[2978,11571,11572],{"class":2991},"ExecuteScalarAsync",[2978,11574,3443],{"class":3049},[2978,11576,7326],{"class":3418},[2978,11578,3477],{"class":3049},[2978,11580,11581],{"class":2980,"line":4954},[2978,11582,3022],{"emptyLinePlaceholder":3021},[2978,11584,11585,11587,11589,11591,11593],{"class":2980,"line":4959},[2978,11586,6384],{"class":3567},[2978,11588,4019],{"class":3418},[2978,11590,3119],{"class":3049},[2978,11592,3591],{"class":2991},[2978,11594,5238],{"class":3049},[2978,11596,11597,11600],{"class":2980,"line":4964},[2978,11598,11599],{"class":2995},"                \"Database connection pool healthy\"",[2978,11601,5062],{"class":3049},[2978,11603,11604,11606,11608,11610],{"class":2980,"line":6186},[2978,11605,7042],{"class":3418},[2978,11607,3669],{"class":3049},[2978,11609,6276],{"class":3418},[2978,11611,3477],{"class":3049},[2978,11613,11614],{"class":2980,"line":6192},[2978,11615,6442],{"class":3049},[2978,11617,11618,11620,11622,11625,11627,11629,11632,11634,11636,11638,11641,11644,11646,11648],{"class":2980,"line":6197},[2978,11619,6448],{"class":3567},[2978,11621,5924],{"class":3049},[2978,11623,11624],{"class":3498},"SqlException",[2978,11626,6456],{"class":3418},[2978,11628,5767],{"class":3049},[2978,11630,11631],{"class":3567},"when",[2978,11633,5924],{"class":3049},[2978,11635,6506],{"class":3418},[2978,11637,3119],{"class":3049},[2978,11639,11640],{"class":3418},"Number",[2978,11642,11643],{"class":3049}," == -",[2978,11645,3989],{"class":3005},[2978,11647,5767],{"class":3049},[2978,11649,11650],{"class":2984},"// Timeout\n",[2978,11652,11653],{"class":2980,"line":6214},[2978,11654,5848],{"class":3049},[2978,11656,11657,11659,11661,11663,11665],{"class":2980,"line":6219},[2978,11658,6384],{"class":3567},[2978,11660,4019],{"class":3418},[2978,11662,3119],{"class":3049},[2978,11664,4050],{"class":2991},[2978,11666,5238],{"class":3049},[2978,11668,11669,11672],{"class":2980,"line":6232},[2978,11670,11671],{"class":2995},"                \"Database connection timeout\"",[2978,11673,5062],{"class":3049},[2978,11675,11676,11678,11680,11682],{"class":2980,"line":6243},[2978,11677,7675],{"class":3418},[2978,11679,3669],{"class":3049},[2978,11681,6506],{"class":3418},[2978,11683,3477],{"class":3049},[2978,11685,11686],{"class":2980,"line":6268},[2978,11687,6442],{"class":3049},[2978,11689,11690,11692,11694,11696,11698],{"class":2980,"line":6281},[2978,11691,6448],{"class":3567},[2978,11693,5924],{"class":3049},[2978,11695,6453],{"class":3498},[2978,11697,6456],{"class":3418},[2978,11699,3175],{"class":3049},[2978,11701,11702],{"class":2980,"line":6286},[2978,11703,5848],{"class":3049},[2978,11705,11706,11708,11710,11712,11714],{"class":2980,"line":6291},[2978,11707,6384],{"class":3567},[2978,11709,4019],{"class":3418},[2978,11711,3119],{"class":3049},[2978,11713,3605],{"class":2991},[2978,11715,5238],{"class":3049},[2978,11717,11718,11721],{"class":2980,"line":6311},[2978,11719,11720],{"class":2995},"                \"Database connection failed\"",[2978,11722,5062],{"class":3049},[2978,11724,11725,11727,11729,11731],{"class":2980,"line":6316},[2978,11726,7675],{"class":3418},[2978,11728,3669],{"class":3049},[2978,11730,6506],{"class":3418},[2978,11732,3477],{"class":3049},[2978,11734,11735],{"class":2980,"line":6329},[2978,11736,6442],{"class":3049},[2978,11738,11739],{"class":2980,"line":6340},[2978,11740,3617],{"class":3049},[2978,11742,11743],{"class":2980,"line":6360},[2978,11744,3622],{"class":3049},[3351,11746,11748],{"id":11747},"завдання-22-rate-limiting-health-check","Завдання 2.2: Rate Limiting Health Check",[2964,11750,11751],{},"Перевірте, чи не досягнуто ліміту rate limiting:",[11082,11753,11754],{"title":11201},[2968,11755,11757],{"className":3409,"code":11756,"language":3411,"meta":2973,"style":2973},"public class RateLimitHealthCheck : IHealthCheck\n{\n    private readonly IRateLimitService _rateLimitService;\n\n    public RateLimitHealthCheck(IRateLimitService rateLimitService)\n    {\n        _rateLimitService = rateLimitService;\n    }\n\n    public Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        var stats = _rateLimitService.GetStatistics();\n\n        var data = new Dictionary\u003Cstring, object>\n        {\n            [\"TotalRequests\"] = stats.TotalRequests,\n            [\"RejectedRequests\"] = stats.RejectedRequests,\n            [\"RejectionRate\"] = stats.RejectionRate,\n            [\"CurrentLimit\"] = stats.CurrentLimit\n        };\n\n        if (stats.RejectionRate > 0.5) // > 50% rejected\n        {\n            return Task.FromResult(\n                HealthCheckResult.Unhealthy(\n                    $\"High rejection rate: {stats.RejectionRate:P}\",\n                    data: data));\n        }\n\n        if (stats.RejectionRate > 0.2) // > 20% rejected\n        {\n            return Task.FromResult(\n                HealthCheckResult.Degraded(\n                    $\"Elevated rejection rate: {stats.RejectionRate:P}\",\n                    data: data));\n        }\n\n        return Task.FromResult(\n            HealthCheckResult.Healthy(\n                $\"Rate limiting normal: {stats.RejectionRate:P} rejected\",\n                data: data));\n    }\n}\n",[2975,11758,11759,11772,11776,11790,11794,11810,11814,11826,11830,11834,11850,11858,11870,11874,11893,11897,11919,11923,11942,11960,11978,11994,11998,12002,12024,12028,12040,12050,12074,12084,12088,12092,12114,12118,12130,12140,12163,12173,12177,12181,12193,12203,12227,12237,12241],{"__ignoreMap":2973},[2978,11760,11761,11763,11765,11768,11770],{"class":2980,"line":2981},[2978,11762,3492],{"class":3192},[2978,11764,3495],{"class":3192},[2978,11766,11767],{"class":3498}," RateLimitHealthCheck",[2978,11769,3502],{"class":3049},[2978,11771,3505],{"class":3498},[2978,11773,11774],{"class":2980,"line":2988},[2978,11775,3510],{"class":3049},[2978,11777,11778,11780,11782,11785,11788],{"class":2980,"line":2999},[2978,11779,5731],{"class":3192},[2978,11781,5734],{"class":3192},[2978,11783,11784],{"class":3498}," IRateLimitService",[2978,11786,11787],{"class":3418}," _rateLimitService",[2978,11789,4539],{"class":3049},[2978,11791,11792],{"class":2980,"line":3018},[2978,11793,3022],{"emptyLinePlaceholder":3021},[2978,11795,11796,11798,11800,11802,11805,11808],{"class":2980,"line":3025},[2978,11797,3515],{"class":3192},[2978,11799,11767],{"class":2991},[2978,11801,3443],{"class":3049},[2978,11803,11804],{"class":3498},"IRateLimitService",[2978,11806,11807],{"class":3418}," rateLimitService",[2978,11809,3175],{"class":3049},[2978,11811,11812],{"class":2980,"line":3031},[2978,11813,3545],{"class":3049},[2978,11815,11816,11819,11821,11824],{"class":2980,"line":3040},[2978,11817,11818],{"class":3418},"        _rateLimitService",[2978,11820,3556],{"class":3049},[2978,11822,11823],{"class":3418},"rateLimitService",[2978,11825,4539],{"class":3049},[2978,11827,11828],{"class":2980,"line":3059},[2978,11829,3617],{"class":3049},[2978,11831,11832],{"class":2980,"line":3076},[2978,11833,3022],{"emptyLinePlaceholder":3021},[2978,11835,11836,11838,11840,11842,11844,11846,11848],{"class":2980,"line":3081},[2978,11837,3515],{"class":3192},[2978,11839,3518],{"class":3498},[2978,11841,3521],{"class":3049},[2978,11843,3524],{"class":3498},[2978,11845,3527],{"class":3049},[2978,11847,3530],{"class":2991},[2978,11849,5238],{"class":3049},[2978,11851,11852,11854,11856],{"class":2980,"line":3246},[2978,11853,5815],{"class":3498},[2978,11855,3538],{"class":3418},[2978,11857,5062],{"class":3049},[2978,11859,11860,11862,11864,11866,11868],{"class":2980,"line":3256},[2978,11861,5824],{"class":3498},[2978,11863,5827],{"class":3418},[2978,11865,3556],{"class":3049},[2978,11867,5832],{"class":3192},[2978,11869,3175],{"class":3049},[2978,11871,11872],{"class":2980,"line":3261},[2978,11873,3545],{"class":3049},[2978,11875,11876,11878,11881,11883,11886,11888,11891],{"class":2980,"line":3267},[2978,11877,3550],{"class":3192},[2978,11879,11880],{"class":3418}," stats",[2978,11882,3556],{"class":3049},[2978,11884,11885],{"class":3418},"_rateLimitService",[2978,11887,3119],{"class":3049},[2978,11889,11890],{"class":2991},"GetStatistics",[2978,11892,3562],{"class":3049},[2978,11894,11895],{"class":2980,"line":3276},[2978,11896,3022],{"emptyLinePlaceholder":3021},[2978,11898,11899,11901,11903,11905,11907,11909,11911,11913,11915,11917],{"class":2980,"line":3836},[2978,11900,3550],{"class":3192},[2978,11902,6027],{"class":3418},[2978,11904,3556],{"class":3049},[2978,11906,4130],{"class":3192},[2978,11908,6034],{"class":3498},[2978,11910,3521],{"class":3049},[2978,11912,6039],{"class":3192},[2978,11914,4122],{"class":3049},[2978,11916,6044],{"class":3192},[2978,11918,6047],{"class":3049},[2978,11920,11921],{"class":2980,"line":4741},[2978,11922,5848],{"class":3049},[2978,11924,11925,11927,11930,11932,11935,11937,11940],{"class":2980,"line":4753},[2978,11926,6820],{"class":3049},[2978,11928,11929],{"class":2995},"\"TotalRequests\"",[2978,11931,6062],{"class":3049},[2978,11933,11934],{"class":3418},"stats",[2978,11936,3119],{"class":3049},[2978,11938,11939],{"class":3418},"TotalRequests",[2978,11941,5062],{"class":3049},[2978,11943,11944,11946,11949,11951,11953,11955,11958],{"class":2980,"line":4758},[2978,11945,6820],{"class":3049},[2978,11947,11948],{"class":2995},"\"RejectedRequests\"",[2978,11950,6062],{"class":3049},[2978,11952,11934],{"class":3418},[2978,11954,3119],{"class":3049},[2978,11956,11957],{"class":3418},"RejectedRequests",[2978,11959,5062],{"class":3049},[2978,11961,11962,11964,11967,11969,11971,11973,11976],{"class":2980,"line":4764},[2978,11963,6820],{"class":3049},[2978,11965,11966],{"class":2995},"\"RejectionRate\"",[2978,11968,6062],{"class":3049},[2978,11970,11934],{"class":3418},[2978,11972,3119],{"class":3049},[2978,11974,11975],{"class":3418},"RejectionRate",[2978,11977,5062],{"class":3049},[2978,11979,11980,11982,11985,11987,11989,11991],{"class":2980,"line":4784},[2978,11981,6820],{"class":3049},[2978,11983,11984],{"class":2995},"\"CurrentLimit\"",[2978,11986,6062],{"class":3049},[2978,11988,11934],{"class":3418},[2978,11990,3119],{"class":3049},[2978,11992,11993],{"class":3418},"CurrentLimit\n",[2978,11995,11996],{"class":2980,"line":4789},[2978,11997,6911],{"class":3049},[2978,11999,12000],{"class":2980,"line":4805},[2978,12001,3022],{"emptyLinePlaceholder":3021},[2978,12003,12004,12006,12008,12010,12012,12014,12016,12019,12021],{"class":2980,"line":4810},[2978,12005,6920],{"class":3567},[2978,12007,5924],{"class":3049},[2978,12009,11934],{"class":3418},[2978,12011,3119],{"class":3049},[2978,12013,11975],{"class":3418},[2978,12015,3573],{"class":3049},[2978,12017,12018],{"class":3005},"0.5",[2978,12020,5767],{"class":3049},[2978,12022,12023],{"class":2984},"// > 50% rejected\n",[2978,12025,12026],{"class":2980,"line":4815},[2978,12027,5848],{"class":3049},[2978,12029,12030,12032,12034,12036,12038],{"class":2980,"line":4834},[2978,12031,6384],{"class":3567},[2978,12033,3518],{"class":3418},[2978,12035,3119],{"class":3049},[2978,12037,5951],{"class":2991},[2978,12039,5238],{"class":3049},[2978,12041,12042,12044,12046,12048],{"class":2980,"line":4839},[2978,12043,6398],{"class":3418},[2978,12045,3119],{"class":3049},[2978,12047,3605],{"class":2991},[2978,12049,5238],{"class":3049},[2978,12051,12052,12055,12057,12059,12061,12063,12065,12068,12070,12072],{"class":2980,"line":4867},[2978,12053,12054],{"class":2995},"                    $\"High rejection rate: ",[2978,12056,6250],{"class":6249},[2978,12058,11934],{"class":3418},[2978,12060,3119],{"class":6249},[2978,12062,11975],{"class":3418},[2978,12064,3365],{"class":3049},[2978,12066,12067],{"class":3418},"P",[2978,12069,6260],{"class":6249},[2978,12071,7483],{"class":2995},[2978,12073,5062],{"class":3049},[2978,12075,12076,12078,12080,12082],{"class":2980,"line":4880},[2978,12077,6430],{"class":3418},[2978,12079,3669],{"class":3049},[2978,12081,6276],{"class":3418},[2978,12083,5320],{"class":3049},[2978,12085,12086],{"class":2980,"line":4885},[2978,12087,6442],{"class":3049},[2978,12089,12090],{"class":2980,"line":4890},[2978,12091,3022],{"emptyLinePlaceholder":3021},[2978,12093,12094,12096,12098,12100,12102,12104,12106,12109,12111],{"class":2980,"line":4909},[2978,12095,6920],{"class":3567},[2978,12097,5924],{"class":3049},[2978,12099,11934],{"class":3418},[2978,12101,3119],{"class":3049},[2978,12103,11975],{"class":3418},[2978,12105,3573],{"class":3049},[2978,12107,12108],{"class":3005},"0.2",[2978,12110,5767],{"class":3049},[2978,12112,12113],{"class":2984},"// > 20% rejected\n",[2978,12115,12116],{"class":2980,"line":4914},[2978,12117,5848],{"class":3049},[2978,12119,12120,12122,12124,12126,12128],{"class":2980,"line":4941},[2978,12121,6384],{"class":3567},[2978,12123,3518],{"class":3418},[2978,12125,3119],{"class":3049},[2978,12127,5951],{"class":2991},[2978,12129,5238],{"class":3049},[2978,12131,12132,12134,12136,12138],{"class":2980,"line":4954},[2978,12133,6398],{"class":3418},[2978,12135,3119],{"class":3049},[2978,12137,4050],{"class":2991},[2978,12139,5238],{"class":3049},[2978,12141,12142,12145,12147,12149,12151,12153,12155,12157,12159,12161],{"class":2980,"line":4959},[2978,12143,12144],{"class":2995},"                    $\"Elevated rejection rate: ",[2978,12146,6250],{"class":6249},[2978,12148,11934],{"class":3418},[2978,12150,3119],{"class":6249},[2978,12152,11975],{"class":3418},[2978,12154,3365],{"class":3049},[2978,12156,12067],{"class":3418},[2978,12158,6260],{"class":6249},[2978,12160,7483],{"class":2995},[2978,12162,5062],{"class":3049},[2978,12164,12165,12167,12169,12171],{"class":2980,"line":4964},[2978,12166,6430],{"class":3418},[2978,12168,3669],{"class":3049},[2978,12170,6276],{"class":3418},[2978,12172,5320],{"class":3049},[2978,12174,12175],{"class":2980,"line":6186},[2978,12176,6442],{"class":3049},[2978,12178,12179],{"class":2980,"line":6192},[2978,12180,3022],{"emptyLinePlaceholder":3021},[2978,12182,12183,12185,12187,12189,12191],{"class":2980,"line":6197},[2978,12184,3568],{"class":3567},[2978,12186,3518],{"class":3418},[2978,12188,3119],{"class":3049},[2978,12190,5951],{"class":2991},[2978,12192,5238],{"class":3049},[2978,12194,12195,12197,12199,12201],{"class":2980,"line":6214},[2978,12196,7012],{"class":3418},[2978,12198,3119],{"class":3049},[2978,12200,3591],{"class":2991},[2978,12202,5238],{"class":3049},[2978,12204,12205,12208,12210,12212,12214,12216,12218,12220,12222,12225],{"class":2980,"line":6219},[2978,12206,12207],{"class":2995},"                $\"Rate limiting normal: ",[2978,12209,6250],{"class":6249},[2978,12211,11934],{"class":3418},[2978,12213,3119],{"class":6249},[2978,12215,11975],{"class":3418},[2978,12217,3365],{"class":3049},[2978,12219,12067],{"class":3418},[2978,12221,6260],{"class":6249},[2978,12223,12224],{"class":2995}," rejected\"",[2978,12226,5062],{"class":3049},[2978,12228,12229,12231,12233,12235],{"class":2980,"line":6232},[2978,12230,7042],{"class":3418},[2978,12232,3669],{"class":3049},[2978,12234,6276],{"class":3418},[2978,12236,5320],{"class":3049},[2978,12238,12239],{"class":2980,"line":6243},[2978,12240,3617],{"class":3049},[2978,12242,12243],{"class":2980,"line":6268},[2978,12244,3622],{"class":3049},[3351,12246,12248],{"id":12247},"завдання-23-composite-health-check","Завдання 2.3: Composite Health Check",[2964,12250,12251],{},"Створіть health check, що агрегує результати кількох інших:",[11082,12253,12254],{"title":11201},[2968,12255,12257],{"className":3409,"code":12256,"language":3411,"meta":2973,"style":2973},"public class CompositeHealthCheck : IHealthCheck\n{\n    private readonly IHealthCheckService _healthCheckService;\n\n    public CompositeHealthCheck(IHealthCheckService healthCheckService)\n    {\n        _healthCheckService = healthCheckService;\n    }\n\n    public async Task\u003CHealthCheckResult> CheckHealthAsync(\n        HealthCheckContext context,\n        CancellationToken cancellationToken = default)\n    {\n        // Виконуємо всі \"ready\" чеки\n        var report = await _healthCheckService.CheckHealthAsync(\n            check => check.Tags.Contains(\"ready\"),\n            cancellationToken);\n\n        var data = new Dictionary\u003Cstring, object>();\n        var unhealthyChecks = new List\u003Cstring>();\n        var degradedChecks = new List\u003Cstring>();\n\n        foreach (var entry in report.Entries)\n        {\n            data[entry.Key] = entry.Value.Status.ToString();\n\n            if (entry.Value.Status == HealthStatus.Unhealthy)\n            {\n                unhealthyChecks.Add(entry.Key);\n            }\n            else if (entry.Value.Status == HealthStatus.Degraded)\n            {\n                degradedChecks.Add(entry.Key);\n            }\n        }\n\n        if (unhealthyChecks.Any())\n        {\n            return HealthCheckResult.Unhealthy(\n                $\"Unhealthy checks: {string.Join(\", \", unhealthyChecks)}\",\n                data: data);\n        }\n\n        if (degradedChecks.Any())\n        {\n            return HealthCheckResult.Degraded(\n                $\"Degraded checks: {string.Join(\", \", degradedChecks)}\",\n                data: data);\n        }\n\n        return HealthCheckResult.Healthy(\n            \"All checks passed\",\n            data: data);\n    }\n}\n",[2975,12258,12259,12272,12276,12290,12294,12310,12314,12326,12330,12334,12352,12360,12372,12376,12381,12399,12422,12429,12433,12455,12475,12494,12498,12518,12522,12555,12559,12585,12589,12609,12613,12643,12647,12666,12670,12674,12678,12694,12698,12710,12740,12750,12754,12758,12773,12777,12789,12816,12826,12830,12834,12846,12853,12863,12867],{"__ignoreMap":2973},[2978,12260,12261,12263,12265,12268,12270],{"class":2980,"line":2981},[2978,12262,3492],{"class":3192},[2978,12264,3495],{"class":3192},[2978,12266,12267],{"class":3498}," CompositeHealthCheck",[2978,12269,3502],{"class":3049},[2978,12271,3505],{"class":3498},[2978,12273,12274],{"class":2980,"line":2988},[2978,12275,3510],{"class":3049},[2978,12277,12278,12280,12282,12285,12288],{"class":2980,"line":2999},[2978,12279,5731],{"class":3192},[2978,12281,5734],{"class":3192},[2978,12283,12284],{"class":3498}," IHealthCheckService",[2978,12286,12287],{"class":3418}," _healthCheckService",[2978,12289,4539],{"class":3049},[2978,12291,12292],{"class":2980,"line":3018},[2978,12293,3022],{"emptyLinePlaceholder":3021},[2978,12295,12296,12298,12300,12302,12305,12308],{"class":2980,"line":3025},[2978,12297,3515],{"class":3192},[2978,12299,12267],{"class":2991},[2978,12301,3443],{"class":3049},[2978,12303,12304],{"class":3498},"IHealthCheckService",[2978,12306,12307],{"class":3418}," healthCheckService",[2978,12309,3175],{"class":3049},[2978,12311,12312],{"class":2980,"line":3031},[2978,12313,3545],{"class":3049},[2978,12315,12316,12319,12321,12324],{"class":2980,"line":3040},[2978,12317,12318],{"class":3418},"        _healthCheckService",[2978,12320,3556],{"class":3049},[2978,12322,12323],{"class":3418},"healthCheckService",[2978,12325,4539],{"class":3049},[2978,12327,12328],{"class":2980,"line":3059},[2978,12329,3617],{"class":3049},[2978,12331,12332],{"class":2980,"line":3076},[2978,12333,3022],{"emptyLinePlaceholder":3021},[2978,12335,12336,12338,12340,12342,12344,12346,12348,12350],{"class":2980,"line":3081},[2978,12337,3515],{"class":3192},[2978,12339,7225],{"class":3192},[2978,12341,3518],{"class":3498},[2978,12343,3521],{"class":3049},[2978,12345,3524],{"class":3498},[2978,12347,3527],{"class":3049},[2978,12349,3530],{"class":2991},[2978,12351,5238],{"class":3049},[2978,12353,12354,12356,12358],{"class":2980,"line":3246},[2978,12355,5815],{"class":3498},[2978,12357,3538],{"class":3418},[2978,12359,5062],{"class":3049},[2978,12361,12362,12364,12366,12368,12370],{"class":2980,"line":3256},[2978,12363,5824],{"class":3498},[2978,12365,5827],{"class":3418},[2978,12367,3556],{"class":3049},[2978,12369,5832],{"class":3192},[2978,12371,3175],{"class":3049},[2978,12373,12374],{"class":2980,"line":3261},[2978,12375,3545],{"class":3049},[2978,12377,12378],{"class":2980,"line":3267},[2978,12379,12380],{"class":2984},"        // Виконуємо всі \"ready\" чеки\n",[2978,12382,12383,12385,12387,12389,12391,12393,12395,12397],{"class":2980,"line":3276},[2978,12384,3550],{"class":3192},[2978,12386,9236],{"class":3418},[2978,12388,3556],{"class":3049},[2978,12390,7309],{"class":3192},[2978,12392,12287],{"class":3418},[2978,12394,3119],{"class":3049},[2978,12396,3530],{"class":2991},[2978,12398,5238],{"class":3049},[2978,12400,12401,12404,12406,12408,12410,12412,12414,12416,12418,12420],{"class":2980,"line":3836},[2978,12402,12403],{"class":3418},"            check",[2978,12405,4266],{"class":3049},[2978,12407,4263],{"class":3418},[2978,12409,3119],{"class":3049},[2978,12411,4273],{"class":3418},[2978,12413,3119],{"class":3049},[2978,12415,4278],{"class":2991},[2978,12417,3443],{"class":3049},[2978,12419,4141],{"class":2995},[2978,12421,4864],{"class":3049},[2978,12423,12424,12427],{"class":2980,"line":4741},[2978,12425,12426],{"class":3418},"            cancellationToken",[2978,12428,3477],{"class":3049},[2978,12430,12431],{"class":2980,"line":4753},[2978,12432,3022],{"emptyLinePlaceholder":3021},[2978,12434,12435,12437,12439,12441,12443,12445,12447,12449,12451,12453],{"class":2980,"line":4758},[2978,12436,3550],{"class":3192},[2978,12438,6027],{"class":3418},[2978,12440,3556],{"class":3049},[2978,12442,4130],{"class":3192},[2978,12444,6034],{"class":3498},[2978,12446,3521],{"class":3049},[2978,12448,6039],{"class":3192},[2978,12450,4122],{"class":3049},[2978,12452,6044],{"class":3192},[2978,12454,9460],{"class":3049},[2978,12456,12457,12459,12462,12464,12466,12469,12471,12473],{"class":2980,"line":4764},[2978,12458,3550],{"class":3192},[2978,12460,12461],{"class":3418}," unhealthyChecks",[2978,12463,3556],{"class":3049},[2978,12465,4130],{"class":3192},[2978,12467,12468],{"class":3498}," List",[2978,12470,3521],{"class":3049},[2978,12472,6039],{"class":3192},[2978,12474,9460],{"class":3049},[2978,12476,12477,12479,12482,12484,12486,12488,12490,12492],{"class":2980,"line":4784},[2978,12478,3550],{"class":3192},[2978,12480,12481],{"class":3418}," degradedChecks",[2978,12483,3556],{"class":3049},[2978,12485,4130],{"class":3192},[2978,12487,12468],{"class":3498},[2978,12489,3521],{"class":3049},[2978,12491,6039],{"class":3192},[2978,12493,9460],{"class":3049},[2978,12495,12496],{"class":2980,"line":4789},[2978,12497,3022],{"emptyLinePlaceholder":3021},[2978,12499,12500,12502,12504,12506,12508,12510,12512,12514,12516],{"class":2980,"line":4805},[2978,12501,9309],{"class":3567},[2978,12503,5924],{"class":3049},[2978,12505,4588],{"class":3192},[2978,12507,9316],{"class":3418},[2978,12509,9319],{"class":3567},[2978,12511,9236],{"class":3418},[2978,12513,3119],{"class":3049},[2978,12515,9326],{"class":3418},[2978,12517,3175],{"class":3049},[2978,12519,12520],{"class":2980,"line":4810},[2978,12521,5848],{"class":3049},[2978,12523,12524,12527,12530,12533,12535,12537,12539,12541,12543,12545,12547,12549,12551,12553],{"class":2980,"line":4815},[2978,12525,12526],{"class":3418},"            data",[2978,12528,12529],{"class":3049},"[",[2978,12531,12532],{"class":3418},"entry",[2978,12534,3119],{"class":3049},[2978,12536,9360],{"class":3418},[2978,12538,6062],{"class":3049},[2978,12540,12532],{"class":3418},[2978,12542,3119],{"class":3049},[2978,12544,9371],{"class":3418},[2978,12546,3119],{"class":3049},[2978,12548,9277],{"class":3418},[2978,12550,3119],{"class":3049},[2978,12552,10474],{"class":2991},[2978,12554,3562],{"class":3049},[2978,12556,12557],{"class":2980,"line":4834},[2978,12558,3022],{"emptyLinePlaceholder":3021},[2978,12560,12561,12563,12565,12567,12569,12571,12573,12575,12577,12579,12581,12583],{"class":2980,"line":4839},[2978,12562,5921],{"class":3567},[2978,12564,5924],{"class":3049},[2978,12566,12532],{"class":3418},[2978,12568,3119],{"class":3049},[2978,12570,9371],{"class":3418},[2978,12572,3119],{"class":3049},[2978,12574,9277],{"class":3418},[2978,12576,5903],{"class":3049},[2978,12578,5271],{"class":3418},[2978,12580,3119],{"class":3049},[2978,12582,3605],{"class":3418},[2978,12584,3175],{"class":3049},[2978,12586,12587],{"class":2980,"line":4867},[2978,12588,5939],{"class":3049},[2978,12590,12591,12594,12596,12599,12601,12603,12605,12607],{"class":2980,"line":4880},[2978,12592,12593],{"class":3418},"                unhealthyChecks",[2978,12595,3119],{"class":3049},[2978,12597,12598],{"class":2991},"Add",[2978,12600,3443],{"class":3049},[2978,12602,12532],{"class":3418},[2978,12604,3119],{"class":3049},[2978,12606,9360],{"class":3418},[2978,12608,3477],{"class":3049},[2978,12610,12611],{"class":2980,"line":4885},[2978,12612,5974],{"class":3049},[2978,12614,12615,12618,12621,12623,12625,12627,12629,12631,12633,12635,12637,12639,12641],{"class":2980,"line":4890},[2978,12616,12617],{"class":3567},"            else",[2978,12619,12620],{"class":3567}," if",[2978,12622,5924],{"class":3049},[2978,12624,12532],{"class":3418},[2978,12626,3119],{"class":3049},[2978,12628,9371],{"class":3418},[2978,12630,3119],{"class":3049},[2978,12632,9277],{"class":3418},[2978,12634,5903],{"class":3049},[2978,12636,5271],{"class":3418},[2978,12638,3119],{"class":3049},[2978,12640,4050],{"class":3418},[2978,12642,3175],{"class":3049},[2978,12644,12645],{"class":2980,"line":4909},[2978,12646,5939],{"class":3049},[2978,12648,12649,12652,12654,12656,12658,12660,12662,12664],{"class":2980,"line":4914},[2978,12650,12651],{"class":3418},"                degradedChecks",[2978,12653,3119],{"class":3049},[2978,12655,12598],{"class":2991},[2978,12657,3443],{"class":3049},[2978,12659,12532],{"class":3418},[2978,12661,3119],{"class":3049},[2978,12663,9360],{"class":3418},[2978,12665,3477],{"class":3049},[2978,12667,12668],{"class":2980,"line":4941},[2978,12669,5974],{"class":3049},[2978,12671,12672],{"class":2980,"line":4954},[2978,12673,6442],{"class":3049},[2978,12675,12676],{"class":2980,"line":4959},[2978,12677,3022],{"emptyLinePlaceholder":3021},[2978,12679,12680,12682,12684,12687,12689,12692],{"class":2980,"line":4964},[2978,12681,6920],{"class":3567},[2978,12683,5924],{"class":3049},[2978,12685,12686],{"class":3418},"unhealthyChecks",[2978,12688,3119],{"class":3049},[2978,12690,12691],{"class":2991},"Any",[2978,12693,9639],{"class":3049},[2978,12695,12696],{"class":2980,"line":6186},[2978,12697,5848],{"class":3049},[2978,12699,12700,12702,12704,12706,12708],{"class":2980,"line":6192},[2978,12701,6384],{"class":3567},[2978,12703,4019],{"class":3418},[2978,12705,3119],{"class":3049},[2978,12707,3605],{"class":2991},[2978,12709,5238],{"class":3049},[2978,12711,12712,12715,12717,12719,12721,12724,12726,12729,12731,12733,12736,12738],{"class":2980,"line":6197},[2978,12713,12714],{"class":2995},"                $\"Unhealthy checks: ",[2978,12716,6250],{"class":6249},[2978,12718,6039],{"class":3192},[2978,12720,3119],{"class":6249},[2978,12722,12723],{"class":2991},"Join",[2978,12725,3443],{"class":6249},[2978,12727,12728],{"class":2995},"\", \"",[2978,12730,4122],{"class":6249},[2978,12732,12686],{"class":3418},[2978,12734,12735],{"class":6249},")}",[2978,12737,7483],{"class":2995},[2978,12739,5062],{"class":3049},[2978,12741,12742,12744,12746,12748],{"class":2980,"line":6214},[2978,12743,7042],{"class":3418},[2978,12745,3669],{"class":3049},[2978,12747,6276],{"class":3418},[2978,12749,3477],{"class":3049},[2978,12751,12752],{"class":2980,"line":6219},[2978,12753,6442],{"class":3049},[2978,12755,12756],{"class":2980,"line":6232},[2978,12757,3022],{"emptyLinePlaceholder":3021},[2978,12759,12760,12762,12764,12767,12769,12771],{"class":2980,"line":6243},[2978,12761,6920],{"class":3567},[2978,12763,5924],{"class":3049},[2978,12765,12766],{"class":3418},"degradedChecks",[2978,12768,3119],{"class":3049},[2978,12770,12691],{"class":2991},[2978,12772,9639],{"class":3049},[2978,12774,12775],{"class":2980,"line":6268},[2978,12776,5848],{"class":3049},[2978,12778,12779,12781,12783,12785,12787],{"class":2980,"line":6281},[2978,12780,6384],{"class":3567},[2978,12782,4019],{"class":3418},[2978,12784,3119],{"class":3049},[2978,12786,4050],{"class":2991},[2978,12788,5238],{"class":3049},[2978,12790,12791,12794,12796,12798,12800,12802,12804,12806,12808,12810,12812,12814],{"class":2980,"line":6286},[2978,12792,12793],{"class":2995},"                $\"Degraded checks: ",[2978,12795,6250],{"class":6249},[2978,12797,6039],{"class":3192},[2978,12799,3119],{"class":6249},[2978,12801,12723],{"class":2991},[2978,12803,3443],{"class":6249},[2978,12805,12728],{"class":2995},[2978,12807,4122],{"class":6249},[2978,12809,12766],{"class":3418},[2978,12811,12735],{"class":6249},[2978,12813,7483],{"class":2995},[2978,12815,5062],{"class":3049},[2978,12817,12818,12820,12822,12824],{"class":2980,"line":6291},[2978,12819,7042],{"class":3418},[2978,12821,3669],{"class":3049},[2978,12823,6276],{"class":3418},[2978,12825,3477],{"class":3049},[2978,12827,12828],{"class":2980,"line":6311},[2978,12829,6442],{"class":3049},[2978,12831,12832],{"class":2980,"line":6316},[2978,12833,3022],{"emptyLinePlaceholder":3021},[2978,12835,12836,12838,12840,12842,12844],{"class":2980,"line":6329},[2978,12837,3568],{"class":3567},[2978,12839,4019],{"class":3418},[2978,12841,3119],{"class":3049},[2978,12843,3591],{"class":2991},[2978,12845,5238],{"class":3049},[2978,12847,12848,12851],{"class":2980,"line":6340},[2978,12849,12850],{"class":2995},"            \"All checks passed\"",[2978,12852,5062],{"class":3049},[2978,12854,12855,12857,12859,12861],{"class":2980,"line":6360},[2978,12856,12526],{"class":3418},[2978,12858,3669],{"class":3049},[2978,12860,6276],{"class":3418},[2978,12862,3477],{"class":3049},[2978,12864,12865],{"class":2980,"line":6371},[2978,12866,3617],{"class":3049},[2978,12868,12869],{"class":2980,"line":6376},[2978,12870,3622],{"class":3049},[3735,12872],{},[3351,12874,12876],{"id":12875},"рівень-3-архітектура-та-створення","Рівень 3: Архітектура та створення",[4363,12878,12879,12883,12886,13602,13606,13609,14393,14397,14400],{},[3351,12880,12882],{"id":12881},"завдання-31-health-check-middleware-з-caching","Завдання 3.1: Health Check Middleware з Caching",[2964,12884,12885],{},"Створіть middleware для кешування результатів health checks:",[11082,12887,12888,13565,13569],{"title":11201},[2968,12889,12891],{"className":3409,"code":12890,"language":3411,"meta":2973,"style":2973},"public class CachedHealthCheckMiddleware\n{\n    private readonly RequestDelegate _next;\n    private readonly IHealthCheckService _healthCheckService;\n    private readonly IMemoryCache _cache;\n    private readonly TimeSpan _cacheDuration;\n\n    public CachedHealthCheckMiddleware(\n        RequestDelegate next,\n        IHealthCheckService healthCheckService,\n        IMemoryCache cache,\n        TimeSpan cacheDuration)\n    {\n        _next = next;\n        _healthCheckService = healthCheckService;\n        _cache = cache;\n        _cacheDuration = cacheDuration;\n    }\n\n    public async Task InvokeAsync(HttpContext context)\n    {\n        if (!context.Request.Path.StartsWithSegments(\"/health\"))\n        {\n            await _next(context);\n            return;\n        }\n\n        var cacheKey = $\"health-check:{context.Request.Path}\";\n\n        if (_cache.TryGetValue\u003CHealthReport>(cacheKey, out var cachedReport))\n        {\n            await WriteResponse(context, cachedReport!);\n            return;\n        }\n\n        var report = await _healthCheckService.CheckHealthAsync();\n\n        _cache.Set(cacheKey, report, _cacheDuration);\n\n        await WriteResponse(context, report);\n    }\n\n    private static async Task WriteResponse(HttpContext context, HealthReport report)\n    {\n        context.Response.ContentType = \"application/json\";\n        context.Response.StatusCode = report.Status == HealthStatus.Healthy ? 200 : 503;\n\n        await context.Response.WriteAsJsonAsync(new\n        {\n            status = report.Status.ToString(),\n            duration = report.TotalDuration.TotalMilliseconds,\n            checks = report.Entries.Select(e => new\n            {\n                name = e.Key,\n                status = e.Value.Status.ToString()\n            })\n        });\n    }\n}\n",[2975,12892,12893,12902,12906,12920,12932,12946,12960,12964,12973,12983,12992,13002,13012,13016,13028,13038,13050,13062,13066,13070,13090,13094,13123,13127,13139,13145,13149,13153,13183,13187,13222,13226,13245,13251,13255,13259,13277,13281,13305,13309,13325,13329,13333,13360,13364,13382,13422,13426,13444,13448,13466,13484,13508,13512,13526,13548,13552,13557,13561],{"__ignoreMap":2973},[2978,12894,12895,12897,12899],{"class":2980,"line":2981},[2978,12896,3492],{"class":3192},[2978,12898,3495],{"class":3192},[2978,12900,12901],{"class":3498}," CachedHealthCheckMiddleware\n",[2978,12903,12904],{"class":2980,"line":2988},[2978,12905,3510],{"class":3049},[2978,12907,12908,12910,12912,12915,12918],{"class":2980,"line":2999},[2978,12909,5731],{"class":3192},[2978,12911,5734],{"class":3192},[2978,12913,12914],{"class":3498}," RequestDelegate",[2978,12916,12917],{"class":3418}," _next",[2978,12919,4539],{"class":3049},[2978,12921,12922,12924,12926,12928,12930],{"class":2980,"line":3018},[2978,12923,5731],{"class":3192},[2978,12925,5734],{"class":3192},[2978,12927,12284],{"class":3498},[2978,12929,12287],{"class":3418},[2978,12931,4539],{"class":3049},[2978,12933,12934,12936,12938,12941,12944],{"class":2980,"line":3025},[2978,12935,5731],{"class":3192},[2978,12937,5734],{"class":3192},[2978,12939,12940],{"class":3498}," IMemoryCache",[2978,12942,12943],{"class":3418}," _cache",[2978,12945,4539],{"class":3049},[2978,12947,12948,12950,12952,12955,12958],{"class":2980,"line":3031},[2978,12949,5731],{"class":3192},[2978,12951,5734],{"class":3192},[2978,12953,12954],{"class":3498}," TimeSpan",[2978,12956,12957],{"class":3418}," _cacheDuration",[2978,12959,4539],{"class":3049},[2978,12961,12962],{"class":2980,"line":3040},[2978,12963,3022],{"emptyLinePlaceholder":3021},[2978,12965,12966,12968,12971],{"class":2980,"line":3059},[2978,12967,3515],{"class":3192},[2978,12969,12970],{"class":2991}," CachedHealthCheckMiddleware",[2978,12972,5238],{"class":3049},[2978,12974,12975,12978,12981],{"class":2980,"line":3076},[2978,12976,12977],{"class":3498},"        RequestDelegate",[2978,12979,12980],{"class":3418}," next",[2978,12982,5062],{"class":3049},[2978,12984,12985,12988,12990],{"class":2980,"line":3081},[2978,12986,12987],{"class":3498},"        IHealthCheckService",[2978,12989,12307],{"class":3418},[2978,12991,5062],{"class":3049},[2978,12993,12994,12997,13000],{"class":2980,"line":3246},[2978,12995,12996],{"class":3498},"        IMemoryCache",[2978,12998,12999],{"class":3418}," cache",[2978,13001,5062],{"class":3049},[2978,13003,13004,13007,13010],{"class":2980,"line":3256},[2978,13005,13006],{"class":3498},"        TimeSpan",[2978,13008,13009],{"class":3418}," cacheDuration",[2978,13011,3175],{"class":3049},[2978,13013,13014],{"class":2980,"line":3261},[2978,13015,3545],{"class":3049},[2978,13017,13018,13021,13023,13026],{"class":2980,"line":3267},[2978,13019,13020],{"class":3418},"        _next",[2978,13022,3556],{"class":3049},[2978,13024,13025],{"class":3418},"next",[2978,13027,4539],{"class":3049},[2978,13029,13030,13032,13034,13036],{"class":2980,"line":3276},[2978,13031,12318],{"class":3418},[2978,13033,3556],{"class":3049},[2978,13035,12323],{"class":3418},[2978,13037,4539],{"class":3049},[2978,13039,13040,13043,13045,13048],{"class":2980,"line":3836},[2978,13041,13042],{"class":3418},"        _cache",[2978,13044,3556],{"class":3049},[2978,13046,13047],{"class":3418},"cache",[2978,13049,4539],{"class":3049},[2978,13051,13052,13055,13057,13060],{"class":2980,"line":4741},[2978,13053,13054],{"class":3418},"        _cacheDuration",[2978,13056,3556],{"class":3049},[2978,13058,13059],{"class":3418},"cacheDuration",[2978,13061,4539],{"class":3049},[2978,13063,13064],{"class":2980,"line":4753},[2978,13065,3617],{"class":3049},[2978,13067,13068],{"class":2980,"line":4758},[2978,13069,3022],{"emptyLinePlaceholder":3021},[2978,13071,13072,13074,13076,13078,13081,13083,13086,13088],{"class":2980,"line":4764},[2978,13073,3515],{"class":3192},[2978,13075,7225],{"class":3192},[2978,13077,3518],{"class":3498},[2978,13079,13080],{"class":2991}," InvokeAsync",[2978,13082,3443],{"class":3049},[2978,13084,13085],{"class":3498},"HttpContext",[2978,13087,3538],{"class":3418},[2978,13089,3175],{"class":3049},[2978,13091,13092],{"class":2980,"line":4784},[2978,13093,3545],{"class":3049},[2978,13095,13096,13098,13100,13102,13104,13107,13109,13112,13114,13117,13119,13121],{"class":2980,"line":4789},[2978,13097,6920],{"class":3567},[2978,13099,7440],{"class":3049},[2978,13101,10740],{"class":3418},[2978,13103,3119],{"class":3049},[2978,13105,13106],{"class":3418},"Request",[2978,13108,3119],{"class":3049},[2978,13110,13111],{"class":3418},"Path",[2978,13113,3119],{"class":3049},[2978,13115,13116],{"class":2991},"StartsWithSegments",[2978,13118,3443],{"class":3049},[2978,13120,4775],{"class":2995},[2978,13122,10679],{"class":3049},[2978,13124,13125],{"class":2980,"line":4805},[2978,13126,5848],{"class":3049},[2978,13128,13129,13131,13133,13135,13137],{"class":2980,"line":4810},[2978,13130,11357],{"class":3192},[2978,13132,12917],{"class":2991},[2978,13134,3443],{"class":3049},[2978,13136,10740],{"class":3418},[2978,13138,3477],{"class":3049},[2978,13140,13141,13143],{"class":2980,"line":4815},[2978,13142,6384],{"class":3567},[2978,13144,4539],{"class":3049},[2978,13146,13147],{"class":2980,"line":4834},[2978,13148,6442],{"class":3049},[2978,13150,13151],{"class":2980,"line":4839},[2978,13152,3022],{"emptyLinePlaceholder":3021},[2978,13154,13155,13157,13160,13162,13165,13167,13169,13171,13173,13175,13177,13179,13181],{"class":2980,"line":4867},[2978,13156,3550],{"class":3192},[2978,13158,13159],{"class":3418}," cacheKey",[2978,13161,3556],{"class":3049},[2978,13163,13164],{"class":2995},"$\"health-check:",[2978,13166,6250],{"class":6249},[2978,13168,10740],{"class":3418},[2978,13170,3119],{"class":6249},[2978,13172,13106],{"class":3418},[2978,13174,3119],{"class":6249},[2978,13176,13111],{"class":3418},[2978,13178,6260],{"class":6249},[2978,13180,7483],{"class":2995},[2978,13182,4539],{"class":3049},[2978,13184,13185],{"class":2980,"line":4880},[2978,13186,3022],{"emptyLinePlaceholder":3021},[2978,13188,13189,13191,13193,13196,13198,13201,13203,13205,13207,13210,13212,13215,13217,13220],{"class":2980,"line":4885},[2978,13190,6920],{"class":3567},[2978,13192,5924],{"class":3049},[2978,13194,13195],{"class":3418},"_cache",[2978,13197,3119],{"class":3049},[2978,13199,13200],{"class":2991},"TryGetValue",[2978,13202,3521],{"class":3049},[2978,13204,9233],{"class":3498},[2978,13206,4188],{"class":3049},[2978,13208,13209],{"class":3418},"cacheKey",[2978,13211,4122],{"class":3049},[2978,13213,13214],{"class":3192},"out",[2978,13216,11335],{"class":3192},[2978,13218,13219],{"class":3418}," cachedReport",[2978,13221,10679],{"class":3049},[2978,13223,13224],{"class":2980,"line":4890},[2978,13225,5848],{"class":3049},[2978,13227,13228,13230,13233,13235,13237,13239,13242],{"class":2980,"line":4909},[2978,13229,11357],{"class":3192},[2978,13231,13232],{"class":2991}," WriteResponse",[2978,13234,3443],{"class":3049},[2978,13236,10740],{"class":3418},[2978,13238,4122],{"class":3049},[2978,13240,13241],{"class":3418},"cachedReport",[2978,13243,13244],{"class":3049},"!);\n",[2978,13246,13247,13249],{"class":2980,"line":4914},[2978,13248,6384],{"class":3567},[2978,13250,4539],{"class":3049},[2978,13252,13253],{"class":2980,"line":4941},[2978,13254,6442],{"class":3049},[2978,13256,13257],{"class":2980,"line":4954},[2978,13258,3022],{"emptyLinePlaceholder":3021},[2978,13260,13261,13263,13265,13267,13269,13271,13273,13275],{"class":2980,"line":4959},[2978,13262,3550],{"class":3192},[2978,13264,9236],{"class":3418},[2978,13266,3556],{"class":3049},[2978,13268,7309],{"class":3192},[2978,13270,12287],{"class":3418},[2978,13272,3119],{"class":3049},[2978,13274,3530],{"class":2991},[2978,13276,3562],{"class":3049},[2978,13278,13279],{"class":2980,"line":4964},[2978,13280,3022],{"emptyLinePlaceholder":3021},[2978,13282,13283,13285,13287,13290,13292,13294,13296,13298,13300,13303],{"class":2980,"line":6186},[2978,13284,13042],{"class":3418},[2978,13286,3119],{"class":3049},[2978,13288,13289],{"class":2991},"Set",[2978,13291,3443],{"class":3049},[2978,13293,13209],{"class":3418},[2978,13295,4122],{"class":3049},[2978,13297,10745],{"class":3418},[2978,13299,4122],{"class":3049},[2978,13301,13302],{"class":3418},"_cacheDuration",[2978,13304,3477],{"class":3049},[2978,13306,13307],{"class":2980,"line":6192},[2978,13308,3022],{"emptyLinePlaceholder":3021},[2978,13310,13311,13313,13315,13317,13319,13321,13323],{"class":2980,"line":6197},[2978,13312,11019],{"class":3192},[2978,13314,13232],{"class":2991},[2978,13316,3443],{"class":3049},[2978,13318,10740],{"class":3418},[2978,13320,4122],{"class":3049},[2978,13322,10745],{"class":3418},[2978,13324,3477],{"class":3049},[2978,13326,13327],{"class":2980,"line":6214},[2978,13328,3617],{"class":3049},[2978,13330,13331],{"class":2980,"line":6219},[2978,13332,3022],{"emptyLinePlaceholder":3021},[2978,13334,13335,13337,13340,13342,13344,13346,13348,13350,13352,13354,13356,13358],{"class":2980,"line":6232},[2978,13336,5731],{"class":3192},[2978,13338,13339],{"class":3192}," static",[2978,13341,7225],{"class":3192},[2978,13343,3518],{"class":3498},[2978,13345,13232],{"class":2991},[2978,13347,3443],{"class":3049},[2978,13349,13085],{"class":3498},[2978,13351,3538],{"class":3418},[2978,13353,4122],{"class":3049},[2978,13355,9233],{"class":3498},[2978,13357,9236],{"class":3418},[2978,13359,3175],{"class":3049},[2978,13361,13362],{"class":2980,"line":6243},[2978,13363,3545],{"class":3049},[2978,13365,13366,13368,13370,13372,13374,13376,13378,13380],{"class":2980,"line":6268},[2978,13367,10757],{"class":3418},[2978,13369,3119],{"class":3049},[2978,13371,10762],{"class":3418},[2978,13373,3119],{"class":3049},[2978,13375,10767],{"class":3418},[2978,13377,3556],{"class":3049},[2978,13379,10772],{"class":2995},[2978,13381,4539],{"class":3049},[2978,13383,13384,13386,13388,13390,13392,13394,13396,13398,13400,13402,13404,13406,13408,13410,13412,13415,13417,13420],{"class":2980,"line":6281},[2978,13385,10757],{"class":3418},[2978,13387,3119],{"class":3049},[2978,13389,10762],{"class":3418},[2978,13391,3119],{"class":3049},[2978,13393,7406],{"class":3418},[2978,13395,3556],{"class":3049},[2978,13397,10745],{"class":3418},[2978,13399,3119],{"class":3049},[2978,13401,9277],{"class":3418},[2978,13403,5903],{"class":3049},[2978,13405,5271],{"class":3418},[2978,13407,3119],{"class":3049},[2978,13409,3591],{"class":3418},[2978,13411,10230],{"class":3049},[2978,13413,13414],{"class":3005},"200",[2978,13416,3502],{"class":3049},[2978,13418,13419],{"class":3005},"503",[2978,13421,4539],{"class":3049},[2978,13423,13424],{"class":2980,"line":6286},[2978,13425,3022],{"emptyLinePlaceholder":3021},[2978,13427,13428,13430,13432,13434,13436,13438,13440,13442],{"class":2980,"line":6291},[2978,13429,11019],{"class":3192},[2978,13431,3538],{"class":3418},[2978,13433,3119],{"class":3049},[2978,13435,10762],{"class":3418},[2978,13437,3119],{"class":3049},[2978,13439,11030],{"class":2991},[2978,13441,3443],{"class":3049},[2978,13443,10789],{"class":3192},[2978,13445,13446],{"class":2980,"line":6311},[2978,13447,5848],{"class":3049},[2978,13449,13450,13452,13454,13456,13458,13460,13462,13464],{"class":2980,"line":6316},[2978,13451,10798],{"class":3418},[2978,13453,3556],{"class":3049},[2978,13455,10745],{"class":3418},[2978,13457,3119],{"class":3049},[2978,13459,9277],{"class":3418},[2978,13461,3119],{"class":3049},[2978,13463,10474],{"class":2991},[2978,13465,10477],{"class":3049},[2978,13467,13468,13470,13472,13474,13476,13478,13480,13482],{"class":2980,"line":6329},[2978,13469,10834],{"class":3418},[2978,13471,3556],{"class":3049},[2978,13473,10745],{"class":3418},[2978,13475,3119],{"class":3049},[2978,13477,9288],{"class":3418},[2978,13479,3119],{"class":3049},[2978,13481,9293],{"class":3418},[2978,13483,5062],{"class":3049},[2978,13485,13486,13488,13490,13492,13494,13496,13498,13500,13502,13504,13506],{"class":2980,"line":6340},[2978,13487,10853],{"class":3418},[2978,13489,3556],{"class":3049},[2978,13491,10745],{"class":3418},[2978,13493,3119],{"class":3049},[2978,13495,9326],{"class":3418},[2978,13497,3119],{"class":3049},[2978,13499,10866],{"class":2991},[2978,13501,3443],{"class":3049},[2978,13503,10871],{"class":3418},[2978,13505,4266],{"class":3049},[2978,13507,10789],{"class":3192},[2978,13509,13510],{"class":2980,"line":6360},[2978,13511,5939],{"class":3049},[2978,13513,13514,13516,13518,13520,13522,13524],{"class":2980,"line":6371},[2978,13515,10884],{"class":3418},[2978,13517,3556],{"class":3049},[2978,13519,10871],{"class":3418},[2978,13521,3119],{"class":3049},[2978,13523,9360],{"class":3418},[2978,13525,5062],{"class":3049},[2978,13527,13528,13530,13532,13534,13536,13538,13540,13542,13544,13546],{"class":2980,"line":6376},[2978,13529,10899],{"class":3418},[2978,13531,3556],{"class":3049},[2978,13533,10871],{"class":3418},[2978,13535,3119],{"class":3049},[2978,13537,9371],{"class":3418},[2978,13539,3119],{"class":3049},[2978,13541,9277],{"class":3418},[2978,13543,3119],{"class":3049},[2978,13545,10474],{"class":2991},[2978,13547,3432],{"class":3049},[2978,13549,13550],{"class":2980,"line":6381},[2978,13551,11006],{"class":3049},[2978,13553,13554],{"class":2980,"line":6395},[2978,13555,13556],{"class":3049},"        });\n",[2978,13558,13559],{"class":2980,"line":6407},[2978,13560,3617],{"class":3049},[2978,13562,13563],{"class":2980,"line":6427},[2978,13564,3622],{"class":3049},[2964,13566,13567],{},[3088,13568,9430],{},[2968,13570,13572],{"className":3409,"code":13571,"language":3411,"meta":2973,"style":2973},"app.UseMiddleware\u003CCachedHealthCheckMiddleware>(TimeSpan.FromSeconds(10));\n",[2975,13573,13574],{"__ignoreMap":2973},[2978,13575,13576,13578,13580,13583,13585,13588,13590,13592,13594,13596,13598,13600],{"class":2980,"line":2981},[2978,13577,4232],{"class":3418},[2978,13579,3119],{"class":3049},[2978,13581,13582],{"class":2991},"UseMiddleware",[2978,13584,3521],{"class":3049},[2978,13586,13587],{"class":3498},"CachedHealthCheckMiddleware",[2978,13589,4188],{"class":3049},[2978,13591,5307],{"class":3418},[2978,13593,3119],{"class":3049},[2978,13595,5312],{"class":2991},[2978,13597,3443],{"class":3049},[2978,13599,5631],{"class":3005},[2978,13601,5320],{"class":3049},[3351,13603,13605],{"id":13604},"завдання-32-alerting-system","Завдання 3.2: Alerting System",[2964,13607,13608],{},"Створіть систему алертів на основі health checks:",[11082,13610,13611],{"title":11201},[2968,13612,13614],{"className":3409,"code":13613,"language":3411,"meta":2973,"style":2973},"public class HealthCheckAlertingPublisher : IHealthCheckPublisher\n{\n    private readonly ILogger\u003CHealthCheckAlertingPublisher> _logger;\n    private readonly IEmailService _emailService;\n    private readonly Dictionary\u003Cstring, HealthStatus> _previousStatuses = new();\n\n    public HealthCheckAlertingPublisher(\n        ILogger\u003CHealthCheckAlertingPublisher> logger,\n        IEmailService emailService)\n    {\n        _logger = logger;\n        _emailService = emailService;\n    }\n\n    public async Task PublishAsync(HealthReport report, CancellationToken cancellationToken)\n    {\n        foreach (var entry in report.Entries)\n        {\n            var currentStatus = entry.Value.Status;\n            var checkName = entry.Key;\n\n            // Перевіряємо, чи змінився статус\n            if (_previousStatuses.TryGetValue(checkName, out var previousStatus))\n            {\n                if (previousStatus != currentStatus)\n                {\n                    await SendAlert(checkName, previousStatus, currentStatus, entry.Value);\n                }\n            }\n\n            _previousStatuses[checkName] = currentStatus;\n        }\n    }\n\n    private async Task SendAlert(\n        string checkName,\n        HealthStatus previousStatus,\n        HealthStatus currentStatus,\n        HealthReportEntry entry)\n    {\n        var severity = currentStatus switch\n        {\n            HealthStatus.Unhealthy => \"CRITICAL\",\n            HealthStatus.Degraded => \"WARNING\",\n            HealthStatus.Healthy => \"INFO\",\n            _ => \"UNKNOWN\"\n        };\n\n        var message = $@\"\nHealth Check Alert\n\nCheck: {checkName}\nPrevious Status: {previousStatus}\nCurrent Status: {currentStatus}\nSeverity: {severity}\nDescription: {entry.Description}\nDuration: {entry.Duration.TotalMilliseconds}ms\nException: {entry.Exception?.Message ?? \"None\"}\n\";\n\n        _logger.LogWarning(\n            \"Health check status changed: {CheckName} {PreviousStatus} → {CurrentStatus}\",\n            checkName,\n            previousStatus,\n            currentStatus);\n\n        if (currentStatus == HealthStatus.Unhealthy)\n        {\n            await _emailService.SendAlertAsync(\n                \"ops-team@example.com\",\n                $\"[{severity}] Health Check Alert: {checkName}\",\n                message);\n        }\n    }\n}\n",[2975,13615,13616,13629,13633,13652,13666,13693,13697,13705,13720,13730,13734,13744,13756,13760,13764,13788,13792,13812,13816,13837,13854,13858,13863,13891,13895,13913,13917,13947,13952,13956,13960,13975,13979,13983,13987,13999,14008,14017,14025,14034,14038,14051,14055,14071,14086,14101,14110,14114,14118,14130,14135,14139,14150,14161,14172,14184,14199,14221,14249,14255,14259,14270,14277,14284,14291,14298,14302,14320,14324,14337,14345,14370,14378,14383,14388],{"__ignoreMap":2973},[2978,13617,13618,13620,13622,13625,13627],{"class":2980,"line":2981},[2978,13619,3492],{"class":3192},[2978,13621,3495],{"class":3192},[2978,13623,13624],{"class":3498}," HealthCheckAlertingPublisher",[2978,13626,3502],{"class":3049},[2978,13628,9145],{"class":3498},[2978,13630,13631],{"class":2980,"line":2988},[2978,13632,3510],{"class":3049},[2978,13634,13635,13637,13639,13641,13643,13646,13648,13650],{"class":2980,"line":2999},[2978,13636,5731],{"class":3192},[2978,13638,5734],{"class":3192},[2978,13640,9158],{"class":3498},[2978,13642,3521],{"class":3049},[2978,13644,13645],{"class":3498},"HealthCheckAlertingPublisher",[2978,13647,3527],{"class":3049},[2978,13649,9168],{"class":3418},[2978,13651,4539],{"class":3049},[2978,13653,13654,13656,13658,13661,13664],{"class":2980,"line":3018},[2978,13655,5731],{"class":3192},[2978,13657,5734],{"class":3192},[2978,13659,13660],{"class":3498}," IEmailService",[2978,13662,13663],{"class":3418}," _emailService",[2978,13665,4539],{"class":3049},[2978,13667,13668,13670,13672,13674,13676,13678,13680,13682,13684,13687,13689,13691],{"class":2980,"line":3025},[2978,13669,5731],{"class":3192},[2978,13671,5734],{"class":3192},[2978,13673,6034],{"class":3498},[2978,13675,3521],{"class":3049},[2978,13677,6039],{"class":3192},[2978,13679,4122],{"class":3049},[2978,13681,5271],{"class":3498},[2978,13683,3527],{"class":3049},[2978,13685,13686],{"class":3418},"_previousStatuses",[2978,13688,3556],{"class":3049},[2978,13690,4130],{"class":3192},[2978,13692,3562],{"class":3049},[2978,13694,13695],{"class":2980,"line":3031},[2978,13696,3022],{"emptyLinePlaceholder":3021},[2978,13698,13699,13701,13703],{"class":2980,"line":3040},[2978,13700,3515],{"class":3192},[2978,13702,13624],{"class":2991},[2978,13704,5238],{"class":3049},[2978,13706,13707,13710,13712,13714,13716,13718],{"class":2980,"line":3059},[2978,13708,13709],{"class":3498},"        ILogger",[2978,13711,3521],{"class":3049},[2978,13713,13645],{"class":3498},[2978,13715,3527],{"class":3049},[2978,13717,9194],{"class":3418},[2978,13719,5062],{"class":3049},[2978,13721,13722,13725,13728],{"class":2980,"line":3076},[2978,13723,13724],{"class":3498},"        IEmailService",[2978,13726,13727],{"class":3418}," emailService",[2978,13729,3175],{"class":3049},[2978,13731,13732],{"class":2980,"line":3081},[2978,13733,3545],{"class":3049},[2978,13735,13736,13738,13740,13742],{"class":2980,"line":3246},[2978,13737,9205],{"class":3418},[2978,13739,3556],{"class":3049},[2978,13741,9194],{"class":3418},[2978,13743,4539],{"class":3049},[2978,13745,13746,13749,13751,13754],{"class":2980,"line":3256},[2978,13747,13748],{"class":3418},"        _emailService",[2978,13750,3556],{"class":3049},[2978,13752,13753],{"class":3418},"emailService",[2978,13755,4539],{"class":3049},[2978,13757,13758],{"class":2980,"line":3261},[2978,13759,3617],{"class":3049},[2978,13761,13762],{"class":2980,"line":3267},[2978,13763,3022],{"emptyLinePlaceholder":3021},[2978,13765,13766,13768,13770,13772,13774,13776,13778,13780,13782,13784,13786],{"class":2980,"line":3276},[2978,13767,3515],{"class":3192},[2978,13769,7225],{"class":3192},[2978,13771,3518],{"class":3498},[2978,13773,9228],{"class":2991},[2978,13775,3443],{"class":3049},[2978,13777,9233],{"class":3498},[2978,13779,9236],{"class":3418},[2978,13781,4122],{"class":3049},[2978,13783,9241],{"class":3498},[2978,13785,5827],{"class":3418},[2978,13787,3175],{"class":3049},[2978,13789,13790],{"class":2980,"line":3836},[2978,13791,3545],{"class":3049},[2978,13793,13794,13796,13798,13800,13802,13804,13806,13808,13810],{"class":2980,"line":4741},[2978,13795,9309],{"class":3567},[2978,13797,5924],{"class":3049},[2978,13799,4588],{"class":3192},[2978,13801,9316],{"class":3418},[2978,13803,9319],{"class":3567},[2978,13805,9236],{"class":3418},[2978,13807,3119],{"class":3049},[2978,13809,9326],{"class":3418},[2978,13811,3175],{"class":3049},[2978,13813,13814],{"class":2980,"line":4753},[2978,13815,5848],{"class":3049},[2978,13817,13818,13820,13823,13825,13827,13829,13831,13833,13835],{"class":2980,"line":4758},[2978,13819,5853],{"class":3192},[2978,13821,13822],{"class":3418}," currentStatus",[2978,13824,3556],{"class":3049},[2978,13826,12532],{"class":3418},[2978,13828,3119],{"class":3049},[2978,13830,9371],{"class":3418},[2978,13832,3119],{"class":3049},[2978,13834,9277],{"class":3418},[2978,13836,4539],{"class":3049},[2978,13838,13839,13841,13844,13846,13848,13850,13852],{"class":2980,"line":4764},[2978,13840,5853],{"class":3192},[2978,13842,13843],{"class":3418}," checkName",[2978,13845,3556],{"class":3049},[2978,13847,12532],{"class":3418},[2978,13849,3119],{"class":3049},[2978,13851,9360],{"class":3418},[2978,13853,4539],{"class":3049},[2978,13855,13856],{"class":2980,"line":4784},[2978,13857,3022],{"emptyLinePlaceholder":3021},[2978,13859,13860],{"class":2980,"line":4789},[2978,13861,13862],{"class":2984},"            // Перевіряємо, чи змінився статус\n",[2978,13864,13865,13867,13869,13871,13873,13875,13877,13880,13882,13884,13886,13889],{"class":2980,"line":4805},[2978,13866,5921],{"class":3567},[2978,13868,5924],{"class":3049},[2978,13870,13686],{"class":3418},[2978,13872,3119],{"class":3049},[2978,13874,13200],{"class":2991},[2978,13876,3443],{"class":3049},[2978,13878,13879],{"class":3418},"checkName",[2978,13881,4122],{"class":3049},[2978,13883,13214],{"class":3192},[2978,13885,11335],{"class":3192},[2978,13887,13888],{"class":3418}," previousStatus",[2978,13890,10679],{"class":3049},[2978,13892,13893],{"class":2980,"line":4810},[2978,13894,5939],{"class":3049},[2978,13896,13897,13900,13902,13905,13908,13911],{"class":2980,"line":4815},[2978,13898,13899],{"class":3567},"                if",[2978,13901,5924],{"class":3049},[2978,13903,13904],{"class":3418},"previousStatus",[2978,13906,13907],{"class":3049}," != ",[2978,13909,13910],{"class":3418},"currentStatus",[2978,13912,3175],{"class":3049},[2978,13914,13915],{"class":2980,"line":4834},[2978,13916,10106],{"class":3049},[2978,13918,13919,13922,13925,13927,13929,13931,13933,13935,13937,13939,13941,13943,13945],{"class":2980,"line":4839},[2978,13920,13921],{"class":3192},"                    await",[2978,13923,13924],{"class":2991}," SendAlert",[2978,13926,3443],{"class":3049},[2978,13928,13879],{"class":3418},[2978,13930,4122],{"class":3049},[2978,13932,13904],{"class":3418},[2978,13934,4122],{"class":3049},[2978,13936,13910],{"class":3418},[2978,13938,4122],{"class":3049},[2978,13940,12532],{"class":3418},[2978,13942,3119],{"class":3049},[2978,13944,9371],{"class":3418},[2978,13946,3477],{"class":3049},[2978,13948,13949],{"class":2980,"line":4867},[2978,13950,13951],{"class":3049},"                }\n",[2978,13953,13954],{"class":2980,"line":4880},[2978,13955,5974],{"class":3049},[2978,13957,13958],{"class":2980,"line":4885},[2978,13959,3022],{"emptyLinePlaceholder":3021},[2978,13961,13962,13965,13967,13969,13971,13973],{"class":2980,"line":4890},[2978,13963,13964],{"class":3418},"            _previousStatuses",[2978,13966,12529],{"class":3049},[2978,13968,13879],{"class":3418},[2978,13970,6062],{"class":3049},[2978,13972,13910],{"class":3418},[2978,13974,4539],{"class":3049},[2978,13976,13977],{"class":2980,"line":4909},[2978,13978,6442],{"class":3049},[2978,13980,13981],{"class":2980,"line":4914},[2978,13982,3617],{"class":3049},[2978,13984,13985],{"class":2980,"line":4941},[2978,13986,3022],{"emptyLinePlaceholder":3021},[2978,13988,13989,13991,13993,13995,13997],{"class":2980,"line":4954},[2978,13990,5731],{"class":3192},[2978,13992,7225],{"class":3192},[2978,13994,3518],{"class":3498},[2978,13996,13924],{"class":2991},[2978,13998,5238],{"class":3049},[2978,14000,14001,14004,14006],{"class":2980,"line":4959},[2978,14002,14003],{"class":3192},"        string",[2978,14005,13843],{"class":3418},[2978,14007,5062],{"class":3049},[2978,14009,14010,14013,14015],{"class":2980,"line":4964},[2978,14011,14012],{"class":3498},"        HealthStatus",[2978,14014,13888],{"class":3418},[2978,14016,5062],{"class":3049},[2978,14018,14019,14021,14023],{"class":2980,"line":6186},[2978,14020,14012],{"class":3498},[2978,14022,13822],{"class":3418},[2978,14024,5062],{"class":3049},[2978,14026,14027,14030,14032],{"class":2980,"line":6192},[2978,14028,14029],{"class":3498},"        HealthReportEntry",[2978,14031,9316],{"class":3418},[2978,14033,3175],{"class":3049},[2978,14035,14036],{"class":2980,"line":6197},[2978,14037,3545],{"class":3049},[2978,14039,14040,14042,14045,14047,14049],{"class":2980,"line":6214},[2978,14041,3550],{"class":3192},[2978,14043,14044],{"class":3418}," severity",[2978,14046,3556],{"class":3049},[2978,14048,13910],{"class":3418},[2978,14050,10510],{"class":3567},[2978,14052,14053],{"class":2980,"line":6219},[2978,14054,5848],{"class":3049},[2978,14056,14057,14060,14062,14064,14066,14069],{"class":2980,"line":6232},[2978,14058,14059],{"class":3498},"            HealthStatus",[2978,14061,3119],{"class":3049},[2978,14063,3605],{"class":3498},[2978,14065,4266],{"class":3049},[2978,14067,14068],{"class":2995},"\"CRITICAL\"",[2978,14070,5062],{"class":3049},[2978,14072,14073,14075,14077,14079,14081,14084],{"class":2980,"line":6243},[2978,14074,14059],{"class":3498},[2978,14076,3119],{"class":3049},[2978,14078,4050],{"class":3498},[2978,14080,4266],{"class":3049},[2978,14082,14083],{"class":2995},"\"WARNING\"",[2978,14085,5062],{"class":3049},[2978,14087,14088,14090,14092,14094,14096,14099],{"class":2980,"line":6268},[2978,14089,14059],{"class":3498},[2978,14091,3119],{"class":3049},[2978,14093,3591],{"class":3498},[2978,14095,4266],{"class":3049},[2978,14097,14098],{"class":2995},"\"INFO\"",[2978,14100,5062],{"class":3049},[2978,14102,14103,14105,14107],{"class":2980,"line":6281},[2978,14104,10649],{"class":3192},[2978,14106,4266],{"class":3049},[2978,14108,14109],{"class":2995},"\"UNKNOWN\"\n",[2978,14111,14112],{"class":2980,"line":6286},[2978,14113,6911],{"class":3049},[2978,14115,14116],{"class":2980,"line":6291},[2978,14117,3022],{"emptyLinePlaceholder":3021},[2978,14119,14120,14122,14125,14127],{"class":2980,"line":6311},[2978,14121,3550],{"class":3192},[2978,14123,14124],{"class":3418}," message",[2978,14126,3556],{"class":3049},[2978,14128,14129],{"class":2995},"$@\"\n",[2978,14131,14132],{"class":2980,"line":6316},[2978,14133,14134],{"class":2995},"Health Check Alert\n",[2978,14136,14137],{"class":2980,"line":6329},[2978,14138,3022],{"emptyLinePlaceholder":3021},[2978,14140,14141,14144,14146,14148],{"class":2980,"line":6340},[2978,14142,14143],{"class":2995},"Check: ",[2978,14145,6250],{"class":6249},[2978,14147,13879],{"class":3418},[2978,14149,3622],{"class":6249},[2978,14151,14152,14155,14157,14159],{"class":2980,"line":6360},[2978,14153,14154],{"class":2995},"Previous Status: ",[2978,14156,6250],{"class":6249},[2978,14158,13904],{"class":3418},[2978,14160,3622],{"class":6249},[2978,14162,14163,14166,14168,14170],{"class":2980,"line":6371},[2978,14164,14165],{"class":2995},"Current Status: ",[2978,14167,6250],{"class":6249},[2978,14169,13910],{"class":3418},[2978,14171,3622],{"class":6249},[2978,14173,14174,14177,14179,14182],{"class":2980,"line":6376},[2978,14175,14176],{"class":2995},"Severity: ",[2978,14178,6250],{"class":6249},[2978,14180,14181],{"class":3418},"severity",[2978,14183,3622],{"class":6249},[2978,14185,14186,14189,14191,14193,14195,14197],{"class":2980,"line":6381},[2978,14187,14188],{"class":2995},"Description: ",[2978,14190,6250],{"class":6249},[2978,14192,12532],{"class":3418},[2978,14194,3119],{"class":6249},[2978,14196,10958],{"class":3418},[2978,14198,3622],{"class":6249},[2978,14200,14201,14204,14206,14208,14210,14212,14214,14216,14218],{"class":2980,"line":6395},[2978,14202,14203],{"class":2995},"Duration: ",[2978,14205,6250],{"class":6249},[2978,14207,12532],{"class":3418},[2978,14209,3119],{"class":6249},[2978,14211,9390],{"class":3418},[2978,14213,3119],{"class":6249},[2978,14215,9293],{"class":3418},[2978,14217,6260],{"class":6249},[2978,14219,14220],{"class":2995},"ms\n",[2978,14222,14223,14226,14228,14230,14232,14234,14237,14239,14241,14244,14247],{"class":2980,"line":6407},[2978,14224,14225],{"class":2995},"Exception: ",[2978,14227,6250],{"class":6249},[2978,14229,12532],{"class":3418},[2978,14231,3119],{"class":6249},[2978,14233,6453],{"class":3418},[2978,14235,14236],{"class":3049},"?",[2978,14238,3119],{"class":6249},[2978,14240,7664],{"class":3418},[2978,14242,14243],{"class":3049}," ??",[2978,14245,14246],{"class":2995}," \"None\"",[2978,14248,3622],{"class":6249},[2978,14250,14251,14253],{"class":2980,"line":6427},[2978,14252,7483],{"class":2995},[2978,14254,4539],{"class":3049},[2978,14256,14257],{"class":2980,"line":6439},[2978,14258,3022],{"emptyLinePlaceholder":3021},[2978,14260,14261,14263,14265,14268],{"class":2980,"line":6445},[2978,14262,9205],{"class":3418},[2978,14264,3119],{"class":3049},[2978,14266,14267],{"class":2991},"LogWarning",[2978,14269,5238],{"class":3049},[2978,14271,14272,14275],{"class":2980,"line":6461},[2978,14273,14274],{"class":2995},"            \"Health check status changed: {CheckName} {PreviousStatus} → {CurrentStatus}\"",[2978,14276,5062],{"class":3049},[2978,14278,14279,14282],{"class":2980,"line":6466},[2978,14280,14281],{"class":3418},"            checkName",[2978,14283,5062],{"class":3049},[2978,14285,14286,14289],{"class":2980,"line":6479},[2978,14287,14288],{"class":3418},"            previousStatus",[2978,14290,5062],{"class":3049},[2978,14292,14293,14296],{"class":2980,"line":6490},[2978,14294,14295],{"class":3418},"            currentStatus",[2978,14297,3477],{"class":3049},[2978,14299,14300],{"class":2980,"line":6498},[2978,14301,3022],{"emptyLinePlaceholder":3021},[2978,14303,14304,14306,14308,14310,14312,14314,14316,14318],{"class":2980,"line":6511},[2978,14305,6920],{"class":3567},[2978,14307,5924],{"class":3049},[2978,14309,13910],{"class":3418},[2978,14311,5903],{"class":3049},[2978,14313,5271],{"class":3418},[2978,14315,3119],{"class":3049},[2978,14317,3605],{"class":3418},[2978,14319,3175],{"class":3049},[2978,14321,14322],{"class":2980,"line":6516},[2978,14323,5848],{"class":3049},[2978,14325,14326,14328,14330,14332,14335],{"class":2980,"line":6521},[2978,14327,11357],{"class":3192},[2978,14329,13663],{"class":3418},[2978,14331,3119],{"class":3049},[2978,14333,14334],{"class":2991},"SendAlertAsync",[2978,14336,5238],{"class":3049},[2978,14338,14340,14343],{"class":2980,"line":14339},70,[2978,14341,14342],{"class":2995},"                \"ops-team@example.com\"",[2978,14344,5062],{"class":3049},[2978,14346,14348,14351,14353,14355,14357,14360,14362,14364,14366,14368],{"class":2980,"line":14347},71,[2978,14349,14350],{"class":2995},"                $\"[",[2978,14352,6250],{"class":6249},[2978,14354,14181],{"class":3418},[2978,14356,6260],{"class":6249},[2978,14358,14359],{"class":2995},"] Health Check Alert: ",[2978,14361,6250],{"class":6249},[2978,14363,13879],{"class":3418},[2978,14365,6260],{"class":6249},[2978,14367,7483],{"class":2995},[2978,14369,5062],{"class":3049},[2978,14371,14373,14376],{"class":2980,"line":14372},72,[2978,14374,14375],{"class":3418},"                message",[2978,14377,3477],{"class":3049},[2978,14379,14381],{"class":2980,"line":14380},73,[2978,14382,6442],{"class":3049},[2978,14384,14386],{"class":2980,"line":14385},74,[2978,14387,3617],{"class":3049},[2978,14389,14391],{"class":2980,"line":14390},75,[2978,14392,3622],{"class":3049},[3351,14394,14396],{"id":14395},"завдання-33-prometheus-metrics-integration","Завдання 3.3: Prometheus Metrics Integration",[2964,14398,14399],{},"Експортуйте health check метрики у Prometheus:",[11082,14401,14402,14874,14879,14947,14952],{"title":11201},[2968,14403,14405],{"className":3409,"code":14404,"language":3411,"meta":2973,"style":2973},"public class PrometheusHealthCheckPublisher : IHealthCheckPublisher\n{\n    private readonly ILogger\u003CPrometheusHealthCheckPublisher> _logger;\n    \n    // Prometheus metrics (використовуйте prometheus-net бібліотеку)\n    private static readonly Gauge HealthCheckStatus = Metrics.CreateGauge(\n        \"health_check_status\",\n        \"Health check status (0=Unhealthy, 1=Degraded, 2=Healthy)\",\n        new GaugeConfiguration\n        {\n            LabelNames = new[] { \"check_name\" }\n        });\n\n    private static readonly Gauge HealthCheckDuration = Metrics.CreateGauge(\n        \"health_check_duration_milliseconds\",\n        \"Health check duration in milliseconds\",\n        new GaugeConfiguration\n        {\n            LabelNames = new[] { \"check_name\" }\n        });\n\n    public PrometheusHealthCheckPublisher(ILogger\u003CPrometheusHealthCheckPublisher> logger)\n    {\n        _logger = logger;\n    }\n\n    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)\n    {\n        foreach (var entry in report.Entries)\n        {\n            var statusValue = entry.Value.Status switch\n            {\n                HealthStatus.Healthy => 2,\n                HealthStatus.Degraded => 1,\n                HealthStatus.Unhealthy => 0,\n                _ => -1\n            };\n\n            HealthCheckStatus.WithLabels(entry.Key).Set(statusValue);\n            HealthCheckDuration.WithLabels(entry.Key).Set(entry.Value.Duration.TotalMilliseconds);\n        }\n\n        return Task.CompletedTask;\n    }\n}\n",[2975,14406,14407,14420,14424,14443,14447,14452,14478,14485,14492,14500,14504,14521,14525,14529,14552,14559,14566,14572,14576,14590,14594,14598,14618,14622,14632,14636,14640,14662,14666,14686,14690,14711,14715,14730,14744,14758,14769,14773,14777,14807,14846,14850,14854,14866,14870],{"__ignoreMap":2973},[2978,14408,14409,14411,14413,14416,14418],{"class":2980,"line":2981},[2978,14410,3492],{"class":3192},[2978,14412,3495],{"class":3192},[2978,14414,14415],{"class":3498}," PrometheusHealthCheckPublisher",[2978,14417,3502],{"class":3049},[2978,14419,9145],{"class":3498},[2978,14421,14422],{"class":2980,"line":2988},[2978,14423,3510],{"class":3049},[2978,14425,14426,14428,14430,14432,14434,14437,14439,14441],{"class":2980,"line":2999},[2978,14427,5731],{"class":3192},[2978,14429,5734],{"class":3192},[2978,14431,9158],{"class":3498},[2978,14433,3521],{"class":3049},[2978,14435,14436],{"class":3498},"PrometheusHealthCheckPublisher",[2978,14438,3527],{"class":3049},[2978,14440,9168],{"class":3418},[2978,14442,4539],{"class":3049},[2978,14444,14445],{"class":2980,"line":3018},[2978,14446,3803],{"class":3049},[2978,14448,14449],{"class":2980,"line":3025},[2978,14450,14451],{"class":2984},"    // Prometheus metrics (використовуйте prometheus-net бібліотеку)\n",[2978,14453,14454,14456,14458,14460,14463,14466,14468,14471,14473,14476],{"class":2980,"line":3031},[2978,14455,5731],{"class":3192},[2978,14457,13339],{"class":3192},[2978,14459,5734],{"class":3192},[2978,14461,14462],{"class":3498}," Gauge",[2978,14464,14465],{"class":3418}," HealthCheckStatus",[2978,14467,3556],{"class":3049},[2978,14469,14470],{"class":3418},"Metrics",[2978,14472,3119],{"class":3049},[2978,14474,14475],{"class":2991},"CreateGauge",[2978,14477,5238],{"class":3049},[2978,14479,14480,14483],{"class":2980,"line":3040},[2978,14481,14482],{"class":2995},"        \"health_check_status\"",[2978,14484,5062],{"class":3049},[2978,14486,14487,14490],{"class":2980,"line":3059},[2978,14488,14489],{"class":2995},"        \"Health check status (0=Unhealthy, 1=Degraded, 2=Healthy)\"",[2978,14491,5062],{"class":3049},[2978,14493,14494,14497],{"class":2980,"line":3076},[2978,14495,14496],{"class":3192},"        new",[2978,14498,14499],{"class":3498}," GaugeConfiguration\n",[2978,14501,14502],{"class":2980,"line":3081},[2978,14503,5848],{"class":3049},[2978,14505,14506,14509,14511,14513,14515,14518],{"class":2980,"line":3246},[2978,14507,14508],{"class":3418},"            LabelNames",[2978,14510,3556],{"class":3049},[2978,14512,4130],{"class":3192},[2978,14514,4133],{"class":3049},[2978,14516,14517],{"class":2995},"\"check_name\"",[2978,14519,14520],{"class":3049}," }\n",[2978,14522,14523],{"class":2980,"line":3256},[2978,14524,13556],{"class":3049},[2978,14526,14527],{"class":2980,"line":3261},[2978,14528,3022],{"emptyLinePlaceholder":3021},[2978,14530,14531,14533,14535,14537,14539,14542,14544,14546,14548,14550],{"class":2980,"line":3267},[2978,14532,5731],{"class":3192},[2978,14534,13339],{"class":3192},[2978,14536,5734],{"class":3192},[2978,14538,14462],{"class":3498},[2978,14540,14541],{"class":3418}," HealthCheckDuration",[2978,14543,3556],{"class":3049},[2978,14545,14470],{"class":3418},[2978,14547,3119],{"class":3049},[2978,14549,14475],{"class":2991},[2978,14551,5238],{"class":3049},[2978,14553,14554,14557],{"class":2980,"line":3276},[2978,14555,14556],{"class":2995},"        \"health_check_duration_milliseconds\"",[2978,14558,5062],{"class":3049},[2978,14560,14561,14564],{"class":2980,"line":3836},[2978,14562,14563],{"class":2995},"        \"Health check duration in milliseconds\"",[2978,14565,5062],{"class":3049},[2978,14567,14568,14570],{"class":2980,"line":4741},[2978,14569,14496],{"class":3192},[2978,14571,14499],{"class":3498},[2978,14573,14574],{"class":2980,"line":4753},[2978,14575,5848],{"class":3049},[2978,14577,14578,14580,14582,14584,14586,14588],{"class":2980,"line":4758},[2978,14579,14508],{"class":3418},[2978,14581,3556],{"class":3049},[2978,14583,4130],{"class":3192},[2978,14585,4133],{"class":3049},[2978,14587,14517],{"class":2995},[2978,14589,14520],{"class":3049},[2978,14591,14592],{"class":2980,"line":4764},[2978,14593,13556],{"class":3049},[2978,14595,14596],{"class":2980,"line":4784},[2978,14597,3022],{"emptyLinePlaceholder":3021},[2978,14599,14600,14602,14604,14606,14608,14610,14612,14614,14616],{"class":2980,"line":4789},[2978,14601,3515],{"class":3192},[2978,14603,14415],{"class":2991},[2978,14605,3443],{"class":3049},[2978,14607,9185],{"class":3498},[2978,14609,3521],{"class":3049},[2978,14611,14436],{"class":3498},[2978,14613,3527],{"class":3049},[2978,14615,9194],{"class":3418},[2978,14617,3175],{"class":3049},[2978,14619,14620],{"class":2980,"line":4805},[2978,14621,3545],{"class":3049},[2978,14623,14624,14626,14628,14630],{"class":2980,"line":4810},[2978,14625,9205],{"class":3418},[2978,14627,3556],{"class":3049},[2978,14629,9194],{"class":3418},[2978,14631,4539],{"class":3049},[2978,14633,14634],{"class":2980,"line":4815},[2978,14635,3617],{"class":3049},[2978,14637,14638],{"class":2980,"line":4834},[2978,14639,3022],{"emptyLinePlaceholder":3021},[2978,14641,14642,14644,14646,14648,14650,14652,14654,14656,14658,14660],{"class":2980,"line":4839},[2978,14643,3515],{"class":3192},[2978,14645,3518],{"class":3498},[2978,14647,9228],{"class":2991},[2978,14649,3443],{"class":3049},[2978,14651,9233],{"class":3498},[2978,14653,9236],{"class":3418},[2978,14655,4122],{"class":3049},[2978,14657,9241],{"class":3498},[2978,14659,5827],{"class":3418},[2978,14661,3175],{"class":3049},[2978,14663,14664],{"class":2980,"line":4867},[2978,14665,3545],{"class":3049},[2978,14667,14668,14670,14672,14674,14676,14678,14680,14682,14684],{"class":2980,"line":4880},[2978,14669,9309],{"class":3567},[2978,14671,5924],{"class":3049},[2978,14673,4588],{"class":3192},[2978,14675,9316],{"class":3418},[2978,14677,9319],{"class":3567},[2978,14679,9236],{"class":3418},[2978,14681,3119],{"class":3049},[2978,14683,9326],{"class":3418},[2978,14685,3175],{"class":3049},[2978,14687,14688],{"class":2980,"line":4885},[2978,14689,5848],{"class":3049},[2978,14691,14692,14694,14697,14699,14701,14703,14705,14707,14709],{"class":2980,"line":4890},[2978,14693,5853],{"class":3192},[2978,14695,14696],{"class":3418}," statusValue",[2978,14698,3556],{"class":3049},[2978,14700,12532],{"class":3418},[2978,14702,3119],{"class":3049},[2978,14704,9371],{"class":3418},[2978,14706,3119],{"class":3049},[2978,14708,9277],{"class":3418},[2978,14710,10510],{"class":3567},[2978,14712,14713],{"class":2980,"line":4909},[2978,14714,5939],{"class":3049},[2978,14716,14717,14720,14722,14724,14726,14728],{"class":2980,"line":4914},[2978,14718,14719],{"class":3498},"                HealthStatus",[2978,14721,3119],{"class":3049},[2978,14723,3591],{"class":3498},[2978,14725,4266],{"class":3049},[2978,14727,3989],{"class":3005},[2978,14729,5062],{"class":3049},[2978,14731,14732,14734,14736,14738,14740,14742],{"class":2980,"line":4941},[2978,14733,14719],{"class":3498},[2978,14735,3119],{"class":3049},[2978,14737,4050],{"class":3498},[2978,14739,4266],{"class":3049},[2978,14741,3973],{"class":3005},[2978,14743,5062],{"class":3049},[2978,14745,14746,14748,14750,14752,14754,14756],{"class":2980,"line":4954},[2978,14747,14719],{"class":3498},[2978,14749,3119],{"class":3049},[2978,14751,3605],{"class":3498},[2978,14753,4266],{"class":3049},[2978,14755,3957],{"class":3005},[2978,14757,5062],{"class":3049},[2978,14759,14760,14763,14766],{"class":2980,"line":4959},[2978,14761,14762],{"class":3192},"                _",[2978,14764,14765],{"class":3049}," => -",[2978,14767,14768],{"class":3005},"1\n",[2978,14770,14771],{"class":2980,"line":4964},[2978,14772,6189],{"class":3049},[2978,14774,14775],{"class":2980,"line":6186},[2978,14776,3022],{"emptyLinePlaceholder":3021},[2978,14778,14779,14782,14784,14787,14789,14791,14793,14795,14798,14800,14802,14805],{"class":2980,"line":6192},[2978,14780,14781],{"class":3418},"            HealthCheckStatus",[2978,14783,3119],{"class":3049},[2978,14785,14786],{"class":2991},"WithLabels",[2978,14788,3443],{"class":3049},[2978,14790,12532],{"class":3418},[2978,14792,3119],{"class":3049},[2978,14794,9360],{"class":3418},[2978,14796,14797],{"class":3049},").",[2978,14799,13289],{"class":2991},[2978,14801,3443],{"class":3049},[2978,14803,14804],{"class":3418},"statusValue",[2978,14806,3477],{"class":3049},[2978,14808,14809,14812,14814,14816,14818,14820,14822,14824,14826,14828,14830,14832,14834,14836,14838,14840,14842,14844],{"class":2980,"line":6197},[2978,14810,14811],{"class":3418},"            HealthCheckDuration",[2978,14813,3119],{"class":3049},[2978,14815,14786],{"class":2991},[2978,14817,3443],{"class":3049},[2978,14819,12532],{"class":3418},[2978,14821,3119],{"class":3049},[2978,14823,9360],{"class":3418},[2978,14825,14797],{"class":3049},[2978,14827,13289],{"class":2991},[2978,14829,3443],{"class":3049},[2978,14831,12532],{"class":3418},[2978,14833,3119],{"class":3049},[2978,14835,9371],{"class":3418},[2978,14837,3119],{"class":3049},[2978,14839,9390],{"class":3418},[2978,14841,3119],{"class":3049},[2978,14843,9293],{"class":3418},[2978,14845,3477],{"class":3049},[2978,14847,14848],{"class":2980,"line":6214},[2978,14849,6442],{"class":3049},[2978,14851,14852],{"class":2980,"line":6219},[2978,14853,3022],{"emptyLinePlaceholder":3021},[2978,14855,14856,14858,14860,14862,14864],{"class":2980,"line":6232},[2978,14857,3568],{"class":3567},[2978,14859,3518],{"class":3418},[2978,14861,3119],{"class":3049},[2978,14863,9415],{"class":3418},[2978,14865,4539],{"class":3049},[2978,14867,14868],{"class":2980,"line":6243},[2978,14869,3617],{"class":3049},[2978,14871,14872],{"class":2980,"line":6268},[2978,14873,3622],{"class":3049},[2964,14875,14876],{},[3088,14877,14878],{},"Prometheus scrape config:",[2968,14880,14882],{"className":3641,"code":14881,"language":3643,"meta":2973,"style":2973},"scrape_configs:\n  - job_name: 'ecommerce-api'\n    static_configs:\n      - targets: ['api.example.com:80']\n    metrics_path: '/metrics'\n    scrape_interval: 15s\n",[2975,14883,14884,14891,14904,14911,14927,14937],{"__ignoreMap":2973},[2978,14885,14886,14889],{"class":2980,"line":2981},[2978,14887,14888],{"class":3650},"scrape_configs",[2978,14890,3654],{"class":3049},[2978,14892,14893,14896,14899,14901],{"class":2980,"line":2988},[2978,14894,14895],{"class":3049},"  - ",[2978,14897,14898],{"class":3650},"job_name",[2978,14900,3669],{"class":3049},[2978,14902,14903],{"class":3672},"'ecommerce-api'\n",[2978,14905,14906,14909],{"class":2980,"line":2999},[2978,14907,14908],{"class":3650},"    static_configs",[2978,14910,3654],{"class":3049},[2978,14912,14913,14915,14918,14921,14924],{"class":2980,"line":3018},[2978,14914,8372],{"class":3049},[2978,14916,14917],{"class":3650},"targets",[2978,14919,14920],{"class":3049},": [",[2978,14922,14923],{"class":3672},"'api.example.com:80'",[2978,14925,14926],{"class":3049},"]\n",[2978,14928,14929,14932,14934],{"class":2980,"line":3025},[2978,14930,14931],{"class":3650},"    metrics_path",[2978,14933,3669],{"class":3049},[2978,14935,14936],{"class":3672},"'/metrics'\n",[2978,14938,14939,14942,14944],{"class":2980,"line":3031},[2978,14940,14941],{"class":3650},"    scrape_interval",[2978,14943,3669],{"class":3049},[2978,14945,14946],{"class":3672},"15s\n",[2964,14948,14949],{},[3088,14950,14951],{},"Grafana dashboard query:",[2968,14953,14957],{"className":14954,"code":14955,"language":14956,"meta":2973,"style":2973},"language-promql shiki shiki-themes light-plus dark-plus dark-plus","# Health check status\nhealth_check_status{check_name=\"database\"}\n\n# Health check duration\nhealth_check_duration_milliseconds{check_name=\"database\"}\n\n# Alert rule\nhealth_check_status{check_name=\"database\"} \u003C 2\n","promql",[2975,14958,14959,14964,14969,14973,14978,14983,14987,14992],{"__ignoreMap":2973},[2978,14960,14961],{"class":2980,"line":2981},[2978,14962,14963],{},"# Health check status\n",[2978,14965,14966],{"class":2980,"line":2988},[2978,14967,14968],{},"health_check_status{check_name=\"database\"}\n",[2978,14970,14971],{"class":2980,"line":2999},[2978,14972,3022],{"emptyLinePlaceholder":3021},[2978,14974,14975],{"class":2980,"line":3018},[2978,14976,14977],{},"# Health check duration\n",[2978,14979,14980],{"class":2980,"line":3025},[2978,14981,14982],{},"health_check_duration_milliseconds{check_name=\"database\"}\n",[2978,14984,14985],{"class":2980,"line":3031},[2978,14986,3022],{"emptyLinePlaceholder":3021},[2978,14988,14989],{"class":2980,"line":3040},[2978,14990,14991],{},"# Alert rule\n",[2978,14993,14994],{"class":2980,"line":3059},[2978,14995,14996],{},"health_check_status{check_name=\"database\"} \u003C 2\n",[3735,14998],{},[2959,15000,15002],{"id":15001},"резюме","Резюме",[2964,15004,15005,15006,15009],{},"У цій статті ви навчилися створювати ",[3088,15007,15008],{},"комплексну систему health checks"," для Web API:",[3351,15011,15013],{"id":15012},"ключові-концепції","Ключові концепції",[2964,15015,15016],{},[3088,15017,15018],{},"1. Три типи health checks:",[3092,15020,15021,15026,15031],{},[3095,15022,15023,15025],{},[3088,15024,3872],{}," — чи завершився запуск?",[3095,15027,15028,15030],{},[3088,15029,3888],{}," — чи живий процес?",[3095,15032,15033,15035],{},[3088,15034,3904],{}," — чи готовий приймати трафік?",[2964,15037,15038],{},[3088,15039,15040],{},"2. HealthStatus:",[3092,15042,15043,15048,15053],{},[3095,15044,15045,15047],{},[3088,15046,3591],{}," — все працює",[3095,15049,15050,15052],{},[3088,15051,4050],{}," — працює, але з проблемами",[3095,15054,15055,15057],{},[3088,15056,3605],{}," — не працює",[2964,15059,15060],{},[3088,15061,15062],{},"3. Вбудовані чеки:",[3092,15064,15065,15068,15071,15074],{},[3095,15066,15067],{},"SQL Server, PostgreSQL, MySQL",[3095,15069,15070],{},"Redis, MongoDB, Elasticsearch",[3095,15072,15073],{},"RabbitMQ, Kafka",[3095,15075,15076],{},"HTTP endpoints",[2964,15078,15079],{},[3088,15080,15081],{},"4. Кастомні чеки:",[3092,15083,15084,15087,15090,15093],{},[3095,15085,15086],{},"Disk space, memory usage",[3095,15088,15089],{},"External APIs",[3095,15091,15092],{},"Circuit breakers",[3095,15094,15095],{},"Rate limiting",[2964,15097,15098],{},[3088,15099,15100],{},"5. Health Check UI:",[3092,15102,15103,15106,15109],{},[3095,15104,15105],{},"Інтерактивний dashboard",[3095,15107,15108],{},"Історія перевірок",[3095,15110,15111],{},"Real-time моніторинг",[2964,15113,15114],{},[3088,15115,15116],{},"6. Kubernetes Integration:",[3092,15118,15119,15122,15125],{},[3095,15120,15121],{},"Startup, Liveness, Readiness probes",[3095,15123,15124],{},"Автоматичний restart при failure",[3095,15126,15127],{},"Automatic traffic management",[3351,15129,15131],{"id":15130},"best-practices","Best Practices",[2964,15133,15134,15135,15138,15139,15142,15143,15146,15147,15142,15149,15152,15153,15142,15155,15158,15159,15142,15161,15164,15165,15142,15167,15170,15171,15142,15173,15176],{},"✅ ",[3088,15136,15137],{},"Використовуйте tags"," для розділення live/ready чеків",[15140,15141],"br",{},"\n✅ ",[3088,15144,15145],{},"Встановлюйте timeouts"," для всіх чеків (3-5 секунд)",[15140,15148],{},[3088,15150,15151],{},"Логуйте зміни статусу"," для debugging",[15140,15154],{},[3088,15156,15157],{},"Кешуйте результати"," для зменшення навантаження",[15140,15160],{},[3088,15162,15163],{},"Моніторьте health checks"," через Prometheus/CloudWatch",[15140,15166],{},[3088,15168,15169],{},"Налаштуйте алерти"," на Unhealthy статус",[15140,15172],{},[3088,15174,15175],{},"Тестуйте health checks"," у staging перед production",[5503,15178,15179,15184],{},[2964,15180,15181],{},[3088,15182,15183],{},"Production Checklist:",[3092,15185,15186,15189,15192,15195,15198,15201,15204],{},[3095,15187,15188],{},"✅ Startup probe для повільного старту",[3095,15190,15191],{},"✅ Liveness probe для deadlock detection",[3095,15193,15194],{},"✅ Readiness probe для всіх залежностей",[3095,15196,15197],{},"✅ Health Check UI для моніторингу",[3095,15199,15200],{},"✅ Alerting на зміну статусу",[3095,15202,15203],{},"✅ Prometheus metrics export",[3095,15205,15206],{},"✅ Graceful degradation при Degraded статусі",[3735,15208],{},[2959,15210,15212],{"id":15211},"додаткові-ресурси","Додаткові ресурси",[15214,15215,15216,15228,15237,15246],"card-group",{},[15217,15218,15221],"card",{"icon":15219,"title":15220},"i-heroicons-heart","ASP.NET Core Health Checks",[15222,15223,15227],"a",{"href":15224,"rel":15225},"https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks",[15226],"nofollow","Official Documentation",[15217,15229,15232],{"icon":15230,"title":15231},"i-heroicons-check-circle","AspNetCore.Diagnostics.HealthChecks",[15222,15233,15236],{"href":15234,"rel":15235},"https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks",[15226],"Community Health Checks Library",[15217,15238,15241],{"icon":15239,"title":15240},"i-heroicons-server","Kubernetes Probes",[15222,15242,15245],{"href":15243,"rel":15244},"https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",[15226],"Configure Liveness, Readiness and Startup Probes",[15217,15247,15250],{"icon":15248,"title":15249},"i-heroicons-chart-bar","Health Check UI",[15222,15251,15254],{"href":15252,"rel":15253},"https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/tree/master/src/HealthChecks.UI",[15226],"Health Checks UI Documentation",[3735,15256],{},[3344,15258,15260,4381,15263,15266],{"icon":15259},"i-heroicons-arrow-right",[3088,15261,15262],{},"Наступна стаття:",[15222,15264,15265],{"href":1340},"Підсумковий проєкт: Production-Ready REST API"," — наскрізний проєкт Book Store REST API, що поєднує всі 11 попередніх статей: Controllers, ActionResult, Content Negotiation, API Versioning, ProblemDetails, Filters, Pagination, HATEOAS, Hybrid Architecture, Documentation, Health Checks.",[15268,15269,15270],"style",{},"html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html pre.shiki code .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .su1O8, html code.shiki .su1O8{--shiki-light:#0000FF;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sN1BT, html code.shiki .sN1BT{--shiki-light:#267F99;--shiki-default:#4EC9B0;--shiki-dark:#4EC9B0}html pre.shiki code .sCDza, html code.shiki .sCDza{--shiki-light:#AF00DB;--shiki-default:#CE92A4;--shiki-dark:#CE92A4}html pre.shiki code .sKtos, html code.shiki .sKtos{--shiki-light:#800000;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .su9tN, html code.shiki .su9tN{--shiki-light:#0000FF;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .sLwNe, html code.shiki .sLwNe{--shiki-light:#0451A5;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sD7JJ, html code.shiki .sD7JJ{--shiki-light:#000000FF;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}",{"title":2973,"searchDepth":2988,"depth":2988,"links":15272},[15273,15276,15281,15290,15297,15310,15314],{"id":2961,"depth":2988,"text":2962,"children":15274},[15275],{"id":3353,"depth":2999,"text":3354},{"id":3739,"depth":2988,"text":3740,"children":15277},[15278,15279,15280],{"id":3743,"depth":2999,"text":3744},{"id":3927,"depth":2999,"text":3928},{"id":4086,"depth":2999,"text":4087},{"id":4356,"depth":2988,"text":4357,"children":15282},[15283,15284,15285,15286,15287,15288,15289],{"id":4360,"depth":2999,"text":4361},{"id":4367,"depth":2999,"text":4368},{"id":4501,"depth":2999,"text":4502},{"id":5139,"depth":2999,"text":5140},{"id":5653,"depth":2999,"text":5654},{"id":8022,"depth":2999,"text":8023},{"id":8236,"depth":2999,"text":8237},{"id":9118,"depth":2988,"text":9119,"children":15291},[15292,15293,15294,15295,15296],{"id":9122,"depth":2999,"text":9123},{"id":9551,"depth":2999,"text":9552},{"id":9828,"depth":2999,"text":9829},{"id":10284,"depth":2999,"text":10285},{"id":10694,"depth":2999,"text":10695},{"id":11049,"depth":2988,"text":11050,"children":15298},[15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309],{"id":11053,"depth":2999,"text":11054},{"id":11059,"depth":2999,"text":11060},{"id":11138,"depth":2999,"text":11139},{"id":11188,"depth":2999,"text":11189},{"id":11194,"depth":2999,"text":11195},{"id":11747,"depth":2999,"text":11748},{"id":12247,"depth":2999,"text":12248},{"id":12875,"depth":2999,"text":12876},{"id":12881,"depth":2999,"text":12882},{"id":13604,"depth":2999,"text":13605},{"id":14395,"depth":2999,"text":14396},{"id":15001,"depth":2988,"text":15002,"children":15311},[15312,15313],{"id":15012,"depth":2999,"text":15013},{"id":15130,"depth":2999,"text":15131},{"id":15211,"depth":2988,"text":15212},"IHealthCheck інтерфейс, вбудовані чеки (SQL Server, Redis, RabbitMQ), кастомні health checks (зовнішні API, диск, пам'ять), Health Check UI, tags та фільтри (liveness vs readiness), Kubernetes probes, structured health response.","md",null,{},{"title":1335,"description":15315},"hTKprWWtDLPqAYzaeVpoHYI_K0_DuWAG3KDPsIA-zxA",[15322,15324],{"title":1331,"path":1332,"stem":1333,"description":15323,"children":-1},"Production-level документація для Web API Controllers, XML-коментарі → OpenAPI, Swashbuckle фільтри (IOperationFilter, IDocumentFilter), аутентифікація у Swagger UI, NSwag для генерації C# та TypeScript клієнтів, Refit автоматичний HTTP-клієнт.",{"title":1339,"path":1340,"stem":1341,"description":15325,"children":-1},"Наскрізний проєкт Book Store REST API, що поєднує всі попередні статті - ControllerBase, ActionResult, Content Negotiation, API Versioning, ProblemDetails, Filters, Pagination, HATEOAS, Hybrid Architecture, Documentation, Health Checks. Повний production-ready проєкт з best practices.",1777912430511]