How to log to socket in Flask - python

I have the rest of my program using a socketHandler to log which is being consumed using http://code.activestate.com/recipes/577025-loggingwebmonitor-a-central-logging-server-and-mon/.
How do I setup my flask app to log this?
I tried the following based on their docs (http://flask.pocoo.org/docs/errorhandling/#logging-to-a-file):
class HelloWorld(Resource):
def get(self):
resp = "HELLO!"
app.logger.info("GET HelloWorld %s", resp)
return resp
if __name__ == '__main__':
import logging
import logging.handlers # you NEED this line
socketHandler = logging.handlers.SocketHandler('localhost',
logging.handlers.DEFAULT_TCP_LOGGING_PORT)
socketHandler.setLevel(logging.INFO)
app.logger.addHandler(socketHandler)
app.run('0.0.0.0')

Related

Get the exception easily with Azure app insight using python flask

I had tried the code below for getting the exception in https://learn.microsoft.com/en-us/azure/azure-monitor/app/opencensus-python
from opencensus.ext.azure.log_exporter import AzureLogHandler
logger = logging.getLogger(__name__)
# TODO: replace the all-zero GUID with your instrumentation key.
logger.addHandler(AzureLogHandler(
connection_string='InstrumentationKey=00000000-0000-0000-0000-000000000000')
)
properties = {'custom_dimensions': {'key_1': 'value_1', 'key_2': 'value_2'}}
# Use properties in exception logs
try:
result = 1 / 0 # generate a ZeroDivisionError
except Exception:
logger.exception('Captured an exception.', extra=properties)
It is working. I can catch the exception.
However, I want to ask if there is an easy way to catch the exception automatically in the python flask?
Since I try the below code, it just gives me a request record, not the exception.
app = Flask(__name__)
app.logger.addHandler(file_handler)
handler = AzureEventHandler(
connection_string="InstrumentationKey={}".format(app.config['APPINSIGHTS_INSTRUMENTATIONKEY']))
handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
handler.setLevel(logging.ERROR)
app.logger.addHandler(handler)
Thank you for helping
Your code should like below. For more details, you can check offical sample code.
Flask "To-Do" Sample Application
import logging
import sys
from flask import Flask
sys.path.append('..')
from config import Config
from flask_sqlalchemy import SQLAlchemy
from opencensus.ext.azure import metrics_exporter
from opencensus.ext.azure.log_exporter import AzureLogHandler
from opencensus.ext.flask.flask_middleware import FlaskMiddleware
from opencensus.trace import config_integration
logger = logging.getLogger(__name__)
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
# Import here to avoid circular imports
from app import routes # noqa isort:skip
# Trace integrations for sqlalchemy library
config_integration.trace_integrations(['sqlalchemy'])
# Trace integrations for requests library
config_integration.trace_integrations(['requests'])
# FlaskMiddleware will track requests for the Flask application and send
# request/dependency telemetry to Azure Monitor
middleware = FlaskMiddleware(app)
# Processor function for changing the role name of the app
def callback_function(envelope):
envelope.tags['ai.cloud.role'] = "To-Do App"
return True
# Adds the telemetry processor to the trace exporter
middleware.exporter.add_telemetry_processor(callback_function)
# Exporter for metrics, will send metrics data
exporter = metrics_exporter.new_metrics_exporter(
enable_standard_metrics=False,
connection_string='InstrumentationKey=' + Config.INSTRUMENTATION_KEY)
# Exporter for logs, will send logging data
logger.addHandler(
AzureLogHandler(
connection_string='InstrumentationKey=' + Config.INSTRUMENTATION_KEY
)
)
if __name__ == '__main__':
app.run(host='localhost', port=5000, threaded=True, debug=True)

Possible to shut down a Flask app without starting/stopping a server, calling os.kill, or using command line?

I need to start and stop a simple Python app on a Flask server after the app runs and modifies files in the home directory. The app is housed on G Cloud. I've researched similar questions that involve using the command line, os, and http.server to stop the app. None of these approaches will work in my case. The best option seems to be to make a request to an app route that contains a request.environment.get function, which I've tried to do here. But the script triggers the following tracebacks: TypeError: The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a Response. And TypeError: shutdown_server() takes 0 positional arguments but 2 were given. Can I shut down the app using a script and without starting/stopping a server (i.e., using http.server)? If so, what am I doing wrong?
from flask import Flask, render_template, request, jsonify
import urllib.request, urllib.parse, urllib.error
from urllib.request import urlopen
from bs4 import BeautifulSoup
import textwrap
from hidden import consumer_key, consumer_secret, access_token, access_token_secret
import tweepy
from tweepy import TweepError
import requests
app = Flask(__name__, template_folder = 'templates')
app.config.update(
SERVER_NAME = "127.0.0.1:8080"
)
#app.route('/')
def check_status():
with open('app_status.txt') as f:
status = f.read()
status = status.rstrip()
status = int(status)
if status == 1:
with open('app_status.txt', 'w+') as f:
f.write(F'0')
print('exiting')
return requests.get('http://127.0.0.1:8080/shutdown')
if status == 0:
return get_chunk()
def get_chunk():
...
# Create the app's weboutput by rendering an html template
if tweet:
with open('app_status.txt', 'w+') as f:
f.write(F'1')
with app.app_context():
return render_template('index.html', excrpt = chunk_wrp), requests.get('http://127.0.0.1:8080/shutdown')
#app.route("/shutdown", methods=['GET'])
def shutdown():
shutdown_func = request.environ.get('werkzeug.server.shutdown')
if shutdown_func is None:
raise RuntimeError('Not running werkzeug')
shutdown_func()
return "Shutting down..."
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True, use_reloader=True)
A look at the mod_wsgi documentation yielded code for killing a daemon process. For the moment, this appears to be working:
import signal
import os
#...#
def shutdown():
return os.kill(os.getpid(), signal.SIGINT)

