เชชเซเชฐเซ‹เชฎเชฟเชฅเชฟเชฏเชธ เชธเชพเชฅเซ‡ เชซเซเชฒเชพเชธเซเช• เชฎเชพเช‡เช•เซเชฐเซ‹เชธเชฐเซเชตเชฟเชธเชฟเชธเชจเซเช‚ เชฎเซ‹เชจเชฟเชŸเชฐเชฟเช‚เช—

เช•เซ‹เชกเชจเซ€ เช•เซ‡เชŸเชฒเซ€เช• เชฒเชพเช‡เชจ เช…เชจเซ‡ เชคเชฎเชพเชฐเซ€ เชเชชเซเชฒเชฟเช•เซ‡เชถเชจ เชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธ เชœเชจเชฐเซ‡เชŸ เช•เชฐเซ‡ เช›เซ‡, เชตเชพเชน!

เชชเซเชฐเซ‹เชฎเชฟเชฅเชฟเชฏเชธ_ เช•เซ‡เชตเซ€ เชฐเซ€เชคเซ‡ เช•เชพเชฐเซเชฏ เช•เชฐเซ‡ เช›เซ‡ เชคเซ‡ เชธเชฎเชœเชตเชพ เชฎเชพเชŸเซ‡เชซเซเชฒเชพเชธเซเช•_เชจเชฟเช•เชพเชธเช•เชพเชฐ เชฎเชพเชŸเซ‡ เชจเซเชฏเซ‚เชจเชคเชฎ เช‰เชฆเชพเชนเชฐเชฃ เชชเซ‚เชฐเชคเซเช‚ เช›เซ‡:

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

เช‰เชชเชฐเชจเชพ เช‰เชฆเชพเชนเชฐเชฃเชฎเชพเช‚, เช…เช‚เชคเชฟเชฎ เชฌเชฟเช‚เชฆเซ เชชเชฐ เช•เซเชฒเชฟเช• เช•เชฐเชตเซเช‚ /collection/10002/item/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}
    )
)

เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เชฎเชพเช‚ เชฒเซ‹เช•เชชเซเชฐเชฟเชฏ เชฎเชฒเซเชŸเชฟเชชเซเชฐเซ‹เชธเซ‡เชธเชฟเช‚เช— เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€เช“ เชœเซ‡เชฎ เช•เซ‡ uWSGI เช…เชจเซ‡ Gunicorn เชฎเชพเชŸเซ‡ เช…เชจเซเช•เซ‚เชณ เชเช•เซเชธเชŸเซ‡เชจเซเชถเชจ เช›เซ‡. เชคเชฎเซ‡ เชฎเชฒเซเชŸเชฟเชชเซเชฐเซ‹เชธเซ‡เชธเชฟเช‚เช— เชธเชนเชฟเชค เชฒเช•เซเชทเชฟเชค เช‰เชชเชฏเซ‹เช—เชจเชพ เช•เซ‡เชธเซ‹เชจเชพ เชจเชพเชจเชพ เช‰เชฆเชพเชนเชฐเชฃเซ‹ เชชเชฃ เชถเซ‹เชงเซ€ เชถเช•เซ‹ เช›เซ‹.

เชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธ เชธเช‚เช—เซเชฐเชน

เช‰เชชเชฐ เชœเชฃเชพเชตเซเชฏเชพ เชฎเซเชœเชฌ, เชฒเชพเช‡เชฌเซเชฐเซ‡เชฐเซ€ เชฎเซ‚เชณเชญเซ‚เชค เชฐเซ€เชคเซ‡ เช…เช‚เชคเชฟเชฎ เชฌเชฟเช‚เชฆเซ เชชเซเชฐเชฆเชพเชจ เช•เชฐเซ‡ เช›เซ‡ /เชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธ เชซเซเชฒเชพเชธเซเช• เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชฎเชพเช‚, เชœเซ‡ เชฒเช•เซเชทเซเชฏ เชคเชฐเซ€เช•เซ‡ เชธเซ‡เชตเชพ เช†เชชเซ€ เชถเช•เซ‡ เช›เซ‡ เชชเซเชฐเซ‹เชฎเชฟเชฅเชฟเชฏเชธ เชฌเชฟเชฒเซเชกเชฐ.

