ืขื‘ื•ื“ื” ืงืœื” ืขื ื”ืชืจืื•ืช ืžื•ืจื›ื‘ื•ืช. ืื• ื”ื”ื™ืกื˜ื•ืจื™ื” ืฉืœ ื‘ืืœืจื˜ืจ

ืขื‘ื•ื“ื” ืงืœื” ืขื ื”ืชืจืื•ืช ืžื•ืจื›ื‘ื•ืช. ืื• ื”ื”ื™ืกื˜ื•ืจื™ื” ืฉืœ ื‘ืืœืจื˜ืจ

ื›ื•ืœื ืื•ื”ื‘ื™ื ื”ืชืจืื•ืช.

ื›ืžื•ื‘ืŸ ืฉื”ืจื‘ื” ื™ื•ืชืจ ื˜ื•ื‘ ืœืงื‘ืœ ื”ื•ื“ืขื” ื›ืฉืžืฉื”ื• ืงืจื” (ืื• ืชื•ืงืŸ) ืžืืฉืจ ืœืฉื‘ืช ื•ืœื”ืกืชื›ืœ ืขืœ ื’ืจืคื™ื ื•ืœื—ืคืฉ ื—ืจื™ื’ื•ืช.

ื•ื›ืœื™ื ืจื‘ื™ื ื ื•ืฆืจื• ืœื›ืš. Alertmanager ืžื”ืžืขืจื›ืช ื”ืืงื•ืœื•ื’ื™ืช ืฉืœ Prometheus ื•-vmalert ืžืงื‘ื•ืฆืช ื”ืžื•ืฆืจื™ื VictoriaMetrics. ื”ืชืจืื•ืช ื•ื”ืชืจืื•ืช Zabbix ื‘ื’ืจืคืื ื”. ืกืงืจื™ืคื˜ื™ื ืฉื ื›ืชื‘ื• ื‘ืขืฆืžื ื‘-bash ื•ื‘ื‘ื•ื˜ื™ื ืฉืœ Telegram ืฉืžืจื™ืžื™ื ืžืขืช ืœืขืช ื›ืชื•ื‘ืช URL ื›ืœืฉื”ื™ ื•ืื•ืžืจื™ื ืœืš ืื ืžืฉื”ื• ืœื ื‘ืกื“ืจ. ื”ืจื‘ื” ืžื”ื›ืœ.

ื’ื ืื ื—ื ื•, ื‘ื—ื‘ืจื” ืฉืœื ื•, ื”ืฉืชืžืฉื ื• ื‘ืคืชืจื•ื ื•ืช ืฉื•ื ื™ื ืขื“ ืฉื ืชืงืœื ื• ื‘ืžื•ืจื›ื‘ื•ืช, ืื• ืœื™ืชืจ ื“ื™ื•ืง, ื‘ื—ื•ืกืจ ื”ืืคืฉืจื•ืช ืœื™ืฆื•ืจ ื”ืชืจืื•ืช ืžื•ืจื›ื‘ื•ืช ื•ืžื•ืจื›ื‘ื•ืช. ืžื” ืฉืจืฆื™ื ื• ื•ืžื” ืฉืขืฉื™ื ื• ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ ื–ื” ืžืชื—ืช ืœื’ื–ืจื”. TLDR: ื›ืš ื”ื•ืคื™ืข ืคืจื•ื™ืงื˜ ื”ืงื•ื“ ื”ืคืชื•ื— Balerter

ื‘ืžืฉืš ื“ื™ ื”ืจื‘ื” ื–ืžืŸ ื—ื™ื™ื ื• ื˜ื•ื‘ ืขื ื”ืชืจืื•ืช ืฉื”ื•ื’ื“ืจื• ื‘ื’ืจืคืื ื”. ื›ืŸ, ื–ื• ืœื ื”ื“ืจืš ื”ื˜ื•ื‘ื” ื‘ื™ื•ืชืจ. ืชืžื™ื“ ืžื•ืžืœืฅ ืœื”ืฉืชืžืฉ ื‘ื›ืžื” ืคืชืจื•ื ื•ืช ืžื™ื•ื—ื“ื™ื, ื›ื’ื•ืŸ Alertmanager. ื•ื’ื ื”ืกืชื›ืœื ื• ืœืขื‘ืจ ืชื ื•ืขื” ื™ื•ืชืจ ืžืคืขื ืื—ืช. ื•ืื–, ืœืื˜ ืœืื˜, ืจืฆื™ื ื• ื™ื•ืชืจ.