Flask-socketio not emitting data from class methods and registered signal slots

I am instantiating flas app from main class of my project, and from one of the module inside project i have created signal to emit data,using signalslot python library, and and flaskApp class is responsible for flask server, and on the same class signal is connected to slot to publish the data to connected websocket
For signalslot i am usign this library https://pypi.org/project/signalslot/
signals.py
import signalslot
on_heartbeat_data_received_signal = signalslot.Signal()
message.py
import signals.py
on_heartbeat_data_received_signal .emit(data="hello")
main.py
class Main():
flaskApp()
if __name__ == "__main__":
main = Main()
flaskApp.py
from flask import Flask
from flask_socketio import SocketIO, emit
from common.signals import on_heartbeat_data_received_signal
class FlaskApp():
def __init__(self,config_path):
self.logger = Logger.get_instance("FlaskApp")
self.logger.debug("started")
# Create an application
app = Flask(__name__)
app.config['SECRET_KEY'] = 'gjr39dkjn344_!67#' #todo read from yaml
socketio.init_app(app, async_mode="threading", cors_allowed_origins="*")
CORS(app)
# load yml to read flask configuration from config path
with open(config_path, "r") as yamlStream:
try:
self.flask_config = yaml.safe_load(yamlStream)["flask"]
except yaml.YAMLError as exc:
print("replace to logger")
self.logger.info(self.flask_config["host"])
self.logger.info(self.flask_config["port"])
self.logger.debug("connect to signal to send to UI..")
on_heartbeat_data_received_signal.connect(self.publish_data)
socketio.run(app, debug=True, host=self.flask_config["host"], port=self.flask_config["port"])
self.logger.debug("flask server is up....")
self.logger.debug("ended")
#socketio.on("connect")
def websocket_connect():
print("websocket connected...")
# socketio.emit("response", "mesg from server") # this line is working
#registered slot to capture data from signal
def publish_data(self, data, **kwargs):
self.logger.debug("started publish data to connected websocket client..")
self.logger.debug(data)
try:
socketio.emit("response-data", data) #this is not emiting data
except Exception as e:
self.logger.error(e)
#socketio.on("response-data")
def handle_message(message):
print(message)

Python POST api giving error. Logs not found

I am new with python. I have a POST api in python deployed on AWS using steps from the below mentioned link.
https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uwsgi-and-nginx-on-ubuntu-16-04
The api is giving internal server error and the logs are not getting printed. Is there a directory which I'm missing or can I print the logs somehow?
Also if someone can help with what could be the possible issue with the API :
#!/usr/bin/env python2.7
#!flask/bin/python
#!/usr/bin/python
import numpy
import sys,os
import codecs
import json
import phonetics
import transliteration
import jellyfish
import traceback
from pyjarowinkler import distance
from flask import Flask, jsonify, request
import panphon.distance
from datetime import datetime
from flask_cors import CORS
def obj_dict(obj):
return obj.__dict__
# logFile = open('log.txt','a')
app = Flask(__name__)
cors = CORS(app, resources={r"/todo/api/*": {"origins": "*"}})
#app.route('/todo/api/v1.0/tasks', methods=['GET''POST'])
def get_tasks():
if request.method == 'GET':
return "done with get request"
elif request.method == 'POST':
try :
content = request.get_json()
with codecs.open('words.txt', 'a') as file:
for line in content['words']:
file.write("\n"+line.encode('utf-8'))
except Exception:
with open('log.txt','a') as logger:
logger.write("At "+str(datetime.now())+" "+traceback.format_exc())
logger.write("\n\n")
return "done"
if __name__ == '__main__':
import logging
logging.basicConfig(filename='log.txt',level=logging.DEBUG)
app.run(host='0.0.0.0', debug = False)
NOTE: The other imports are for some other purpose. I need the POST API to work.
Try setting debug = True
For example
if __name__ == '__main__':
import logging
logging.basicConfig(filename='log.txt',level=logging.DEBUG)
app.run(host='0.0.0.0', debug = True)
Also you don't need to import logging as you can use flask's logger which should be accessible using app.logger
If this is production then debug=True is not recommended.
Flask considers ERROR as the default logging level if you do not set up log level
So you might try setting the log level using app.logger.setLevel(logging.DEBUG)
#app.route('/todo/api/v1.0/tasks', methods=['GET', 'POST'])
def get_tasks():
if request.method == 'GET':
return "done with get request"
elif request.method == 'POST':
try :
content = json.loads(request.get_data())
with codecs.open('words.txt', 'a') as file:
for line in content['words']:
file.write("\n"+line.encode('utf-8'))
except Exception:
with open('log.txt','a') as logger:
logger.write("At "+str(datetime.now())+" "+traceback.format_exc())
logger.write("\n\n")
return "done"

Unable to log messages while running a Flask app

I am trying to tie Flask's logger to a FileHandler, so I can save custom log messages to a file. Anytime I try to log a message when a POST requests hits foo, nothing happens, at all. How can I work around this?
import logging
from logging import FileHandler
from time import strftime
from flask import Flask, Response
app = Flask(__name__)
#app.route('/foo', methods=['POST'])
def bar():
app.logger.info('post request')
...
return Response(), 200
if __name__ == "__main__":
file_date = strftime('%d_%m_%Y')
handler = FileHandler(f'./log/{file_date}.log')
handler.setLevel(logging.INFO)
app.logger.setLevel(logging.INFO)
app.logger.addHandler(handler)
app.run()

Categories