brunch

Python: Elastic APM

파이썬 플라스크 웹 서버 모니터링

by 유윤식

간단 사용기.


우선,

AWS에서 Elasticsearch 서비스를 활용하고 있다는 가정하에.


Elasticsearch API 로 접근하기 위한 IP 는 10.10.0.2


Python Web Server 로 접근하기 위한 IP 는 10.10.2.2


첫번째로,

Elasticsearch 를 서비스하고 있는 VM 에 APM 전용 서비스를 설치


>> curl -L -O https://artifacts.elastic.co/downloads/apm-server/apm-server-7.1.1-x86_64.rpm

>> rpm -vi apm-server-7.1.1-x86_64.rpm

>> service apm-server start

정상 구동 되었다면,

>> systemctl enable apm-server



잠시 APM 서비스의 .yml 파일을 살펴볼 필요가 있다.

2 곳의 설정을 바꿔주면 우선 간단하게 실행 할 수 있다.


apm_yml_result2.png APM 서비스 호스트
apm_yml_result.png Elasticsearch output 호스트


다음으로,

Flask 라이브러리 설치


>> pip install flask

or,

>> python3 -m pip install flask

and,

>> python3 -m pip install elastic-apm[flask]



80% 완료!


간단한 flask 구동 서버 코드

file: app.py


from elasticapm.contrib.flask import ElasticAPM

from elasticapm.handlers.logging import LoggingHandler

from flask import Flask, flash, redirect, render_template, request, url_for, logging


app = Flask(__name__)

app.secret_key = 'random string'

app.config['ELASTIC_APM'] ={

'SERVICE_NAME': 'aws',

'SECRET_TOKEN': 'david',

'SERVER_URL': 'http://10.10.0.2:8200'

}

apm = ElasticAPM(app, logging=True)

@app.route('/')

def index():

return render_template('index.html')

@app.route('/login', methods = ['GET', 'POST'])

def login():

error = None

if request.method == 'POST':

if request.form['username'] != 'admin' or request.form['password'] != 'admin':

error = 'Invalid username or password. Please try again!'

app.logger.error( 'Critical Error!! Call 112!!!', exc_info=True)

else:

flash('You were successfully logged in')

return redirect(url_for('index'))

return render_template('login.html', error = error)

if __name__ == "__main__":

handler = LoggingHandler(client=apm.client)

#handler.setLevel(logging.DEBUG)

app.logger.addHandler(handler)

app.run(host="10.10.2.2")


file: /templates/index.html


<!doctype html>

<html>

<head>

<title>Flask Message flashing</title>

</head>

<body>

{% with messages = get_flashed_messages() %}

{% if messages %}

<ul>

{% for message in messages %}

<li>{{ message }}</li>

{% endfor %}

</ul>

{% endif %}

{% endwith %}

<h1>Flask Message Flashing Example</h1>

<p>Do you want to <a href = "{{ url_for('login') }}">

<b>log in?</b></a></p>

</body>

</html>


file: /templates/login.html


<!doctype html>

<html>

<body>

<h1>Login</h1>

{% if error %}

<p><strong>Error:</strong> {{ error }}

{% endif %}

<form action = "" method = post>

<dl>

<dt>Username:</dt>

<dd>

<input type = text name = username

value = "{{request.form.username }}">

</dd>

<dt>Password:</dt>

<dd><input type = password name = password></dd>

</dl>

<p><input type = submit value = Login></p>

</form>

</body>

</html>



간단한 테스트!


>> python3 app.py

* Serving Flask app "app" (lazy loading)

* Environment: production

WARNING: This is a development server. Do not use it in a production deployment.

Use a production WSGI server instead.

* Debug mode: off



접속!

Flask 는 기본을 5000번 포트를 사용한다.

apm_flask_login_result.png 처음 접속 화면
apm_flask_login_fail_result.png 로그인 실패
apm_flask_login_success_result.png 로그인 성공
apm_flask_kibana_result.png Kibana APM 화면구성
apm_flask_kibana_error_result.png 로그인 실패 관련 로깅


이게 사실은 DB 접속, 외부 웹 사이트 접속, 인증 등의 다양한 서비스를 포함하는

웹 서비스에 사용하면 좋다.


응답 속도, 응답 내용 등에 대한 간단한 내용뿐만 아니라.

누가 어떤 경로로 어떤 요청과 어떤 응답을 받았는지,

이게 다른 사용자와 어떻게 다르고,

어떤 문제점을 가지는지에 대해서 분석할 수 있는

기본 정보를 제공한다.


결국! Graph!!


끝.


* 참고로 Elastic 도 Graph 모듈이 존재한다.

keyword
작가의 이전글Linux:iptables on AWS VPC