ื ื’ื™ื“ ืžืชื™ ืชืจืฉื™ื ืžืกื•ื™ื ื™ืจื“/ืขืœื” ื‘-XX% ื•ื”ื™ื” ืฉื N ื“ืงื•ืช ื‘ื”ืฉื•ื•ืื” ืœืชืงื•ืคื” ื”ืงื•ื“ืžืช ืฉืœ M ืฉืขื•ืช? ื ืจืื” ืฉืืชื” ื™ื›ื•ืœ ืœื ืกื•ืช ืœื™ื™ืฉื ืืช ื–ื” ืขื Grafana ืื• Alertmanager, ืื‘ืœ ื–ื” ืœื ืžืžืฉ ืงืœ. (ืื• ืฉืื•ืœื™ ื–ื” ืœื ืืคืฉืจื™, ืื ื™ ืœื ืื’ื™ื“ ืขื›ืฉื™ื•)

ื”ื“ื‘ืจื™ื ืžืกืชื‘ื›ื™ื ืขื•ื“ ื™ื•ืชืจ ื›ืืฉืจ ื”ื—ืœื˜ืช ื”ื”ืชืจืื” ื—ื™ื™ื‘ืช ืœื”ื™ืขืฉื•ืช ืขืœ ืกืžืš ื ืชื•ื ื™ื ืžืžืงื•ืจื•ืช ืฉื•ื ื™ื. ื“ื•ื’ืžื” ื—ื™ื”:

ืื ื—ื ื• ื‘ื•ื“ืงื™ื ืืช ื”ื ืชื•ื ื™ื ืžืฉื ื™ ืžืกื“ื™ ื ืชื•ื ื™ื ืฉืœ Clickhouse, ื•ืื– ืžืฉื•ื•ื™ื ืื•ืชื ืœื›ืžื” ื ืชื•ื ื™ื ืž-Postgres ื•ืžื—ืœื™ื˜ื™ื ืขืœ ื”ืชืจืื”. ืกื™ืžืŸ ืื• ื‘ื˜ืœ

ืฆื‘ืจื ื• ื“ื™ ื”ืจื‘ื” ืจืฆื•ื ื•ืช ื“ื•ืžื™ื ื›ื“ื™ ืฉื ื—ืฉื•ื‘ ืขืœ ื”ื”ื—ืœื˜ื” ืฉืœื ื•. ื•ืื– ื ื™ืกื™ื ื• ืœื”ืจื›ื™ื‘ ืืช ื”ืจืฉื™ืžื” ื”ืจืืฉื•ื ื” ืฉืœ ื“ืจื™ืฉื•ืช/ื™ื›ื•ืœื•ืช ืฉืœ ื”ืฉื™ืจื•ืช ื”ื–ื”, ืฉืขื“ื™ื™ืŸ ืœื ื ื•ืฆืจื”.

  • ืœื’ืฉืช ืœืžืงื•ืจื•ืช ื ืชื•ื ื™ื ืฉื•ื ื™ื. ืœื“ื•ื’ืžื”, Prometheus, Clickhouse, Postgres

  • ืœืฉืœื•ื— ื”ืชืจืื•ืช ืœืขืจื•ืฆื™ื ืฉื•ื ื™ื - ื˜ืœื’ืจื, slack ื•ื›ื•'.

  • ื‘ืชื”ืœื™ืš ื”ื—ืฉื™ื‘ื” ื”ืชื‘ืจืจ ืฉืื ื™ ืœื ืจื•ืฆื” ืชื™ืื•ืจ ื”ืฆื”ืจืชื™, ืืœื ื™ื›ื•ืœืช ืœื›ืชื•ื‘ ืชืกืจื™ื˜ื™ื

  • ื”ืคืขืœืช ืกืงืจื™ืคื˜ื™ื ืœืคื™ ืœื•ื— ื–ืžื ื™ื

  • ืขื“ื›ื•ืŸ ืงืœ ืฉืœ ืกืงืจื™ืคื˜ื™ื ืžื‘ืœื™ ืœื”ืคืขื™ืœ ืžื—ื“ืฉ ืืช ื”ืฉื™ืจื•ืช

  • ื”ื™ื›ื•ืœืช ืœื”ืจื—ื™ื‘ ืื™ื›ืฉื”ื• ืืช ื”ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ืžื‘ืœื™ ืœื‘ื ื•ืช ืžื—ื“ืฉ ืืช ื”ืฉื™ืจื•ืช ืžืงื•ื“ื™ ืžืงื•ืจ