เช‰เชชเชฐเชจเชพ เชกเซ‡เชถเชฌเซ‹เชฐเซเชก เช‰เชฆเชพเชนเชฐเชฃเชฎเชพเช‚, เชคเชฎเซ‡ เชคเชฎเชพเชฐเชพ เชชเซเชฐเซ‹เชฎเชฟเชฅเชฟเชฏเชธเชจเซ‡ เช† เชฐเซ‚เชชเชฐเซ‡เช–เชพเช‚เช•เชจ เชธเชพเชฅเซ‡ เชกเชฟเชซเซ‹เชฒเซเชŸ เชธเซ‡เชŸเชฟเช‚เช—เซเชธ เชธเชพเชฅเซ‡ เชซเซเชฒเชพเชธเซเช• เชเชชเซเชฒเชฟเช•เซ‡เชถเชจ เชชเชฐ เชฒเช•เซเชทเซเชฏ เชฌเชจเชพเชตเซ€ เชถเช•เซ‹ เช›เซ‹:

scrape_configs:
  - job_name: 'example'

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

เชชเชฐ เชธเช‚เชชเซ‚เชฐเซเชฃ เช‰เชฆเชพเชนเชฐเชฃ เชœเซเช“ GitHub เชฐเซ€เชชเซ‹เชเซ€เชŸเชฐเซ€เช. เช† เชงเชพเชฐเซ‡ เช›เซ‡ เช•เซ‡ เชชเซเชฐเซ‹เชฎเชฟเชฅเชฟเชฏเชธ เชคเชฎเชพเชฐเชพ เชซเซเชฒเชพเชธเซเช• เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชจเชพ เชฆเชพเช–เชฒเชพเช“ เชถเซ‹เชงเซ€ เชถเช•เซ‡ เช›เซ‡ http://app:5000/metrics, เชœเซเชฏเชพเช‚ เชเชชเซเชฒเชฟเช•เซ‡เชถเชจ เชกเซ‹เชฎเซ‡เชจ เชจเชพเชฎ เชธเช‚เชญเชตเชฟเชค เชฐเซ€เชคเซ‡ เชฌเชนเซเชตเชฟเชง IP เชธเชฐเชจเชพเชฎเชพเช‚เชจเซ‡ เช‰เช•เซ‡เชฒเซ€ เชถเช•เซ‡ เช›เซ‡, เช‰เชฆเชพเชนเชฐเชฃ เชคเชฐเซ€เช•เซ‡ เชœเซเชฏเชพเชฐเซ‡ เชšเชพเชฒเซ€ เชฐเชนเซเชฏเซเช‚ เชนเซ‹เชฏ เช•เซเชฏเซเชฌเชฐเซเชจเซ‡เชŸเชฟเชธ เช…เชฅเชตเชพ เชกเซ‹เช•เชฐ เชธเซเชตเซ‹เชฐเซเชฎ.

เชœเซ‹ เชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธ เชเชจเซเชกเชชเซ‹เช‡เชจเซเชŸเชจเซ‡ เช† เชฐเซ€เชคเซ‡ เชเช•เซเชธเชชเซ‹เช เช•เชฐเชตเซเช‚ เชคเชฎเชจเซ‡ เช…เชจเซเช•เซ‚เชณ เชจ เช†เชตเซ‡, เชคเซ‹ เช•เชฆเชพเชš เชคเชฎเซ‡ เชคเซ‡เชจเซ‡ เชเช•เซเชธเชŸเชฐเซเชจเชฒ เชเช•เซเชธเซ‡เชธเชจเซ‡ เชฎเช‚เชœเซ‚เชฐเซ€ เช†เชชเชตเชพ เชฎเชพเช‚เช—เชคเชพ เชจ เชนเซ‹เชต, เชคเซ‹ เชคเชฎเซ‡ เชคเซ‡เชจเซ‡ เชธเชฐเชณเชคเชพเชฅเซ€ เชชเชธเชพเชฐ เช•เชฐเซ€เชจเซ‡ เช…เช•เซเชทเชฎ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ เชชเชพเชฅ=เช•เซ‹เชˆ เชจเชนเซ€เช‚ เชฆเชพเช–เชฒเซ‹ เชฌเชจเชพเชตเชคเซ€ เชตเช–เชคเซ‡ เชชเซเชฐเซ‹เชฎเชฟเชฅเชฟเชฏเชธเชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธ.

