рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдХреЗ рд╕рд╛рде рдлреНрд▓рд╛рд╕реНрдХ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕реЗрдЬ рдХреА рдирд┐рдЧрд░рд╛рдиреА

рдХреЛрдб рдХреА рдХреБрдЫ рдкрдВрдХреНрддрд┐рдпрд╛рдБ рдФрд░ рдЖрдкрдХрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдЯреНрд░рд┐рдХреНрд╕ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рд╡рд╛рд╣!

рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдкреНрд░реЛрдореЗрдерд┐рдпрд╕_ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИрдХреБрдкреНрдкреА_рдирд┐рд░реНрдпрд╛рддрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдиреНрдпреВрдирддрдо рдЙрджрд╛рд╣рд░рдг рд╣реА рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ:

from flask import Flask
from prometheus_flask_exporter import PrometheusMetrics

app = Flask(__name__)
metrics = PrometheusMetrics(app)

@app.route('/')
def main():
    return 'OK'

рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдмрд╕ рдЗрддрдирд╛ рд╣реА рдЪрд╛рд╣рд┐рдП! рдЖрд░рдВрднреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдпрд╛рдд рдФрд░ рдПрдХ рдкрдВрдХреНрддрд┐ рдЬреЛрдбрд╝рдХрд░ рдкреНрд░реЛрдореЗрдерд┐рдпрд╕рдореЗрдЯреНрд░рд┐рдХреНрд╕, рдЖрдкрдХреЛ рдореЗрдЯреНрд░рд┐рдХреНрд╕ рдорд┐рд▓реЗрдВрдЧреЗ рдЕрдиреБрд░реЛрдз рдЕрд╡рдзрд┐ ╨╕ рдЕрдиреБрд░реЛрдз рдХрд╛рдЙрдВрдЯрд░, рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ /рдореИрдЯреНрд░рд┐рдХреНрд╕ рдлреНрд▓рд╛рд╕реНрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдпрд╣ рдкрдВрдЬреАрдХреГрдд рд╣реИ, рд╕рд╛рде рд╣реА рдЖрдзрд╛рд░ рд╕реЗ рдЖрдкрдХреЛ рдорд┐рд▓рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореЗрдЯреНрд░рд┐рдХреНрд╕ рднреА рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдХреНрд▓рд╛рдЗрдВрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА.

рддреБрдо рдЦреЛрдЬ рд╕рдХрддреЗ рд╣реЛ рдкреНрд░рдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рдЙрджрд╛рд╣рд░рдг GitHub рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдЬреЛ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдЪрд▓рд╛рддрд╛ рд╣реИ рдкреНрд░реЛрдорд┐рдереЗрдЙрд╕ ╨╕ рдЧреНрд░рд╛рдлрд╛рдирд╛ рдореЗрдЯреНрд░рд┐рдХреНрд╕ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдбреЗрдореЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд╛рде рдЬреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:

рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдХреЗ рд╕рд╛рде рдлреНрд▓рд╛рд╕реНрдХ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕реЗрдЬ рдХреА рдирд┐рдЧрд░рд╛рдиреА

рдЖрдкрдХреЛ рдЗрд╕рдореЗрдВ рд╕рдВрдХреЗрддрдХреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рднреА рдорд┐рд▓реЗрдЧреА README рдЙрджрд╛рд╣рд░рдг рдЬреЛ рдбреИрд╢рдмреЛрд░реНрдб рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдХреНрд╡реЗрд░реАрдЬрд╝ рдЬреЛ рдбреИрд╢рдмреЛрд░реНрдб рдХреЛ рдкреЙрдкреНрдпреБрд▓реЗрдЯ рдХрд░рддреА рд╣реИрдВред

рд╕рдорд╛рдпреЛрдЬрди

рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдХрдИ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ, рджреЗрдЦреЗрдВ README рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡рд┐рд╡рд░рдг рдХреЗ рд╕рд╛рде рдЙрдирдХреЗ рдЙрджрд╛рд╣рд░рдг рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд░реЗрдВред

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

  • @metrics.counter(..)

  • @metrics.gauge(..)

  • @metrics.summary(..)

  • @metrics.histogram(..)

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

from flask import Flask, request
from prometheus_flask_exporter import PrometheusMetrics

app = Flask(__name__)

# group by endpoint rather than path
metrics = PrometheusMetrics(app, group_by='endpoint')

@app.route('/collection/:collection_id/item/:item_id')
@metrics.counter(
    'cnt_collection', 'Number of invocations per collection', labels={
        'collection': lambda: request.view_args['collection_id'],
        'status': lambda resp: resp.status_code
    })
def get_item_from_collection(collection_id, item_id):
    pass

рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ /рд╕рдВрдЧреНрд░рд╣/10002/рдЖрдЗрдЯрдо/76 рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд╛рдЙрдВрдЯрд░ рдореЗрдВ рд╡реГрджреНрдзрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрдиреЗрдЧрд╛ cnt_collection{рд╕рдВрдЧреНрд░рд╣ = "10002", рд╕реНрдерд┐рддрд┐ = "200"}, рд╕рд╛рде рд╣реА рдЖрдкрдХреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореЗрдЯреНрд░рд┐рдХреНрд╕ (рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рд▓рд┐рдП) рдорд┐рд▓реЗрдВрдЧреЗ:

  • flask_http_request_duration_seconds - рд╡рд┐рдзрд┐, рдкрде рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕рднреА рдлреНрд▓рд╛рд╕реНрдХ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП HTTP рдЕрдиреБрд░реЛрдз рдЕрд╡рдзрд┐ рд╕реЗрдХрдВрдб рдореЗрдВ

  • flask_http_request_total - рд╡рд┐рдзрд┐рдпреЛрдВ рдФрд░ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдХреБрд▓ рд╕рдВрдЦреНрдпрд╛

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

app = Flask(__name__)
metrics = PrometheusMetrics(app)

@app.route('/')
def main():
    pass  # requests tracked by default

@app.route('/skip')
@metrics.do_not_track()
def skip():
    pass  # default metrics are not collected

# custom metric to be applied to multiple endpoints
common_counter = metrics.counter(
    'by_endpoint_counter', 'Request count by endpoints',
    labels={'endpoint': lambda: request.endpoint}
)

@app.route('/common/one')
@common_counter
def endpoint_one():
    pass  # tracked by the custom and the default metrics

@app.route('/common/two')
@common_counter
def endpoint_two():
    pass  # also tracked by the custom and the default metrics

# register additional default metrics
metrics.register_default(
    metrics.counter(
        'by_path_counter', 'Request count by request paths',
        labels={'path': lambda: request.path}
    )
)

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

рдореЗрдЯреНрд░рд┐рдХреНрд╕ рд╕рдВрдЧреНрд░рд╣

рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдПрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ /рдореИрдЯреНрд░рд┐рдХреНрд╕ рдлреНрд▓рд╛рд╕реНрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ, рдЬреЛ рдПрдХ рд▓рдХреНрд╖реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдмрд┐рд▓реНрдбрд░.

рдЙрдкрд░реЛрдХреНрдд рдбреИрд╢рдмреЛрд░реНрдб рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЖрдк рдЕрдкрдиреЗ рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдХреЛ рдЗрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╡рд╛рд▓реЗ рдлреНрд▓рд╛рд╕реНрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░ рд▓рдХреНрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

scrape_configs:
  - job_name: 'example'

    dns_sd_configs:
      - names: ['app']
        port: 5000
        type: A
        refresh_interval: 5s

рдкреВрд░рд╛ рдЙрджрд╛рд╣рд░рдг рдпрд╣рд╛рдВ рджреЗрдЦреЗрдВ GitHub рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА. рдпрд╣ рдорд╛рдирддрд╛ рд╣реИ рдХрд┐ рдкреНрд░реЛрдореЗрдерд┐рдпрд╕ рдЖрдкрдХреЗ рдлреНрд▓рд╛рд╕реНрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХреЛ рдвреВрдВрдв рд╕рдХрддрд╛ рд╣реИ http://app:5000/metrics, рдЬрд╣рд╛рдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдбреЛрдореЗрди рдирд╛рдо рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рдПрдХрд╛рдзрд┐рдХ рдЖрдИрдкреА рдкрддреЗ рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЪрд▓рддреЗ рд╕рдордп Kubernetes рдпрд╛ рдбреЛрдХрд░ рдЭреБрдВрдб.

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

from flask import Flask, request
from prometheus_flask_exporter import PrometheusMetrics

app = Flask(__name__)
metrics = PrometheusMetrics(app, path=None)

...

metrics.start_http_server(5099)

рддрдм рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдкреНрд░рд╛рд░рдВрдн_http_рд╕рд░реНрд╡рд░(рдкреЛрд░реНрдЯ)рдЗрд╕ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЛ рдХрд┐рд╕реА рднрд┐рдиреНрди HTTP рдкреЛрд░реНрдЯ рдкрд░ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, 5099 рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ. рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ, рдпрджрд┐ рдЖрдк рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рдПрдХ рд╣реА рдлреНрд▓рд╛рд╕реНрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рд╣реЛрдиреЗ рд╕реЗ рдЦреБрд╢ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдЗрд╕рдХрд╛ рдкрде рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ /рдореИрдЯреНрд░рд┐рдХреНрд╕, рдЖрдк рдпрд╛ рддреЛ рдкрде рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдФрд░ рдпреВрдЖрд░рдЖрдИ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рд░рдЬрд┐рд╕реНрдЯрд░_рдПрдВрдбрдкреЙрдЗрдВрдЯ(..)рдЗрд╕реЗ рдмрд╛рдж рдореЗрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП.

рд╕рдВрджрд░реНрднреЛрдВ

рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдмреЗрдЭрд┐рдЭрдХ GitHub рдкрд░ рдПрдХ рдореБрджреНрджрд╛ рдЦреЛрд▓реЗрдВ рдпрд╛ рдЕрдкрдиреА рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдФрд░ рд╕реБрдЭрд╛рд╡ рдЫреЛрдбрд╝реЗрдВ!

рд╢реБрдХреНрд░рд┐рдпрд╛!

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╝реЗрдВ