ืจืฉื™ืžื” ื–ื• ื”ื™ื ืžืฉื•ืขืจืช ื•ืกื‘ื™ืจ ืœื”ื ื™ื— ืฉืื™ื ื” ืžื“ื•ื™ืงืช ื‘ืžื™ื•ื—ื“. ื—ืœืง ืžื”ื ืงื•ื“ื•ืช ื”ืฉืชื ื•, ื—ืœืง ืžืชื•. ื”ื›ืœ ื›ืจื’ื™ืœ.

ืœืžืขืฉื”, ื›ืš ื”ืชื—ื™ืœ ื”ืกื™ืคื•ืจ ืฉืœ ื‘ืœื˜ืจ.

ืขื‘ื•ื“ื” ืงืœื” ืขื ื”ืชืจืื•ืช ืžื•ืจื›ื‘ื•ืช. ืื• ื”ื”ื™ืกื˜ื•ืจื™ื” ืฉืœ ื‘ืืœืจื˜ืจ

ืื ืกื” ืœืชืืจ ื‘ืงืฆืจื” ืžื” ืงืจื” ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ ื•ืื™ืš ื–ื” ืขื•ื‘ื“. (ื›ืŸ, ื›ืžื•ื‘ืŸ, ื–ื” ืœื ื”ืกื•ืฃ. ื™ืฉ ื”ืจื‘ื” ืชื•ื›ื ื™ื•ืช ืœืคื™ืชื•ื— ืžื•ืฆืจ. ืืขืฆื•ืจ ืจืง ื”ื™ื•ื)

ืื™ืš ื–ื” ืขื•ื‘ื“?

ืืชื” ื›ื•ืชื‘ ืชืกืจื™ื˜ ื‘-Lua ืฉื‘ื• ืืชื” ืฉื•ืœื— ื‘ืงืฉื•ืช (ืœืคืจื•ืžืชืื•ืก, ืงืœื™ืงื”ืื•ืก ื•ื›ื•'). ืืชื” ืžืงื‘ืœ ืชืฉื•ื‘ื•ืช ื•ืื™ื›ืฉื”ื• ืžืขื‘ื“ ื•ืžืฉื•ื•ื” ืื•ืชืŸ. ืœืื—ืจ ืžื›ืŸ ื”ืคืขืœ/ื›ื‘ื” ื”ืชืจืื” ื›ืœืฉื”ื™. Balerter ืขืฆืžื” ืชืฉืœื— ื”ื•ื“ืขื” ืœืขืจื•ืฆื™ื ืฉื”ื’ื“ืจืชื (ืžื™ื™ืœ, ืžื‘ืจืง, slack ื•ื›ื•'). ื”ืกืงืจื™ืคื˜ ืžื‘ื•ืฆืข ื‘ืžืจื•ื•ื—ื™ ื–ืžืŸ ืžื•ื’ื“ืจื™ื. ื•... ื‘ืื•ืคืŸ ื›ืœืœื™, ื–ื” ื”ื›ืœ)

ืขื“ื™ืฃ ืœื”ืจืื•ืช ืขื ื“ื•ื’ืžื”:

-- @interval 10s
-- @name script1

local minRequestsRPS = 100

local log = require("log")
local ch1 = require("datasource.clickhouse.ch1")

local res, err = ch1.query("SELECT sum(requests) AS rps FROM some_table WHERE date = now()")
if err ~= nil then
    log.error("clickhouse 'ch1' query error: " .. err)
    return
end

local resultRPS = res[1].rps

if resultRPS < minResultRPS then
    alert.error("rps-min-limit", "Requests RPS are very small: " .. tostring(resultRPS))
else
    alert.success("rps-min-limit", "Requests RPS ok")
end 

