mirror of
git://f0xx.org/ac/ac-docs
synced 2026-07-29 05:18:46 +03:00
new DR and spec for cluster monitoring, docs updated
This commit is contained in:
@@ -279,7 +279,7 @@ endobj
|
||||
endobj
|
||||
46 0 obj
|
||||
<<
|
||||
/Author (Android Cast project) /CreationDate (D:20260623115604+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260623115604+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Author (Android Cast project) /CreationDate (D:20260626184402+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260626184402+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (URL shortener service \204 design review \(DR\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
@@ -553,7 +553,7 @@ xref
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<875c6f1c7edbf45055101437d8ba9dff><875c6f1c7edbf45055101437d8ba9dff>]
|
||||
[<b881146e81a0400dc0faf4d7b18a637b><b881146e81a0400dc0faf4d7b18a637b>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 46 0 R
|
||||
|
||||
@@ -498,7 +498,7 @@ endobj
|
||||
endobj
|
||||
79 0 obj
|
||||
<<
|
||||
/Author (Android Cast project) /CreationDate (D:20260623115604+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260623115604+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Author (Android Cast project) /CreationDate (D:20260626184402+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260626184402+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (Platform scaling and multi-environment architecture \204 design review \(DR\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
@@ -933,7 +933,7 @@ xref
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<b9840886073ac09ffa3aaf04613fddc4><b9840886073ac09ffa3aaf04613fddc4>]
|
||||
[<e8d77b162988235e9282c6a48d0eb653><e8d77b162988235e9282c6a48d0eb653>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 79 0 R
|
||||
|
||||
@@ -324,7 +324,7 @@ endobj
|
||||
endobj
|
||||
51 0 obj
|
||||
<<
|
||||
/Author (Android Cast project) /CreationDate (D:20260623115604+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260623115604+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Author (Android Cast project) /CreationDate (D:20260626184402+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260626184402+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (RSSH routed egress \(dev-only\) \204 design review \(DR\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
@@ -663,7 +663,7 @@ xref
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<8bb82ad74cbc70e21b326c36bdc6d400><8bb82ad74cbc70e21b326c36bdc6d400>]
|
||||
[<519e375ae3d00c8c0855ddd359ee5e1c><519e375ae3d00c8c0855ddd359ee5e1c>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 51 0 R
|
||||
|
||||
@@ -319,7 +319,7 @@ endobj
|
||||
endobj
|
||||
51 0 obj
|
||||
<<
|
||||
/Author (Android Cast project) /CreationDate (D:20260623115605+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260623115605+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Author (Android Cast project) /CreationDate (D:20260626184403+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260626184403+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (Codec2 / ultra-low-bandwidth voice \204 design review \(DR\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
@@ -657,7 +657,7 @@ xref
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<46cf1dfdb90851c909d86a9cdac2e0a3><46cf1dfdb90851c909d86a9cdac2e0a3>]
|
||||
[<067f365549c6352e4507032702d5c987><067f365549c6352e4507032702d5c987>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 51 0 R
|
||||
|
||||
@@ -520,7 +520,7 @@ endobj
|
||||
endobj
|
||||
85 0 obj
|
||||
<<
|
||||
/Author (Android Cast project) /CreationDate (D:20260623115605+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260623115605+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Author (Android Cast project) /CreationDate (D:20260626184403+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260626184403+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (Repository and microservice reorganization \204 design review \(DR\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
@@ -1072,7 +1072,7 @@ xref
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<d2f7142333d712b3c1c2561068c30494><d2f7142333d712b3c1c2561068c30494>]
|
||||
[<e9227d6d82ddd0becfc6cb9795cfdb6c><e9227d6d82ddd0becfc6cb9795cfdb6c>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 85 0 R
|
||||
|
||||
@@ -82,7 +82,7 @@ endobj
|
||||
endobj
|
||||
14 0 obj
|
||||
<<
|
||||
/Author (Android Cast project) /CreationDate (D:20260623115606+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260623115606+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Author (Android Cast project) /CreationDate (D:20260626184404+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260626184404+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (Live Cast Control Plane \(P0-P2 kickoff\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
@@ -166,7 +166,7 @@ xref
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<c4fec4b99072874c8420e5c9ea80366d><c4fec4b99072874c8420e5c9ea80366d>]
|
||||
[<33f3e1c0301273f67e72a0a82caefd37><33f3e1c0301273f67e72a0a82caefd37>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 14 0 R
|
||||
|
||||
332
DRs/20260626_cluster_monitoring.md
Normal file
332
DRs/20260626_cluster_monitoring.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# Infrastructure health monitoring — design review (DR)
|
||||
|
||||
<!-- doc-meta:start -->
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Author | Anton Afanasyeu |
|
||||
| Revision | R0 |
|
||||
| Creation date | 2026-06-26 |
|
||||
| Last modification date | 2026-06-26 |
|
||||
| Co-authored | Cursor Agent (project assistant) |
|
||||
| Severity | high |
|
||||
| State | accepted |
|
||||
| Document type | DR |
|
||||
| Superseded by | — |
|
||||
| Specification | [docs/specs/20260626_cluster_monitoring.md](../specs/20260626_cluster_monitoring.md) |
|
||||
<!-- doc-meta:end -->
|
||||
|
||||
---
|
||||
|
||||
**Document type:** DR (Design Review)
|
||||
**Source draft:** [docs/drafts/20260626_cluster_monitoring.txt](../drafts/20260626_cluster_monitoring.txt)
|
||||
**Specification:** [docs/specs/20260626_cluster_monitoring.md](../specs/20260626_cluster_monitoring.md) (normative implementation doc)
|
||||
**PDF:** [20260626_cluster_monitoring.pdf](20260626_cluster_monitoring.pdf) · Regenerate: `bash ac-docs/build-pdf.sh`
|
||||
**Status:** Accepted R0 — implement per SPEC
|
||||
**Scope:** Passive infrastructure monitoring and alerting for the XEN-based VM cluster (cast01–cast04); Track A only — automated remediation is Track B ([drafts/20260626_cluster_orchestration.txt](../drafts/20260626_cluster_orchestration.txt))
|
||||
|
||||
**Related:** [INFRA.md](../INFRA.md) · [specs/20100612_1_scaling.md](../specs/20100612_1_scaling.md) · [specs/20260618_repos_reorganizing.md](../specs/20260618_repos_reorganizing.md) · [orchestration/sim/cluster0/ARCHITECTURE.md](../../orchestration/sim/cluster0/ARCHITECTURE.md) · [20260620_postgres_timescale_db_platform.md](../20260620_postgres_timescale_db_platform.md)
|
||||
|
||||
**Documentation index:** [README.md](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
- [1. Executive summary](#1-executive-summary)
|
||||
- [2. Problem statement](#2-problem-statement)
|
||||
- [3. Track A / Track B scope split](#3-track-a--track-b-scope-split)
|
||||
- [4. Responsibility domains](#4-responsibility-domains)
|
||||
- [5. Monitoring topology — cast04](#5-monitoring-topology--cast04)
|
||||
- [6. Tool selection](#6-tool-selection)
|
||||
- [7. Alert channels](#7-alert-channels)
|
||||
- [8. Infrastructure constraints](#8-infrastructure-constraints)
|
||||
- [9. Relationship to TimescaleDB / business metrics](#9-relationship-to-timescaledb--business-metrics)
|
||||
- [10. Risks and mitigations](#10-risks-and-mitigations)
|
||||
- [11. Non-goals (Track B reference)](#11-non-goals-track-b-reference)
|
||||
- [12. Related documents](#12-related-documents)
|
||||
- [13. Changelog](#13-changelog)
|
||||
<!-- /toc -->
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive summary
|
||||
|
||||
**Question:** How should the VM cluster (cast01–cast03) and its microservices be continuously monitored, and what tooling should be deployed?
|
||||
|
||||
**Short answer:** Deploy a dedicated monitoring VM (cast04, Alpine LTS) running Prometheus + node_exporter (per-node) + blackbox_exporter + mysqld_exporter + Alertmanager + Grafana. Alerts route to email (SMTP relay) and Telegram. External availability is covered by UptimeRobot (free tier, no install). Automated remediation is out of scope for R0 — it becomes Track B.
|
||||
|
||||
**DR decisions (R0):**
|
||||
|
||||
| Item | Decision |
|
||||
|------|----------|
|
||||
| **Scope** | Track A: passive monitoring + alerting only; no auto-remediation |
|
||||
| **Monitoring node** | **cast04** — dedicated 4th Alpine LTS VM; paravirt XEN guest |
|
||||
| **Metrics stack** | **Prometheus** + **node_exporter** + **blackbox_exporter** + **mysqld_exporter** |
|
||||
| **Dashboards** | **Grafana** (community dashboards; self-hosted on cast04) |
|
||||
| **Alerting** | **Alertmanager** → email SMTP relay + Telegram bot API |
|
||||
| **External uptime** | **UptimeRobot** free tier — no install; HTTP probe to `apps.f0xx.org` from internet |
|
||||
| **Status page** | **Uptime Kuma** on cast04 (Docker) — internal, access via SSH tunnel |
|
||||
| **Log aggregation** | Out of scope R0; Grafana Loki planned for R1 (Track B) |
|
||||
| **VictoriaMetrics** | Not used at R0 — not in Alpine apk; standard Prometheus sufficient at 3-node scale |
|
||||
| **Zabbix** | Not chosen — batteries-included but inflexible for future business metrics integration |
|
||||
| **Nagios** | Not chosen — legacy, superseded by Prometheus+Alertmanager |
|
||||
| **Kibana / ELK** | Excluded — log-centric, heavy, wrong tool for infra metrics |
|
||||
| **FE / router changes** | None at R0 — monitoring is internal; FE nginx config change only if external Grafana access added later |
|
||||
| **DNS changes** | None at R0 |
|
||||
| **Data residency** | All metric data stays self-hosted (no external aggregator) |
|
||||
| **Track B** | Placeholder draft created: [drafts/20260626_cluster_orchestration.txt](../drafts/20260626_cluster_orchestration.txt) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Problem statement
|
||||
|
||||
The project runs a cluster of XEN-based VMs (cast01–cast03) hosting microservices at various complexity levels — from a single service per node to multi-node DB master/replica chains. As the microservice split progresses (per [specs/20260618_repos_reorganizing.md](../specs/20260618_repos_reorganizing.md)), manual observation of each service and node becomes impractical.
|
||||
|
||||
Key failure modes that must be detected and alerted:
|
||||
|
||||
| Category | Example failure |
|
||||
|----------|----------------|
|
||||
| Hardware | CPU steal time spiking (Xen overcommit), disk SMART pre-failure, RAM exhaustion |
|
||||
| Software | nginx 5xx surge, php-fpm worker saturation, MariaDB replication lag, process crash |
|
||||
| Network | Egress/ingress saturation, NIC packet drops |
|
||||
| Provider | Uplink outage, XEN host failure, VM unavailability |
|
||||
|
||||
None of these are currently monitored in a structured way.
|
||||
|
||||
---
|
||||
|
||||
## 3. Track A / Track B scope split
|
||||
|
||||
This DR and its SPEC cover **Track A only**.
|
||||
|
||||
| Track | Scope | Milestone |
|
||||
|-------|-------|-----------|
|
||||
| **Track A** (this SPEC) | Passive monitoring: observe, record, alert | R0 |
|
||||
| **Track B** (future) | Active remediation: orchestration reacts to alert signals — auto-scale, auto-failover, DDoS response | R1+ |
|
||||
|
||||
Track B details and prerequisites are captured in [drafts/20260626_cluster_orchestration.txt](../drafts/20260626_cluster_orchestration.txt). Track B MUST NOT be designed until Track A alerting is stable and at least 4 weeks of baseline metric data has been collected.
|
||||
|
||||
---
|
||||
|
||||
## 4. Responsibility domains
|
||||
|
||||
The infrastructure has two clearly bounded ownership layers:
|
||||
|
||||
```text
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Anton's layer (SaaS — contact owner for issues) │
|
||||
│ • Internet provider / uplink │
|
||||
│ • Router (Debian; config-only from project side) │
|
||||
│ • XEN hypervisor hosts + VM provisioning │
|
||||
│ • Internal network (10.7.0.0/8), git server │
|
||||
│ • FE VM (Gentoo HVM; nginx TLS; config-only) │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
delegated cluster boundary ↓
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Project owner's layer (full control) │
|
||||
│ • cast01 / cast02 / cast03 — workload VMs │
|
||||
│ • cast04 — monitoring VM (this SPEC) │
|
||||
│ • All software installed on these VMs │
|
||||
│ • MariaDB, nginx, PHP-FPM, microservices │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Monitoring responsibility boundary:** The project owner monitors everything within the delegated cluster. When monitoring detects that the cause is in Anton's layer (hardware fault, uplink, XEN host instability), the action is to notify Anton — not to auto-remediate.
|
||||
|
||||
**Hardware guarantee baseline** (from Anton's SLA commitment per draft):
|
||||
|
||||
| Resource | Guaranteed value |
|
||||
|----------|-----------------|
|
||||
| CPU | Intel Xeon Gold 5218, 8 real cores @ 2.30 GHz per node |
|
||||
| RAM | 8 GB per node |
|
||||
| Disk | 32 GB non-shared per node |
|
||||
| Network | 200 Mbit/s in/out |
|
||||
| Cluster size | 3 workload nodes (cast01–cast03) |
|
||||
|
||||
Monitoring MUST alert when measured values diverge significantly from this baseline (e.g. CPU steal > 10% for > 5 min = Xen overcommit alarm → notify Anton).
|
||||
|
||||
---
|
||||
|
||||
## 5. Monitoring topology — cast04
|
||||
|
||||
```text
|
||||
[ Internet ]
|
||||
│
|
||||
UptimeRobot (external)
|
||||
HTTP probe → apps.f0xx.org
|
||||
│
|
||||
┌──────────────┴──────────────┐
|
||||
│ FE (Gentoo HVM) │ ← no new software
|
||||
│ TLS nginx, 134.17.26.161 │
|
||||
└──────────────┬──────────────┘
|
||||
│ 10.7.0.0/8 internal
|
||||
┌────────────────────┼────────────────────────────┐
|
||||
│ │ cluster │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ cast01 │ │ cast02 │ │ cast03 │ │
|
||||
│ │workload │ │workload │ │workload │ │
|
||||
│ │node_exp │ │node_exp │ │node_exp │ │
|
||||
│ └────┬────┘ └────┬────┘ └────┬────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌────┴─────────────┴─────────────┴────┐ │
|
||||
│ │ cast04 (monitoring VM) │ │
|
||||
│ │ Prometheus Alertmanager Grafana │ │
|
||||
│ │ blackbox_exporter mysqld_exporter │ │
|
||||
│ │ Uptime Kuma (Docker) node_exporter │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
└───────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Prometheus scrapes node_exporter on cast01/cast02/cast03/cast04 via internal IPs
|
||||
- blackbox_exporter on cast04 probes service HTTP/TCP endpoints from inside cluster
|
||||
- mysqld_exporter runs on the MariaDB primary node (cast01 or cast02 per deployment)
|
||||
- cast04 has no workload services — monitoring-only
|
||||
- Access to Grafana/Uptime Kuma UI: SSH tunnel from dev machine at R0
|
||||
|
||||
**cast04 minimum spec (request from Anton):**
|
||||
|
||||
| Resource | Minimum |
|
||||
|----------|---------|
|
||||
| CPU | 2 vCPU |
|
||||
| RAM | 2 GB (Prometheus + Grafana + Alertmanager) |
|
||||
| Disk | 32 GB (90 days metric retention at 15s scrape) |
|
||||
| OS | Alpine latest LTS, paravirt XEN |
|
||||
|
||||
---
|
||||
|
||||
## 6. Tool selection
|
||||
|
||||
### 6.1 Decided stack
|
||||
|
||||
| Component | Package / source | Role |
|
||||
|-----------|-----------------|------|
|
||||
| Prometheus | `prometheus` (apk) | Time-series scraper + TSDB |
|
||||
| node_exporter | `prometheus-node-exporter` (apk) | Hardware + OS metrics per VM |
|
||||
| blackbox_exporter | `prometheus-blackbox-exporter` (apk) | HTTP/TCP service health probes |
|
||||
| mysqld_exporter | `prometheus-mysqld-exporter` (apk) | MariaDB metrics |
|
||||
| Alertmanager | `alertmanager` (apk) | Alert routing (email + Telegram) |
|
||||
| Grafana | `grafana` (apk) | Dashboards |
|
||||
| Uptime Kuma | Docker image `louislam/uptime-kuma` | Service status page |
|
||||
| UptimeRobot | SaaS free tier (web account) | External HTTP probe |
|
||||
|
||||
All apk packages are available in Alpine community/edge repos. Docker (`docker` apk) is available for Uptime Kuma.
|
||||
|
||||
### 6.2 Options rejected
|
||||
|
||||
| Tool | Reason not chosen |
|
||||
|------|------------------|
|
||||
| Kibana / ELK | Log-centric, heavy (Elasticsearch needs 4+ GB), wrong tool for infra metrics |
|
||||
| Zabbix | Batteries-included but less composable; harder to extend to business metrics later |
|
||||
| Nagios Core | Legacy; status-only; no time-series; superseded by Prometheus+Alertmanager |
|
||||
| VictoriaMetrics | Not in Alpine apk repos; standard Prometheus sufficient at 3-node scale |
|
||||
| Grafana Cloud | Data must remain self-hosted (PO preference) |
|
||||
| Netdata | Good for quick bootstrap but adds another agent daemon; Prometheus covers the same ground |
|
||||
|
||||
### 6.3 Future additions (R1 / Track B)
|
||||
|
||||
| Component | Role |
|
||||
|-----------|------|
|
||||
| Grafana Loki + Promtail | Centralized log aggregation (replaces manual syslog review) |
|
||||
| Alertmanager webhook handlers | Trigger ac-deploy scripts on alert (foundation for Track B remediation) |
|
||||
|
||||
---
|
||||
|
||||
## 7. Alert channels
|
||||
|
||||
| Channel | Tool | Requirement |
|
||||
|---------|------|-------------|
|
||||
| Email | Alertmanager SMTP | **Required** — primary alert channel |
|
||||
| Telegram | Alertmanager Telegram receiver | **Recommended** — fast ops notifications |
|
||||
| Status page | Uptime Kuma | **Recommended** — visual per-service uptime |
|
||||
| External uptime | UptimeRobot | **Required** — provider-fault detection |
|
||||
|
||||
**Email SMTP relay:** Alertmanager needs an outbound SMTP relay (NOT an inbound routing service). Options: Gmail account + app password, or Mailgun free tier (10k emails/month). **Note:** ImprovMX and addy.io are inbound email routing services — they are not SMTP relay providers and cannot be used for Alertmanager outbound alerts.
|
||||
|
||||
**Telegram:** Purely API-based — no software installation. Register a bot via @BotFather, obtain `TOKEN` and `CHAT_ID` (add bot to ops group or DM). Alertmanager calls Telegram HTTP API from cast04.
|
||||
|
||||
**Accounts to create before deploy (PO action):**
|
||||
|
||||
| Account | Purpose | Notes |
|
||||
|---------|---------|-------|
|
||||
| Gmail app password OR Mailgun free | Alertmanager SMTP relay | Gmail: Settings → Security → App passwords |
|
||||
| Telegram bot via @BotFather | Alertmanager Telegram receiver | Note TOKEN + CHAT_ID |
|
||||
| UptimeRobot free account | External HTTP probe | uptimerobot.com; add monitor for `apps.f0xx.org` |
|
||||
|
||||
---
|
||||
|
||||
## 8. Infrastructure constraints
|
||||
|
||||
Constraints discovered during DR review — all accounted for in SPEC:
|
||||
|
||||
| Constraint | Impact |
|
||||
|------------|--------|
|
||||
| Paravirt XEN guest (no HVM) | node_exporter works fine on paravirt; Xen steal time metric available |
|
||||
| Alpine LTS + apk only | All stack components available as apk packages; Uptime Kuma via Docker (apk-installable) |
|
||||
| FE / router: no new software | Monitoring is entirely internal; no FE changes at R0 |
|
||||
| Data self-hosted | No Grafana Cloud or external aggregator |
|
||||
| 8 GB RAM per workload node | Standard Prometheus on cast04 is sufficient (Prometheus ~200–500 MB for this scale) |
|
||||
|
||||
---
|
||||
|
||||
## 9. Relationship to TimescaleDB / business metrics
|
||||
|
||||
The project has a separate PostgreSQL + TimescaleDB platform plan ([20260620_postgres_timescale_db_platform.md](../20260620_postgres_timescale_db_platform.md)). These two stores serve different purposes and coexist:
|
||||
|
||||
| Layer | Store | Metrics type | Retention |
|
||||
|-------|-------|-------------|-----------|
|
||||
| Infrastructure | Prometheus TSDB (cast04) | CPU, RAM, disk, latency, process health | 90 days |
|
||||
| Business / app | TimescaleDB (PostgreSQL) | Crash rates, session counts, graph analytics | Long-term |
|
||||
|
||||
Grafana on cast04 can query **both** data sources. No ETL between them is required.
|
||||
|
||||
---
|
||||
|
||||
## 10. Risks and mitigations
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| cast04 itself fails — monitoring goes dark | cast04 is monitored by UptimeRobot externally; Alertmanager persistence via local disk |
|
||||
| Xen host failure takes cast04 offline | UptimeRobot external probe survives; operator is alerted from outside |
|
||||
| SMTP relay rate limit hit during incident storm | Alertmanager grouping + repeat_interval configured; Telegram as parallel channel |
|
||||
| apk package version lag | Use Alpine edge repo for monitoring components if LTS versions are too old |
|
||||
| Prometheus disk fill (90 day retention + 3 nodes) | Estimated < 5 GB for 3 nodes at 15s scrape; 32 GB disk leaves comfortable margin |
|
||||
| cast04 RAM insufficient | 2 GB minimum; Prometheus + Grafana + Alertmanager combined ~500 MB–1 GB typical |
|
||||
| External UptimeRobot free tier limits | Free tier: 50 monitors, 5-min check interval — sufficient for R0 |
|
||||
|
||||
---
|
||||
|
||||
## 11. Non-goals (Track B reference)
|
||||
|
||||
The following are explicitly **out of scope** for this DR and SPEC:
|
||||
|
||||
- Automatic horizontal scaling (add node under CPU load)
|
||||
- Automatic scale-in (remove idle node)
|
||||
- DDoS automated response
|
||||
- Automatic storage failover
|
||||
- Any orchestration that modifies cluster topology without human approval
|
||||
|
||||
These scenarios are documented as future work in **[drafts/20260626_cluster_orchestration.txt](../drafts/20260626_cluster_orchestration.txt)** (Track B). Track B DR and SPEC will be authored once Track A is operational and baseline metrics are available.
|
||||
|
||||
---
|
||||
|
||||
## 12. Related documents
|
||||
|
||||
| Document | Role |
|
||||
|----------|------|
|
||||
| [specs/20260626_cluster_monitoring.md](../specs/20260626_cluster_monitoring.md) | Normative implementation SPEC (this DR's output) |
|
||||
| [drafts/20260626_cluster_orchestration.txt](../drafts/20260626_cluster_orchestration.txt) | Track B placeholder (auto-remediation, future) |
|
||||
| [INFRA.md](../INFRA.md) | FE/BE topology, hosts, ports |
|
||||
| [specs/20100612_1_scaling.md](../specs/20100612_1_scaling.md) | VM roles and cluster layout |
|
||||
| [specs/20260618_repos_reorganizing.md](../specs/20260618_repos_reorganizing.md) | Microservice split (monitoring must track each MS) |
|
||||
| [20260620_postgres_timescale_db_platform.md](../20260620_postgres_timescale_db_platform.md) | TimescaleDB for business metrics (complements Prometheus) |
|
||||
| [orchestration/sim/cluster0/ARCHITECTURE.md](../../orchestration/sim/cluster0/ARCHITECTURE.md) | Lab cluster node layout |
|
||||
| [GRAFANA_vs_others_graphvis_pivot.md](../GRAFANA_vs_others_graphvis_pivot.md) | Earlier Grafana evaluation for app analytics |
|
||||
|
||||
---
|
||||
|
||||
## 13. Changelog
|
||||
|
||||
| Rev | Date | Change |
|
||||
|-----|------|--------|
|
||||
| R0 | 2026-06-26 | Initial DR — accepted; decisions locked; SPEC generated |
|
||||
393
DRs/20260626_cluster_monitoring.pdf
Normal file
393
DRs/20260626_cluster_monitoring.pdf
Normal file
@@ -0,0 +1,393 @@
|
||||
%PDF-1.4
|
||||
%“Œ‹ž ReportLab Generated PDF document (opensource)
|
||||
1 0 obj
|
||||
<<
|
||||
/F1 2 0 R /F2 3 0 R /F3 20 0 R /F4 21 0 R /F5 22 0 R /F6 23 0 R
|
||||
>>
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
3 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 762.0394 124.373 773.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 751.0394 121.717 762.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 740.0394 156.389 751.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 729.0394 136.381 740.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
8 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 718.0394 160.405 729.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
9 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 707.0394 103.933 718.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
10 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 59.68504 696.6019 119.295 706.6019 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
11 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 59.68504 686.6019 126.8025 696.6019 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
12 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 59.68504 676.6019 174.7275 686.6019 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
13 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 666.0394 105.269 677.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
14 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 655.0394 142.613 666.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
15 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 644.0394 223.517 655.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
16 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 633.0394 134.605 644.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
17 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 622.0394 166.613 633.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
18 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 611.0394 127.949 622.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
19 0 obj
|
||||
<<
|
||||
/Border [ 0 0 0 ] /Contents () /Dest [ 24 0 R /Fit ] /Rect [ 45.68504 600.0394 97.71704 611.0394 ] /Subtype /Link /Type /Annot
|
||||
>>
|
||||
endobj
|
||||
20 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
21 0 obj
|
||||
<<
|
||||
/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
22 0 obj
|
||||
<<
|
||||
/BaseFont /Symbol /Name /F5 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
23 0 obj
|
||||
<<
|
||||
/BaseFont /ZapfDingbats /Name /F6 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
24 0 obj
|
||||
<<
|
||||
/Contents 50 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
25 0 obj
|
||||
<<
|
||||
/Annots [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R
|
||||
14 0 R 15 0 R 16 0 R 17 0 R 18 0 R 19 0 R ] /Contents 51 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0
|
||||
/Trans <<
|
||||
|
||||
>> /Type /Page
|
||||
>>
|
||||
endobj
|
||||
26 0 obj
|
||||
<<
|
||||
/Contents 52 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
27 0 obj
|
||||
<<
|
||||
/Contents 53 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
28 0 obj
|
||||
<<
|
||||
/Contents 54 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
29 0 obj
|
||||
<<
|
||||
/Contents 55 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
30 0 obj
|
||||
<<
|
||||
/Outlines 32 0 R /PageMode /UseNone /Pages 49 0 R /Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
31 0 obj
|
||||
<<
|
||||
/Author (Android Cast project) /CreationDate (D:20260626184404+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260626184404+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (Infrastructure health monitoring \204 design review \(DR\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
32 0 obj
|
||||
<<
|
||||
/Count 17 /First 33 0 R /Last 48 0 R /Type /Outlines
|
||||
>>
|
||||
endobj
|
||||
33 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 34 0 R /Parent 32 0 R /Title (1. Executive summary)
|
||||
>>
|
||||
endobj
|
||||
34 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 35 0 R /Parent 32 0 R /Prev 33 0 R /Title (2. Problem statement)
|
||||
>>
|
||||
endobj
|
||||
35 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 36 0 R /Parent 32 0 R /Prev 34 0 R /Title (3. Track A / Track B scope split)
|
||||
>>
|
||||
endobj
|
||||
36 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 37 0 R /Parent 32 0 R /Prev 35 0 R /Title (4. Responsibility domains)
|
||||
>>
|
||||
endobj
|
||||
37 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 38 0 R /Parent 32 0 R /Prev 36 0 R /Title (5. Monitoring topology \204 cast04)
|
||||
>>
|
||||
endobj
|
||||
38 0 obj
|
||||
<<
|
||||
/Count 3 /Dest [ 24 0 R /Fit ] /First 39 0 R /Last 41 0 R /Next 42 0 R /Parent 32 0 R
|
||||
/Prev 37 0 R /Title (6. Tool selection)
|
||||
>>
|
||||
endobj
|
||||
39 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 40 0 R /Parent 38 0 R /Title (6.1 Decided stack)
|
||||
>>
|
||||
endobj
|
||||
40 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 41 0 R /Parent 38 0 R /Prev 39 0 R /Title (6.2 Options rejected)
|
||||
>>
|
||||
endobj
|
||||
41 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Parent 38 0 R /Prev 40 0 R /Title (6.3 Future additions \(R1 / Track B\))
|
||||
>>
|
||||
endobj
|
||||
42 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 43 0 R /Parent 32 0 R /Prev 38 0 R /Title (7. Alert channels)
|
||||
>>
|
||||
endobj
|
||||
43 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 44 0 R /Parent 32 0 R /Prev 42 0 R /Title (8. Infrastructure constraints)
|
||||
>>
|
||||
endobj
|
||||
44 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 45 0 R /Parent 32 0 R /Prev 43 0 R /Title (9. Relationship to TimescaleDB / business metrics)
|
||||
>>
|
||||
endobj
|
||||
45 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 46 0 R /Parent 32 0 R /Prev 44 0 R /Title (10. Risks and mitigations)
|
||||
>>
|
||||
endobj
|
||||
46 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 47 0 R /Parent 32 0 R /Prev 45 0 R /Title (11. Non-goals \(Track B reference\))
|
||||
>>
|
||||
endobj
|
||||
47 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Next 48 0 R /Parent 32 0 R /Prev 46 0 R /Title (12. Related documents)
|
||||
>>
|
||||
endobj
|
||||
48 0 obj
|
||||
<<
|
||||
/Dest [ 24 0 R /Fit ] /Parent 32 0 R /Prev 47 0 R /Title (13. Changelog)
|
||||
>>
|
||||
endobj
|
||||
49 0 obj
|
||||
<<
|
||||
/Count 6 /Kids [ 24 0 R 25 0 R 26 0 R 27 0 R 28 0 R 29 0 R ] /Type /Pages
|
||||
>>
|
||||
endobj
|
||||
50 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 985
|
||||
>>
|
||||
stream
|
||||
Gat=+>Aoub'RnB330.pQ34A>\*kQQc2YEmqg/Fi*JWinVO;ZNIqt2bP$'uqP,Eu;<J)@g3SE")\fKQ,1O*:S26<N"U+;D[-&;D$TGOR2SrL&e/Q&HsHF3HmAM6IdMMmLk<qpaXI+>4:.qLBih!@+8h1Wr@M@O-Ug.tRi]PmBu4!Sg3#QVuK30S,-(fh+bgd:I,dX^IouXkCKBcVftm1g@jBV%OD@V!AGrH:cX;4C6eo+"o8jI"q+tk$:Gl^qG.k)'K:FN=d.o5S3.?I3Ukmhp!:/4k<K?qJ\Aoo9IW$WXNd2Yf$d+#?9as;.%m([MK5,]&.gr#P9u?\.;^G'AP>JL_;1FDUDM.eWo6tT#2J,:TZo?+bTc=5^=TAkp0m=3HHm.=FSOGVXUn;H+ce0)!7rAQ\&R7,lKrI/`(gb&mTqO7l<H*Af]>d*RM9pg*UHBP]23k-=R>RY@q.?*ci9+-.dYrSj,OaBa_R+bpM$eCmdPZR66,f<KoqkRjubIZo)HSUH7I/>MtAqcUMS3JUF*jfu.t*`)j&bA!M`n1B$#lV6RW8MQ)tQ0rJJGo>'#kGID>B6CjpQ1j6.>?.(,'Uq>g]GuR;D)Nh3:kY#4B)Qq[A1\S'/lhjo)#,7h_$PR*K3I=P(,Fk=sTO*jXc.hEY\8uT:ok$Hlk3SQB1FcAZM5*%2HS_n"$p81oDt:En<P)r$p*6r9+CI3/;r#&jmZfD(U([5a+s,MC<'AorLRf1:X8#dd7QB%c5KVqp;-5!\U8fMA;"56<bJG\+e?kZXG:IEXg>DK1q,B+eqqKu;r,,_HGWg5-];FJa?FTE#:Z;!MmX3$VKrlY6LoO4V4iJAGWh!s%GqB`tU1apg]-uI-Jds2B0X:eC%75.JU-Z!nJi*h;KCE&jFk&Mq#a=^3:uREf#7oX_]+K!h+@1Bq\.Kk*#dJTErn)"^![KrjWE+gp:EnfQo71l"$1[>>blrY%FH7f:r<%J,)7'~>endstream
|
||||
endobj
|
||||
51 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 849
|
||||
>>
|
||||
stream
|
||||
Gatn%>u03/'Sc)R/']G7R^&F%8Tk=@Ue1Go\O8d#EEgo1c>3a*^Y_U\fEOn<:_Y?#XkWU?q0Kr/ik_Luli9d13'(]f3)j[$.7p60#\V]Qa,97cVATt77T7D"SC"'*nTXacT`n5t"@uDtRMS6[N0bsq[oq[>Z:>d%U$>I,mkm'H'b78?\lE.i+KYsm"Fg^-%9.78m;I6^UbCp^oTNFL5r%bg:$R\QfhWoLTPkS?U$HH;*s%Ih9*&u5?_,.IFPoM,</2WQ!(`!D!"o?uX5shOiFm^b!aaS%j3b=s#)9mi*+":i$!\n9>N>Ca7e(h=CfbBc;\VnV7?J2WA;q)MBsW@uHe[9!4^<$!K<0KoB`npjQGO6$+_t<OW`:ffC]:Fgb5YOU.<(G5!9E2-H>;.?J\e=K\l$^SVK*K(:b7UAiCcCQhh+id(^\_\:uk8J,]Gr#_'u=P7aF&\#8c`No3<>+@#9!)lGs8O\&nl9gY*Lp7^S&oP,6Y9![#Y?@8j[%:1:snNXsdK0p>k<Hmt5!*$&lZARqigCg3i[VnB*8FaAZ(\K8CAb'W>OE*C9.-#><.TnoWFc9lFekcf"a1MR$r?dA&cmQOkHG%9i]/DGr"n'kN$AYb3`?+QF!0tpF%Ng7W,To8OBXBa!J(u!koCn-L%&Kddl8Wm"1._iWh@&2F.5dZKU;D<?AI>7GLDA(%R@5E@_Gi.oHUj<99E^9jF=0`io;!t?1oI&'EZSVF1*2(gdbO!Nc*G>O^:XA!#X#oE*KP_b!-)^2`NXKZ"j\4K>6-?<PSikaja]$3"!DfmTrF7*G,5/3tJ*\UWEl&1-#1#i[=>B43J7BOU^N<lV$_IE;cN~>endstream
|
||||
endobj
|
||||
52 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 3955
|
||||
>>
|
||||
stream
|
||||
Gau`VD,]IS')p1[d)WA@Z2C%!+0Lu^fpSC^@mXdCl\[/aZ'@_8hc@$+gonJYr";)2*'8LK<tkd-EiZgKmXD`O)!UOBeR'stki3(WI`;X4BXU1YdO[6PNc&JWJ">M,VIaPgf[_Y8:)qO*/Jm8*q9_63ChmoCiNEofN2so+bso#N@9n>2LF!BdQ7M7cLG.'=-MFa,7O^se'DgZ%c2L\$WECHf1IY*7)_0Jq6<!a'khFRcRPXh0Er0>W6`s^74IDh_39)&K4su81LEAbS`2+@bQ\KB;\mm_G?BC#.o&h]e=;l5r/[]\kp0c@SNn<#q69Vbb*_BKS[IYhT8iN65&*f-`*WhU.MHH5K<,RF7.Z*fG[V[%gm>%1W43VngSG3KaA2l33L*_g--Ro"E$3J##+ttBRKnsrHPVCEci*X98RTT6E`A7J5Q@RgIYp7Q%kKtQO5+:cP]&@PVN"X:\j2:8^*fLuV5/sgPLbCE!0s([)K\H'3_21^.k+rrnBVT?2+s2qtnl.e(@ZJkO7=X+L?\!_oSDWd3YsE>b4<U>-&C45R=\kqsBZ>o'K!%rj"n0"_,YMW,C[a(a"o(c^ZVpQ1'?)IDJ`&^:Mn-<k^ohu`g0(U(WoKk^2l2)dGXm6jmlsUOPm,:i=P=\EFU&l3pfVhe-r$d,6&L<8c^Z>eJA3gGP)0(K2R?:O6deWD_TP7NqW7DBe!I8EgJ>/Je(\Vk6<3k<:em@IMW^4X<:W>IrV:L9@_a=F0`SAoSB4kPK@]bmHj>7TDVE\@$/jU]$/6rM;WWX1.U50h23'P9];Ao3I$2RfORVuc/6`e4DI9V%h$[N;*=&(<JT"gUrZ_NQ[s?LWnJ`+A3"(+F$=*jD5+O2#@AuL8o6;f7Iq9Z9BMO[+7po7uS-^m._VhABY$Q?W&Vu-\/.YOe(qekW,`(?Ws,U%i\eLl+)gK"krJ#UMPHA;c!^#D$o%f\7=@!(7nn%_"CT]Z,:eIDilPs18$&^5.5'mETn19IXN!CDZ'_I^uFG?OBVpBIU^j8V4i"7X'G;0%*bldG>o6=P8W,1K&L%"$)^u)eN#)e&5$;!XOlL@qp+Rl&ch[@B_/>]"B6pnfm=R,Eop&KOi+Rd9Uc"KA/S:pJ.!Qg-#LqLT011pV\h\#W207Kb%<G5\ZaO/=%Rb9Nha!hR*E!hLWb0N@1n?!l\61At'>dV%*8J9ZBnH'$]Um7:K_F+_Mmt%Vk\#Au(!o9t]6+Nbmk"tGlGn<Gq[X:=T!]Ui9b>`sPrNLK;7ij@#,LaN;'fCDUR'qi.ErrG%OlkB;`57[m81s9h_!=BEYi25_n@]BQ(;BiDq,>Rif3@BNMP,[35KgMer@hg0l=LMcTRN,Jq]KH40ok00]9>.%RZq[`(s8.eQtI'STae(Fk';=_bO/f!SRWKp-\p#:l_-G:Lt5L.d8^L=OX!b?lss0E*-8a@84sUr'ILsd^SWjCCQF3aBFt3),(*<kr>+oa!>tkuKX$K0CFW<;6^h>GELh-$4$TC6J@N#VFLFKB&sciq0.g&c7116o@1'M!-:?n-gFOrZ>7ZS620MPeb'<;3j)lD]X$E5R6$X0t"DKAleH.K/l75[B-a*qF4eR,.Pd%&YG3fX'SYhp&!^ROm?@#/F[j#qL-2Ig?Cl<dDk(Uc9UB]:/34g2YeDDYXg:X`q8ii2n-f#rWbt'"[S]?E\iija[o)6m2JX:Nid0LjcQphVfq%X-98C1aaZ%>XO:)3ht1@+6=H&RN9HsPB>%tRC5r<9@a`GMT4B=lI5P@6PtH271<T\R=S3(kQ^6kU5@5CDirM_cESQ3s3q$@DKnNnrhq\db]pCU^]MJ_]&"Ck1pgqD&.),WqYKW4c2u+\<lbKt^l/OS1Sh.O_t1>6[u'383JNYVk&Hjg>tFGfr;9.d?[l9Y%UY[k-=>TZT<+.5U[(.#30p8,,rqO-'0_O;\Juap<<@r.7g;Q"\O@!Ri$gJa`+AOl_bTATs6jBVF#r%9*%74dVT%=(N#!^;hl8,ln%Or&i*;TT(.tl1Q$M5#ftfR3r(h.ABTK8TCY@b3`_4e9`n99U<L;>q\"B#ejeG).Z>0E[;r;jFbLSB>#Kn/==Ig!K^:$Ht97i(TD^TLH[&;]u@b-I*U;u[4q$%2LC_I5nK\dY(/N(iC#IO/m.0<R4gAX9^6.#co%9tH%NZL<2FT+#uHhap1G'TBL/*+Oro9bmU.,U:R3R"E?':%maM=uJ)\/6_bMSD_]_klKA$nsgPJ)\1-1&ir#;+uHb2\ThnL1tZkn/G$pDSDk&SJb$P1N;CtgsR;=Y&L^[W/6Y,l$1buWq;'HSqs'A8#_r:;LrWN&!!PY\#"mBO.O0pXGOH"5sDCk@MdLL24_-X*fh/^&JK[Oc[GX5@_jST7m<n'X-1^7Y0uXg6O5FWud\k'qIPfO$eTaR@MOQP1I4Ockq/RM*iBOgi+%>=1A;)8?Z5i`H8bKuLi+^P`;tQ)uc?D-%T:A)8*,#3Wfk&F?Y\6R@,1%#1qE^]ss=m1eW$Wd5P]GB]m;Xl&(2cP(/3\<`-%p?2)"'?s!b<OFL8<(Z-qi++^@f*Crff6V:CD9<ndZ<C?PK#_WIC;+7rekpTq)j7q:*7F5o&3Q7GZH?5fP)n.T4)#,>@l7dUerl*EOC^;(i3=1UEFT7qX!,0eQG-L;gfS=(=ikM3jDNOg)Tt+0<QrH,k%5'4CK#""2`WJp$tGGB@(@6,6b.t:p/SCm'*pVdrbDb9l"HAsmdF#@\lDHAfRbk8)6EqDK[MNLW`sh[phi'$D,Msqa&($dqMr%bn$<aoRF@eX94b:0,!sgd!_cng]8H<2PB:"a.Q.)ti1"'[B5o91(UEYFQDo6s?YLYRJ>UaIE.IF1+LL,sfpf-RQ9qI1c\5M`Z5fe!Hpf-?b[#7X"O&)Ga?UZBTkg@5@s'DcJ17I^:A,t;'mZ^T=&\bUoGgnh1/d4$UNeEUjrG.4%40l2@Tta2'SBucKS9_WfG$:RHLsuAHX&WgHa[nN%Xt2ABL,a^pX+C='`mS1@2&5R?4)$0;hhT_?FH-2qCC4+CE+AYYDg)Od`N6e7hj@Qn\Lt"s.tP>%M#t?^m^U07mhQc"q7AW]-btAatn!Y2;R\!A8[(s09BYWOe!e&V!>tQXT8.F_b]cR'JPWKEJT:]82p,sq?-:/fasD`6C(52opL%jO*B4))&PHK-kpZ]VUp#L!5'MD30;samSFW\`f%3r$G&N@WsWlTDm.cSdd\UhPcU%+71u?(R(l0^7NeO-%d=thJ[Zr`*Xf`]]Mq.^kEQ+a%4]<bERJhSknm*@:K,B^rrOh1.aNML)_XDp!oJM+KG"9i1^.,%-XBm3E"'qM=3(F9VaSSCj.EP=d>RA+'=jmD"X50>WXeFbG:8C72ZWgm(`kW_dFddjKr]Ld8@V./D%*on6K#Ik"7Ys?"`abSHZ:$K9as0)2heI<46Z=LZEP?i<Vd"=!"ap9i",@qb;]a6<khc^MfLSh/+0qCk`*7L^]G?00K/V&#S\4q2.7WC1puUpggtWo/[(WnXOMkaChdSZi]C3Vnb*-Yfnp)]\[K/F,VL>'QWl@bYl)(.r=\#=9q_G7/?t-#-l2\gQhH=I%?/\`X5VD/JGQAKGSl;mL,U'9cLr^mK3!(q?DA@o`TZZVS,,Oj(3Y`]I)c:Zqn\SY`[k]-TRY.\3*Ej&a&F*TGp5<W/X6s(2^oekD?YDQGt%fuT0q2Fj]+DLcOXf;q!+DmZEi(:</D]@Q'`B@qe32qE9_;:1J_<$XBh4o%G!%"0E`hkO==[,OX#.6T9OW!\p'kE*U!7u1@e$ZFH16VilC=1!$"QMM&lo:=0JR5*Veu>7J180VcMO9N9\s+p8D:Bdju'\l9ihe:fSOQ[[HTa,Zm3/"AR^o2'n$YLLPLH#e)B[GDsY>%"t'b@I-$gqfCdF<.Ft!:cO?d2V=n-iA#S,_q&X_a!suH9Se9q@jB@BIfOmWERO~>endstream
|
||||
endobj
|
||||
53 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 3020
|
||||
>>
|
||||
stream
|
||||
Gb!l"lZ:f='*%C7@_["[DB+N:+-P&dkF@m0]/WeBV<uLk-3I,,`0_ea!4&a+os`jP&!N/)4-$M,CeH%h`F=%rq!B\MJVe:qq<LNN0Dj+DCOnpI56f:c*9b.m2uTL)7on3iE=K,=RLZ].D8W_B%R,ZmB$r4W7nCHGLfu_/UP*)<+_Vds-J7Mil<hA#(bnI3:]cVH0G@-a0CqF5MW#Sl^o&tG(Mj4?$mS'Y8iDMt4OYP3-U4+o`Pa,Vr$dh%:_iKP:q+StSG:(D?6;B/g4pihJRgHkOjlKo6'udT4birKkl1nt)D\"<GQNF!WTZ$H#tn5`aJ`(r^^XdT')3;u<3e36)+7/T^kWM%'W+jh-nGRpLEZ7()]:YQ']*d'/et$p&CY?-!L@qKm%VCa%Dc4OY_6\(2W'\YH47=sT]$`,alJE$1)L4(TGB6@&Ii3[#@"!@[#.`(oh)S49,0O"W3*<iTo$=`[?ns(h/Mj\PTjAJOO)r!C4b?]9ZUp%K9._TgPamhH)=`Kp-Voc0c(F%..&W%[)rN.Pr"=$o[gA1=c:O/]5GOl^(S.=WT-,/%T(lc!H8r-*reU)Jq-.^7qiJ<K]#7DXJi=#@0+Xi/QC#`*#sT[AH_`GV\Vc)X4;fG0s7aJ.9r>>3Z'"B9pj8Rpog@Mol^)@jE$U-k;=1_2#^'>B,jU:o,,_e/9ms.rJ\o1,]]B3kj*9]kF2u9?-J\G%OC=Ob,(9j%">r^74-D0Bs7)@&kY#N6U7d0E,gT;_PPp@9Z(\T#KJ2G#uEV&/rK1=3-tHk94Q=.@qamBc@<V($0"MfhdWM?RKbR3IL(rTGTf!Q=cHP)-57I1AG]0fc)=b*9Y9Vl%#E[7Apj'NWc#7_&i[/VLrT$?9RMr[iDMn$@lZa@+f9rG-i$+"06ZUt[<77pNmPAuj0IaA$q.V4'c21A-O-`NL`Lft2m49,:8b$7aiE[96RLUI'h&C[gM73)OV-=Zd+@IDJr5)mIX.)/o+U>ZGFuY;?CX7ppk!;E'DP6b-pJ6TD@uqI!^GI8gMlLo]]QY+H2Apn95nj1Ou-Q^YN*$KV)=*Pgm1$h(E'\"ibF!u>-lb%S"$2VLAlUP#)UiI!r])miNDc-i/]<reeLhI4HAJ6Y>#W*i\La'p?<Pk#q[-2D5*:E'r/_B`cN9%P7/Y*UmiUsLoF7Ke'WN(jomIKmZ![.iXg/GN#*r!FE-7[h*C.\58Pk[UB(,H"&cb&B66a'O<N1,.QGbP0ps8T`/Tur=FX9AkSQ22a9Bt<Iu6uVM?4OO/dDXedVrc:>`EG\*B[IW3:6F&A&E*rgU4l%4.b,?K@+^2a0@IuNU\I1j1$+^=N#jTBMr$p59`PpcFS7<=Vi;+kJ64mp5hpjd^;.Ad)E`2ki1E8?'9/k5V%[GaIQG_#&ejUP2cJ"5UUOe(`)YPn6)T"LeS;:0b9t+Q<VW?Y%]lQ*+P7q[\i>(\QbhDP/glZ6bho8gc_G/A2U"giD519o8JGL1_m'>K$-D5Wdt3I.ekBo/_brbo=kp]O85_X[]"&D/dn#D(V=<\T55Il?LG]bC"K3Z3fmFT3Nc00-CX%`a3Q'C>dUb!\47'.F-I2LjKNt4ogohGKSs93RX,oe@PG8cm'RWp#0:BFf,e_>2L0Y+346gRmK"b%`VmqPJa)+&ADD[nn)kpj9j3Qm_<0qBfb*XB2n=-nQHg&F6Kf^)k3@A9mC'Rl\'h%A$uQM)%="-sT_i)1^oP*KSc24`?KDW@[F0RiGlrB^Pm4ln)[P](@b87-(E%/+<GgkngG:sq@oqYAa)d.K3rkVT"`Pc5_B]3h2[LO7<$l>"`.pu&"UM"Q%!2\.(^E6NpcRGqJGp`;3+t!U@K<uK5Z:&Uq$V646^"kQ"]5&OSUO%8)?WK].:?9"5Z/1GK?3_e)FfkG3X.%%f"fbmGRoboGf4:MN`Rf5gFPD89KTfiX9_ks)%ZOROeo@Hi+Y-"\=ST:pJ1:%m.)E/"%lo"=_>,A>:?/Giuugl-D?JV'h%DO%h[6aJ_[+/R\d3t1[o\)hpoMkaJs:g?:=udB/=7\c.cHTMojS@>/c\\`ETt=<X#"3hlNZ?ejJnpZmpds<'1b&jMGelfXjQ,2*'m8n)ZjAANPXs12n[ET(O?dFUqDc^bR?q80D1MCZ7F3l.QfMWLiu^)N(?LK.OsYbe%&S:ZoQ4/sM7]=[qro"sK$^LjeIoG\W*bOSO)^a:hR4Ng)`4gY)<_a>[2Ep[-iKg8,>;h]Lk"-XeO5+][RWF2(Y^H1e>F<k:BN,fLFgCfg+^W@=<0J5`#eLhKI0)KMDU3l^W<T;`;fl<b"rX`hlm,d9=5a=lLcji61gWbDqDr]Q=@55i@s.jhXZk.=MPg]+V%4uIP*aK''GWX:L)No>:jV_\!9/B9HN%cuqhMc?=_9Btsr/jT8bcC!Ck'-:eK9J_YcdLWsXq8_fO(-ssnlgAb%OI12GWrnd(]9mXlSMV-0+Zh]GjN!_f=']5(BZ?05RH@t2=J,H4A*i#Vl^Zos7D7r(`&s@=_2J4."EGSPqL"CU5uBH=0(M7\W>;gCa;;F4>ZsMIA@tY)/+-*:qIjKbQ^*QiE5om(QfNPF*fRMJI3j4)j7(0aJ8Du8Y55knmp88_G7J@/a"0p75%<+T;1GSZn5R6#\Heau[6oHp-X=atS!iK7+:b,k"EMM0<3&3nbbTjP\U]*cruEcO_qqHj?XDGnX/;4"non'tb=h_JFNY'f46YP1[(f\IqS:O.IG,L:^,JUO?dZ&aT\c`D?_8m#lYVjs.8921Ts%6M.<c:@/,S#+!l[?-6ap:4jrnm4r<i>ml.XgL3[TgL6K\;6+IGLAYE)&Es0CF-gYOujg@ac=H[D]i0%&-eVVQ,\Q1fXpqn3Z1;*hAfU%ITQOqIFALKBeB\!FpiIc]\\-W'K]=K&<IG8u6W3lJ%OL`OZX4NH8u%'d/*:pYW:):7P/6m/0&MZliGNXCc3@p(Ao2F!Nl0\J'uZC)A2);hi+L=O;7NOX^Y=m]aTD)flFDf$IRqB'I*[LN~>endstream
|
||||
endobj
|
||||
54 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 3911
|
||||
>>
|
||||
stream
|
||||
Gb!l"=``=W&q9SYkXT1sd6&\39O?:OS8@3'@r##B/QYY4,U@G)&IJQld6?o8hZe=]P^(>Gm;-WbAipd#DKN54rUjS$FSmlCJ%[/DknK08)do$eSV&ZF7POcL(Xo-$7n1(21tHJUXH-cK(n,?Q,Q&T8itm]FQD9FJ\cfp5h`cL-Jh''QX*#HB"Uo4lJ90uZ54sI7i]Xr+l(9[.:%J-$J%#8k#It[]YjEVr9m99HCk63/[Q\[rRuC'cA0C978:JgNi'CYn1e\jCL'9;cq/8f&ra^@PL5J-_+uk21hs%UTUQmMSVa"I6ge)d,*^J=t>Nt->J%E.nM6=-/'.1k\bWR2V;#>G,-8V,>>EC<$-`>lp!eW;;>d9)SU=NA(Z*!7(h*$Gf2&[W@:cJ[)f!._\R97&$)'^uB".7lJE0kP6bOXrKX3@t4YVSm,`GA,b4^IZ&Q"AJ>M7Ue\*[R&[GBd,bT(=#=h12RJmU!<%YeN`X?qH-D`W>2:]pPm7%'O)cH[]/E%33&7Ru$n4&,L@d@R9$tj^ei1;;P.?)O>UgU<<HjINYoq7.B3ML9J(:VhkM:K2h'DWs3.hPJ2uf+l9==qq4?1)3][eRdka=;Z"Z6@62(cSt93ig?<&);7NML'_d-uS'h(JBYerCQdp,oItW7]V2hTcF]YCdgn(^trc2>-3$@C^R>!Q_&-5$lg*\&'`KEXQq)]uYUYf@.A=*9=.Q^HXLtPr7d/k35,mcp&-YZ*f0j-DS"k2_ZmP6,1Pd+MF)<pPr>SK^NU:^EAS.g?9A*=l$/.DVo:U:"&#n1,/Bt`l+Vi6#*Sr?r<SMT^84a4,p(add6Wm!cMec?<'np%:^0RROp_\V,$(@a;*GmNWQ)C#P0V9-pke)1\)Ymq&D2t^BADIFSb$6h`(h@6(?%#F)OFX0!c>$m"#5LGH[,Qnu?P5%kijmW!5T1>>[:.A^qG(8CS*ar[RPik0P/LZsH+l'(D]ss`%51U)\$X7?Oadf??KTFe!-:W\(I**3Y*@`Vu;mq3*:LO9rZ3<pD$4HWn/RU>4=MUhN!M9],peQ?HX)qYu>qj9!@O>"$r*_+TV;'*rQ0\65[f6/a%HJtC4a+3S`)*,#HGdhOb]Lbjm7q_7?2dU%\5U-$-Xd;Ep$c:e9SJ,;DWDBm4.1d:Jd>,g<=i$sfQ+N_!jOb_5'hjKXr,b5oal>"*UhpecZ9?W,S!kc<sX&%_48J@n7#SgS_/g8Np=RM;BdgR/$`Xs7hP`rStLOJQ!iYg3OVoobRRVSUKAfrc&Pd*Zg(3F.Y3$Kh,.`tTg[M4/0qUL24MqHT$84f;rK08@I<A;/Q8uuq]Na7P].C(_ut>ZN77"KK\Ok#Vl-/=)57j*L5XBMg8/j0Z*7Y90_ij-6]X\L$,;V5`T%/@oL2<\5\Nh_m+k#sWR##F)D4hS?G1ofQluYJW,?a1K4l=hd=9N'WL_o(o:KPO$\#NW5A:OoQ-u9;+]Rko$mI?0bNe&&/KgjZ9<X,":3rpaE0'JtI@Xb21!2u"r4gpRUN>LD=*=j@;tbm4RG1dF?cXF!*6qYk%tJ[XN#NH)C*TAZibdPK5\nH8&0E)#@Tshg`AOO`S15OrEhTrgU">iU*t,1,3UjMn'+ArjWtsa<<R@AW(VJSYJ1%+dMK2<8OcOE&[Xt5#k4?@rnC@RO@&\_cE0'A9i_&^IGFk786#_R']09-S6MG,3:'?.0RU]qW'=nH/%Hg+NE>TS@$XA0M'M7IEVNF@f1H_H,Sc1s0O5)ffe_?HE)=s,+qQUOC#FI4m\;87!h/))G.jO9$n*rH6U#ITp$!jk#*UFS$#9J4[P6_!s3'iq;^^N3&H5/S>[95uLAlhrK[\2me+c.pGJ@g?392O9s6K(Lmg18BU<.`l"/_md,E80*`D6q0ub]oMPS%MY@.=]Fa?&O8(Y,UZsjjmo!Oi2#!L'']7"n1&P/Wm7*#73H()r)8IEi1Vn@lS>0r#@#OG2W]Y..OLp60VA%kh/5S?K9n\T@MZZ?Yd`Qm:Z,(^h`$?"=>T=&7oc\B+f*E0_cH1foRf4%4u#t^s_r'oJ#]d`5?C",O$,QH+r6X;bS88qUAb_HVUgYT'5O4Ym5qCOcQ,YLpF_i:#fV)=V5T9UQfR>4"e?AE'VNFAJ=0t9,F'G6TXc0'$:JKrBPd;WJ'[\\2NSioY:49CA7Uag-N,R9F9:^7FT[3Q>P3b78qfC4\9iI2cu*(Dtm0E=%tJlS+=,R2(':f'k%WT-)+h]Z"+p(1>Dr;((^6@f":A"_C0cf7.8r91bY(`pZoEWUsY"=j=T3r(Z!nns2N$sZH7sl2.@'fS[V\LlgAVVg*42?>D,dpk3mFC9LMUU3*;>gP<)IB`?Ge+_dqSomX:H)op7DMS)_oSYpk+VmDJQnVQ=9:nm8*;3Pe+>XgkJ)"IS)G=S&g]S(eF4N4kfWGOf$C6@8*eQW)gP^a3Akd<M$9X-3b894F4"bL&ZQnA\1h[a8oYk/FJ[HOP;Ohjgc8bY5"/T!Z@IiLS]280d!5pJp7E^Hcuh5=0L6-!dYW:mNi`Co\__1``B&<T]R&]lohpk&,6/"WeBqd&D_0o6.Sd;K@:ZM3UKEem]s,E8d:BM8+G/b/GJqf!7JeHHY__Bj"s+/R0d>BqGtN)7!G>^Z#*I`Vu@>Y^sUd$MQ.';5luukRX=iqtt]\,&o7bVrpeYP_Cm(-d0Q,[+q_NGXu3(d2OZFWgf6D311T83B'`m?JO"hg+4c@"gPDWYV!mdl5k[?gc%UX_J)p2.;:P=TF-Ui6W;+6a*$hg/[5%&B7Xho,M-]F@KS"0+,;Wr&#r$W(iVAL:Pihr+CV4CN!;4_&TAn7,='"rY*?`Z:76?&A>/8tYaLUG\XcLMo]rE507/[:P^R3%fnYdU+!8gQGMWeu<@N*CWPBn)>:X*,oGsH/8IHs2f>BE9D892cAs<qQLb3V/$[pMnkMoEgq.b>!ElW4&B<P`_Or--Ea7`t7"@[As6_KNQQ)\pt]HgR+gR=TKY#RGT>AhkQY?Tg^CWfH+F.VPQeX@EZ<L>r"FGD]J2efoI/&jYE`V(Z2?.:KEl^hVYmiA2V\):rYlV5L9[O\RHf=_;4ELZ>&4]&r'E(bn,h`Ps5j5QXlF)70t:%C;nb?N#<f_#'l8O8h?(qb@I,BmGjI^T?Gm*4tOGtr:<delCb"q:N#fDea^RfYiMci`Ot-Mm?!2Up4WPU@cZ\nSW!R>@\1)C@K5,_uJS5_21J1#GI=D+qq7cF(4^o;BUf`UiSEC!as[3oY4U)4qj$hnZ4BiC5U32k"0bi>S.rgI<b'2]P=,>=l8,]`G5cgX*9el"KQ`N\>>`Y<CD=ndn3I(pTC*pGuO(,;VUs>u6KbK4<-7SA5ZFC,I21o[-ec6pA@W/,fio,[l_t;p^G9nFl_<X<$,Um(sWE^l;Q$r@EL2Vm=n,!cG#NPPuppPLH?8ZdTZ4?>OrrV*B)r[1M"4N,G(sA1IWALW&7.L]r1HJ?i9U/t4\baF*c+e^0<@30_ngV_Wc&i.8dN:1^X8+[L.9GOV.mJ-clY#$(7eAoG,qKeGK9P>6gZT&-K#q>oZ-bV'jPOX$:ZcPMf0,M?9Q:.u:,)VBF=*1rHtAt-;AZ^J=OQt;^WTs9+"*uM`,J7Fkpe+g%=DBndT=b?N$VKAu(Lb'QW^]B]6W%8mkRK<e1AdQd/CZ0$"<PXUnU>SmCbS6pbI`5:3(C$_X+&'c+e<tnS=g+2M9j%(D=Un]._Tg2fqJ.[.j[)FaO>l]29^(84bZ*Q_:9"Qibn^MbmKsV>n8D7W0co%Y4b'SdX&B`D`P)2@SABM`He9nb-XF>'*6\(V_m'7\Vc;\uXF0!A21^s_XhN8#BbT6i3#M_F-6pEqfWb7")h&LJ60`1^.2^"URV7G.[*5d52@N)aUVRe\Lg>=@E:b5`/uS+~>endstream
|
||||
endobj
|
||||
55 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 3387
|
||||
>>
|
||||
stream
|
||||
GatU6>BAO[%Xua-^tZGuM'D4slZ?KSm<0lAUlN'n&"2rA&oI5.&lhePlLV6pI6l[?]@P5t:7E`/5S*o[HiQT#a$1jHf*_V^B5i,lJ/BtE!3n?gAe/i>48X"eMOBd43>5W+@-fqCTj)#Sn*JfV$'&"[pi2%O8[TBY0FP]NPk<.G,C<a-UH0Yn(qCPY=[5n<,.Z\fU]P-jAC@4R]=iqlG[3r`0e"8VBu3%/!G6htljorX[g$\C\#)m1e:Cf#;G.m8P3lW.Co-*([UKdqi\0GjYbDaY8/B[-V@9&L9U?'4rq6=6pN2?krImd/oq)Lr7YYe?\mssq3.F<@drP0;J";qT[EsF!TE22D)5Q^&A1DP=\\F8;abGAm(CQP5."uo:TKn5m76YsJrT#a4ZdB]:7+4k>j%lF^$r*?2VJUos\rJtGJ2XhFf-8@"&\_k<d>DU"@Q8=X-;#++r]lV2:GKhoC/`K]q%PCoB>NQQi[(+=jJ>Id(5`<T1J\k&`1[L'e)j:JG@_r5c2@?%[k)5M%O#>!K'#'Zn?[.5UL:tr2"^_q)F*BC%I#cgQ>]r:c-fn`"Sku^@MIcU3tP_bT[#p2(JM0UR\[[[QY;LXR3l]&?+3q<El[YaSe?UaY[VASZY)CY0-^uDe?,&Jh**Tq<eMScQFhG=ILai-a)aA0o'IFd.'q"LSh&%S&>Z>D]4*Tf=5A<F^114LT5L-,cr?GEP^-PDlm:"<me5-!($^&>1>5$.00]ni'1Udb'Pbg4"E5eElk)#);2W]CKZ99i7PpjU2JpVfQ*5r2qE[NmMj,OH&`Nc0^OMeg'4Yk3":foV5G)@RH7r,Ugu0VE"n8#kkk3j!Hb\-Uo4g(AMa9n;%H(/FJ4Nrb^o)R1+Buq(5RFM5.Y3?5k'g7HeO)31>#oN92-`9Y_r$o'\heLef5,%ANoOl?H&R7j.^On1L9FMSNe2XRkQ8X%</bAGJNk@RZ"D)n1<1ghc/'>OMW.H6@RbS\;e-2DSKIoGn5Z-F+5iE\mu0\cckHPJR.5X,H,=s2S%^kBK-ndXl1bD1W[8-b>A+2-,')cj,311[k1$Gq7p$F&>I9#Q&BjGd'#\le?kO;oh3)o$K&j2kb#*V]7t'KfG,JU#7baLqkn,WtK@p5/5r\A++S`4!WKVT31$kT!>F\oh8ersc6$XU3`@qi_7Dt=nnRr5%J_\qV8Y:Ep<dJmFkEII;E_Y]6lP@4TMYp6R+pY?EQjYV*"PZ^k'sJqm&U'I%SiVa3,*CD#V-pOd'EWh71SYk*l!>IU+o[D@[)*fQ=ULQ7V">+U;f"`N('2j7*bH>)nhG26o(:'iY*0=P0_l"Xg4>t%Pqf8D':Nrm6k@3sQ/$;Oa5H5M20s_A4lM5*kVaXo&9*:k=Q*V:S])&!4BrO-0NF_cbN&n/RC(CqUTm`.#37.@*NOlYU09:Hl't7WW!sZf'@DCbd:*#%R'D/bPmN$0=Jr/uK7Mq!'oaCQZl$sMF0bP)V"#DBe9aP/@A<l=o4:1Rh$1.?Ta&'S2;Q-<FnUh-K@TKlJ-KGtHs@S,+oprlqU,")(lJZJ,_7W,@J3qUM".77>DQ0M4d.;r^Vr%CC9+3]6lf<1n/subRo=IZ\>['eUF&CGB<i'84j%AWCUkaT)=OKt4,KknWoNYGYi51rAuB*0TICFVK(P0)Z;4jHC-ne8_!%ZHGX-'(HRX@P(ka_Knj=h/)lpZ.C;FYdU@;j<ojYa#NqV]<2m$fQkeYF8)"NK<lgPS;h"21Nf(X.pMH)(<@]]Cp5?l_iP<</]2K=P9L@mPs<,OM6:lF+o5ZgOs7D^a!3NA;e;DU]+=!o"mpV'nl:U'N_4CNqS?_GLP6^[TP(%u2&FQ]eX[&3\<'fLpred;iYfW2C49fub:e-.:i=WbN$C5D3k53fBk64-j;_T-\1]Vk@G[o-_(L((:EJ588_p/Pl[TZTtdQ:MdW8>_f-=2P/2Z^XIi'XLRa.>TI"U5Pk@MKFhi$0DN'7b#WXQ6'hX]%uACIT#F-g9h;#"QE^`!JU45B,k<4VSOpn)j1H%2McjWBX$$%3#0[%$L,Rt1olS,TC-TcH`K69M6"%7'!g8$$bnTg?c[I#=6ig.??6Y1=Mk(R;2PTQ[7Skc?:NH=1[Kj=j<G/i4FK^h8Guj!eQ\4)!55\0blq0cm=^1&_gqWO(6hjJe1f_#D].d4<]gK/[6[J]R)D*?RgJ"jiCOEl)7"`[6q)>7;9%EN\!2(eO2o!O'@@R`K&A0.,cd[o0JR^*_WM<08:%M[$3A%E`$,c9/\L[sV.+eZ`Z1lPGDXtZjJSQC[WDA^S)&i03LTMA6k_1nMWG4a*F`2;-W(2.[HdM']1>m&3BW*]B&6Kn(=shW]\(VZDqA1h1Hdjs't@fK-3_]E:+Vh8H.QgH*[?W6<E=n^<Dhjr>cF_IY:so54E'NP=,M^,U6rnG;mn'b6)Q4Ke>$_fg8=!lG&u-P1e9K4.)HnA*>rajZu^H/`mFD4JmAg)dXC^SoV8OTNqS6$3X)9>_rWq&Vd.t96*Ans\MBZgjSj=`7j!-=F'HRTT0e#%Fcm"?@CUfB`uWqoO>6?e5fTr2eAC@2Y1i(.Fh_D-O$KE0?5No@R55*0$u]HA"_mae<5"-5S[Ke4'./@$'>pKK]e(s`nIf9jJ9l$c2)Aj8(PSjJ!kA=&H+*QpJbH3-G?QZ[O'WiU]q8X(Ep@VspNMtUG?"]-cWXaZp;C)*[b\";K1k#UC5K)T`0ca6_<lR9C\VrMH%Z<]AatI>_%Qm]`R&F:G7;4:WZO\cRB)@,`.(4]U_3X=n,A'FqoHH=W6ZYIAoiek5K.lK[=L["0r.t%1?u""n[UM*NPR3Nra0j@W7D3W?GAj-"j>kk1$\=6PUIhnh2YMd[!,N1l*1IWQ]d,j7BGa?=4<XgI@8pIbe?mAH<F\Ol4<NpMX@K)l4!0uI?Dk)X8As$=7_EA$T)68kLlErL<Fkd2^7YPhn`S@RKTYH;`:KiZM8R6Cm;DkfL+D)omjIY)=R;_HJU(=-8r5:C4[.&ghWSLH7SDiCW3Du<[N0aPt<jklnqV0>m&(&]:cTl?-?f_8Rq1W1r`i\aDao@`K6,GC4^T3l&M6[0uUIWgG,2<*O?_-=tQ*[goP1rA=2.5Wrum6]6-/l"LFS<s6bYK]t2;jT/CJS^K85Y=!-br$"@hXg1l?Vh:7=80ecjMm[;P-7L/,#UFk1%o*gtc'&eQ4>Sp3H,7X(pJ&.)hYqjAJ53k7.cXUsp0"lYpnbc]@&DioQNT/ns]t\*?WpA=mGj^WRNW%R3FKFUF#KN:#VU'!n1Nu@_=\\]g]k?V*DU7[]RI[$gD?_<&cj\O/J4:J^#[Ru\rnIZaen[RA/#'60/__7\A:h=!+Ee>PagtS!#;0FL$K1:NB7$/:~>endstream
|
||||
endobj
|
||||
xref
|
||||
0 56
|
||||
0000000000 65535 f
|
||||
0000000061 00000 n
|
||||
0000000146 00000 n
|
||||
0000000253 00000 n
|
||||
0000000365 00000 n
|
||||
0000000512 00000 n
|
||||
0000000659 00000 n
|
||||
0000000806 00000 n
|
||||
0000000953 00000 n
|
||||
0000001100 00000 n
|
||||
0000001247 00000 n
|
||||
0000001395 00000 n
|
||||
0000001544 00000 n
|
||||
0000001693 00000 n
|
||||
0000001841 00000 n
|
||||
0000001989 00000 n
|
||||
0000002137 00000 n
|
||||
0000002285 00000 n
|
||||
0000002433 00000 n
|
||||
0000002581 00000 n
|
||||
0000002730 00000 n
|
||||
0000002846 00000 n
|
||||
0000002952 00000 n
|
||||
0000003030 00000 n
|
||||
0000003114 00000 n
|
||||
0000003320 00000 n
|
||||
0000003647 00000 n
|
||||
0000003853 00000 n
|
||||
0000004059 00000 n
|
||||
0000004265 00000 n
|
||||
0000004471 00000 n
|
||||
0000004558 00000 n
|
||||
0000004891 00000 n
|
||||
0000004966 00000 n
|
||||
0000005068 00000 n
|
||||
0000005183 00000 n
|
||||
0000005310 00000 n
|
||||
0000005430 00000 n
|
||||
0000005559 00000 n
|
||||
0000005710 00000 n
|
||||
0000005809 00000 n
|
||||
0000005924 00000 n
|
||||
0000006043 00000 n
|
||||
0000006155 00000 n
|
||||
0000006279 00000 n
|
||||
0000006423 00000 n
|
||||
0000006543 00000 n
|
||||
0000006673 00000 n
|
||||
0000006789 00000 n
|
||||
0000006884 00000 n
|
||||
0000006980 00000 n
|
||||
0000008056 00000 n
|
||||
0000008996 00000 n
|
||||
0000013043 00000 n
|
||||
0000016155 00000 n
|
||||
0000020158 00000 n
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<e35c791b1039d8a464ca82208c6e5ad5><e35c791b1039d8a464ca82208c6e5ad5>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 31 0 R
|
||||
/Root 30 0 R
|
||||
/Size 56
|
||||
>>
|
||||
startxref
|
||||
23637
|
||||
%%EOF
|
||||
Reference in New Issue
Block a user