from flask import Flask, request
from prometheus_flask_exporter import PrometheusMetrics

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

...

metrics.start_http_server(5099)

เชชเช›เซ€ เชคเชฎเซ‡ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ start_http_server(เชชเซ‹เชฐเซเชŸ)เช† เชเชจเซเชกเชชเซ‹เช‡เชจเซเชŸเชจเซ‡ เช…เชฒเช— HTTP เชชเซ‹เชฐเซเชŸ เชชเชฐ เช–เซ‹เชฒเชตเชพ เชฎเชพเชŸเซ‡, 5099 เช‰เชชเชฐเชจเชพ เช‰เชฆเชพเชนเชฐเชฃเชฎเชพเช‚. เชตเซˆเช•เชฒเซเชชเชฟเช• เชฐเซ€เชคเซ‡, เชœเซ‹ เชคเชฎเซ‡ เช…เช‚เชคเชฟเชฎ เชฌเชฟเช‚เชฆเซ เชธเชฎเชพเชจ เชซเซเชฒเชพเชธเซเช• เชเชชเซเชฒเชฟเช•เซ‡เชถเชจเชฎเชพเช‚ เชนเซ‹เชตเชพเชฅเซ€ เช–เซเชถ เช›เซ‹, เชชเชฐเช‚เชคเซ เชคเชฎเชพเชฐเซ‡ เชคเซ‡เชจเซ‹ เชฎเชพเชฐเซเช— เชฌเชฆเชฒเชตเชพเชจเซ€ เชœเชฐเซ‚เชฐ เช›เซ‡ /เชฎเซ‡เชŸเซเชฐเชฟเช•เซเชธ, เชคเชฎเซ‡ เช•เชพเช‚ เชคเซ‹ เชชเชพเชฅ เชชเซ‡เชฐเชพเชฎเซ€เชŸเชฐ เชคเชฐเซ€เช•เซ‡ เช…เชจเซเชฏ URI เชชเชพเชธ เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ เช…เชฅเชตเชพ เช‰เชชเชฏเซ‹เช— เช•เชฐเซ€ เชถเช•เซ‹ เช›เซ‹ เชฐเชœเซ€เชธเซเชŸเชฐ_เชเชจเซเชกเชชเซ‹เช‡เชจเซเชŸ(..)เชคเซ‡เชจเซ‡ เชชเช›เซ€เชฅเซ€ เช‡เชจเซเชธเซเชŸเซ‹เชฒ เช•เชฐเชตเชพ เชฎเชพเชŸเซ‡.

เชธเช‚เชฆเชฐเซเชญเซ‹

เชœเซ‹ เชคเชฎเซ‡ เชคเซ‡เชจเซ‡ เช…เชœเชฎเชพเชตเชตเชพเชจเซเช‚ เชจเช•เซเช•เซ€ เช•เชฐเซ‹ เช›เซ‹, เชคเซ‹ GitHub เชชเชฐ เช•เซ‹เชˆ เชฎเซเชฆเซเชฆเซ‹ เช–เซ‹เชฒเชตเชพ เชฎเชพเชŸเซ‡ เชจเชฟเชƒเชธเช‚เช•เซ‹เชš เช…เชฅเชตเชพ เชคเชฎเชพเชฐเซ€ เชŸเชฟเชชเซเชชเชฃเซ€เช“, เชชเซเชฐเชคเชฟเชธเชพเชฆ เช…เชจเซ‡ เชธเซ‚เชšเชจเซ‹ เชฎเซ‚เช•เซ‹!

เช†เชญเชพเชฐ!

เชธเซ‹เชฐเซเชธ: www.habr.com

เชเช• เชŸเชฟเชชเซเชชเชฃเซ€ เช‰เชฎเซ‡เชฐเซ‹