ืžื” ืงื•ืจื” ืคื”:

  • ืื ื• ืžืฆื™ื™ื ื™ื ืฉื™ืฉ ืœื”ืคืขื™ืœ ืืช ื”ืกืงืจื™ืคื˜ ื”ื–ื” ื›ืœ 10 ืฉื ื™ื•ืช

  • ืฆื™ื™ืŸ ืืช ืฉื ื”ืกืงืจื™ืคื˜ (ืขื‘ื•ืจ ื”-API, ืœื”ืฆื’ื” ื‘ื™ื•ืžื ื™ื, ืœืฉื™ืžื•ืฉ ื‘ื‘ื“ื™ืงื•ืช)

  • ื—ื‘ืจ ืืช ื”ืžื•ื“ื•ืœ ืœื”ื•ืฆืืช ื™ื•ืžื ื™ื

  • ื—ื‘ืจ ืžื•ื“ื•ืœ ื›ื“ื™ ืœื’ืฉืช ืืœ ื‘ื™ืช ื”ืงืœื™ืง ืขื ื”ืฉื ch1 (ื”ื—ื™ื‘ื•ืจ ืขืฆืžื• ืžื•ื’ื“ืจ ื‘ืชืฆื•ืจื”)

  • ืฉืœื— ื‘ืงืฉื” ืœืงืœื™ืงื”ืื•ืก

  • ื‘ืžืงืจื” ืฉืœ ืฉื’ื™ืื”, ืื ื• ืžืฆื™ื’ื™ื ื”ื•ื“ืขื” ื‘ื™ื•ืžืŸ ื•ื™ื•ืฆืื™ื

  • ื”ืฉื•ื•ื” ืืช ืชื•ืฆืืช ื”ืฉืื™ืœืชื” ืขื ืงื‘ื•ืข (ื‘ื“ื•ื’ืžื” ื—ื™ื”, ื ื•ื›ืœ ืœืงื‘ืœ ืขืจืš ื–ื”, ืœืžืฉืœ, ืžืžืกื“ ื”ื ืชื•ื ื™ื ืฉืœ Postgres)

  • ื”ืคืขืœ ืื• ื”ืฉื‘ืช ื”ืชืจืื” ืขื ืžื–ื”ื” rps-min-limit

  • ืชืงื‘ืœ ื”ืชืจืื” ืื โ€‹โ€‹ืกื˜ื˜ื•ืก ื”ื”ืชืจืื” ื”ืฉืชื ื”

ื”ื“ื•ื’ืžื” ื“ื™ ืคืฉื•ื˜ื” ื•ืžื•ื‘ื ืช. ืขื ื–ืืช, ื›ืžื•ื‘ืŸ, ื‘ื—ื™ื™ื ื”ืืžื™ืชื™ื™ื ืชืกืจื™ื˜ื™ื ื™ื›ื•ืœื™ื ืœื”ื™ื•ืช ื“ื™ ืืจื•ื›ื™ื ื•ืžื•ืจื›ื‘ื™ื. ืงืœ ืœื”ืชื‘ืœื‘ืœ ื•ืœืขืฉื•ืช ื˜ืขื•ื™ื•ืช.

ืœื›ืŸ, ื”ื‘ืฉื™ืœ ืจืฆื•ืŸ ื”ื’ื™ื•ื ื™ - ืœื”ื™ื•ืช ืžืกื•ื’ืœ ืœื›ืชื•ื‘ ืžื‘ื—ื ื™ื ืœืชืกืจื™ื˜ื™ื ืฉืœืš. ื•ื‘ื’ืจืกื” v0.4.0 ื–ื” ื”ื•ืคื™ืข.

ื‘ื“ื™ืงืช ืกืงืจื™ืคื˜ื™ื

ื‘ื“ื™ืงื” ืœื“ื•ื’ืžื” ืขื‘ื•ืจ ื”ืกืงืจื™ืคื˜ ืฉืœื ื• ืžื”ื“ื•ื’ืžื” ืœืžืขืœื”:

-- @test script1
-- @name script1-test

test = require('test')

local resp = {
    {
        rps = 10
    }
} 

test.datasource('clickhouse.ch1').on('query', 'SELECT sum(requests) AS rps FROM some_table WHERE date = now()').response(resp)

test.alert().assertCalled('error', 'rps-min-limit', 'Requests RPS are very small: 10')
test.alert().assertNotCalled('success', 'rps-min-limit', 'Requests RPS ok')

ื‘ืฉืœื‘ื™ื ื”ื‘ืื™ื:

  • ืฆื™ื™ื ื• ืืช ืฉื ื”ืชืกืจื™ื˜ ืฉืขื‘ื•ืจื• ื ื›ืชื‘ ื”ืžื‘ื—ืŸ

  • ืฉื ื‘ื“ื™ืงื” (ืขื‘ื•ืจ ื™ื•ืžื ื™ื)

  • ื—ื‘ืจ ืืช ืžื•ื“ื•ืœ ื”ื‘ื“ื™ืงื”

  • ืื ื• ืื•ืžืจื™ื ืื™ื–ื• ืชื•ืฆืื” ื™ืฉ ืœื”ื—ื–ื™ืจ ืขื‘ื•ืจ ื‘ืงืฉื” ืกืคืฆื™ืคื™ืช ืœื‘ื™ืช ื”ืงืœื™ืง ch1

  • ืื ื• ื‘ื•ื“ืงื™ื ืฉื”ื”ืชืจืื” (ืฉื’ื™ืื”) rps-min-limit ืขื ื”ื”ื•ื“ืขื” ืฉืฆื•ื™ื ื” ื ืงืจืื”

  • ื‘ื“ื•ืง ืฉื”ืชืจืืช rps-min-limit ืœื ื”ื•ืฉื‘ืชื” (ื”ืฆืœื—ื”)

ืžื” ืขื•ื“ ื™ื›ื•ืœ ื‘ืืœื˜ืจ ืœืขืฉื•ืช?

ืื ืกื” ืœื’ืขืช ื‘ื›ื™ืฉื•ืจื™ ื”ื‘ืืœืจ ื”ื—ืฉื•ื‘ื™ื ื‘ื™ื•ืชืจ ืœื“ืขืชื™. ืืชื” ื™ื›ื•ืœ ืœืจืื•ืช ื”ื›ืœ ื‘ืคื™ืจื•ื˜ ื‘ืืชืจ ื”ืจืฉืžื™ https://balerter.com

  • ืœืงื‘ืœ ื ืชื•ื ื™ื ืž

    • ื‘ื™ืช ืงืœื™ืง

    • postgres

    • MySQL

    • ืคืจื•ืžืชืื•ืก

    • ืœื•ืงื™

  • ืœืฉืœื•ื— ื”ื•ื“ืขื•ืช ืœืขืจื•ืฆื™ื

    • ืจึธืคื•ึผื™

    • ืžื‘ืจืง

    • syslog

    • ื”ืชืจืื” (ื”ื•ื“ืขื•ืช ืžืžืฉืง ืžืฉืชืžืฉ ื‘ืžื—ืฉื‘ ืฉืœืš)

    • ืืžื™ื™ืœ

    • ืžื—ืœื•ืงืช

  • ื‘ื ื” ื’ืจืคื™ื ืขืœ ืกืžืš ื”ื ืชื•ื ื™ื ืฉืœืš, ื”ืขืœื” ืืช ื”ืชืžื•ื ื” ืœืื—ืกื•ืŸ ืชื•ืื S3 ื•ืฆืจืฃ ืื•ืชื” ืœื”ืชืจืื•ืช (ื“ื•ื’ืžื” ืขื ืชืžื•ื ื•ืช)

  • ืžืืคืฉืจ ืœืš ืœื”ื—ืœื™ืฃ ื ืชื•ื ื™ื ื‘ื™ืŸ ืกืงืจื™ืคื˜ื™ื - ืื—ืกื•ืŸ ืžืคืชื—/ืขืจืš ื’ืœื•ื‘ืœื™

  • ื›ืชื•ื‘ ืกืคืจื™ื•ืช ืžืฉืœืš ื‘-Lua ื•ื”ืฉืชืžืฉ ื‘ื”ืŸ ื‘ืกืงืจื™ืคื˜ื™ื (ื›ื‘ืจื™ืจืช ืžื—ื“ืœ, ืกืคืจื™ื•ืช lua ืžืกื•ืคืงื•ืช ืœืขื‘ื•ื“ื” ืขื json, csv)

  • ืฉืœื— ื‘ืงืฉื•ืช HTTP ืžื”ืกืงืจื™ืคื˜ื™ื ืฉืœืš (ื•ืงื‘ืœ ืชื’ื•ื‘ื•ืช, ื›ืžื•ื‘ืŸ)

  • ืžืกืคืง API (ืขื“ื™ื™ืŸ ืœื ืคื•ื ืงืฆื™ื•ื ืœื™ ื›ืคื™ ืฉื”ื™ื™ื ื• ืจื•ืฆื™ื)

  • ืžื™ื™ืฆื ืžื“ื“ื™ื ื‘ืคื•ืจืžื˜ ืคืจื•ืžืชืื•ืก

ืžื” ืขื•ื“ ื”ื™ื™ืช ืจื•ืฆื” ืœื”ื™ื•ืช ืžืกื•ื’ืœ ืœืขืฉื•ืช?

ื›ื‘ืจ ื‘ืจื•ืจ ืฉืžืฉืชืžืฉื™ื ื•ืื ื—ื ื• ืจื•ืฆื™ื ืืช ื”ื™ื›ื•ืœืช ืœืฉืœื•ื˜ ื‘ื”ืฉืงืช ืกืงืจื™ืคื˜ื™ื ื‘ืืžืฆืขื•ืช ื”ืชื—ื‘ื™ืจ cron. ื–ื” ื™ื™ืขืฉื” ืœืคื ื™ ื’ืจืกื” v1.0.0

ืื ื™ ืจื•ืฆื” ืœืชืžื•ืš ื‘ืžืงื•ืจื•ืช ื ืชื•ื ื™ื ื ื•ืกืคื™ื ื•ื‘ืขืจื•ืฆื™ ืžืกื™ืจืช ื”ื•ื“ืขื•ืช. ืœื“ื•ื’ืžื”, ืžื™ืฉื”ื• ื‘ื”ื—ืœื˜ ื™ืชื’ืขื’ืข ืœ-MongoDB. ื—ื™ืคื•ืฉ ืืœืกื˜ื™ ืขื‘ื•ืจ ื›ืžื”. ืฉืœื— SMS ื•/ืื• ื‘ืฆืข ืฉื™ื—ื•ืช ืœื˜ืœืคื•ืŸ ื”ื ื™ื™ื“ ืฉืœืš. ืื ื—ื ื• ืจื•ืฆื™ื ืœื”ื™ื•ืช ืžืกื•ื’ืœื™ื ืœืงื‘ืœ ืกืงืจื™ืคื˜ื™ื ืœื ืจืง ืžืงื‘ืฆื™ื, ืืœื ื’ื, ืœืžืฉืœ, ืžืžืกื“ ื ืชื•ื ื™ื. ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ, ืื ื—ื ื• ืจื•ืฆื™ื ืืชืจ ื™ื“ื™ื“ื•ืชื™ ื™ื•ืชืจ ืœืžืฉืชืžืฉ ื•ืชื™ืขื•ื“ ื˜ื•ื‘ ื™ื•ืชืจ ืขื‘ื•ืจ ื”ืคืจื•ื™ืงื˜.

ืžื™ืฉื”ื• ืชืžื™ื“ ืžืคืกืคืก ืžืฉื”ื•) ื›ืืŸ ืื ื• ืžืกืชืžื›ื™ื ืขืœ ื‘ืงืฉืช ื”ืงื”ื™ืœื” ืขืœ ืžื ืช ืœืงื‘ื•ืข ืกื“ืจ ืขื“ื™ืคื•ื™ื•ืช ื ื›ื•ืŸ. ื•ืœืขื–ืจืช ื”ืงื”ื™ืœื” ืœืžืžืฉ ื”ื›ืœ

ืœืกื™ื›ื•ื

ืื ื• ืžืฉืชืžืฉื™ื Balerter ื™ืฉ ืœื™ ืืช ื–ื” ื“ื™ ื”ืจื‘ื” ื–ืžืŸ ืขื›ืฉื™ื•. ืขืฉืจื•ืช ืชืกืจื™ื˜ื™ื ืฉื•ืžืจื™ื ืขืœ ืฉืœื•ื•ืช ื”ื ืคืฉ ืฉืœื ื•. ืื ื™ ืžืงื•ื•ื” ืฉื”ืขื‘ื•ื“ื” ื”ื–ื• ืชื”ื™ื” ืฉื™ืžื•ืฉื™ืช ืœืžื™ืฉื”ื• ืื—ืจ.

ื•ื‘ืจื•ืš ื”ื‘ื ืขื ื”ื ื•ืฉื ื•ื™ื—ืกื™ ื”ืฆื™ื‘ื•ืจ ืฉืœืš.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”