Hi, I couldn't find any information in the documentation.
How can I access the logger, e.g. to add a handler? I would like to write the output to a file.
I have a bit experience with flask so I tried to access the flask logger
#!/usr/bin/env python3
import connexion
import logging
from logging.handlers import WatchedFileHandler
from swagger_server import encoder
from swagger_server.database import init_db, db_session
from swagger_server.tools import create_path
def main():
app.run(port=8080)
logging.basicConfig(level=logging.INFO)
init_db()
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = encoder.JSONEncoder
app.add_api('swagger.yaml', arguments={'title': 'P7 Renderservice'})
application = app.app
logPath = './data/logs/service.log'
create_path(logPath)
handler = WatchedFileHandler(logPath)
handler.setLevel(logging.DEBUG)
application.logger.addHandler(handler)
@application.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()
if __name__ == '__main__':
main()
-> https://github.com/padok/REST-Event-API-example/blob/master/swagger_server/__main__.py
but my file remains empty
I want to save or modify what the app already print to stdout; for example
172.17.0.1 - - [02/May/2018 03:02:46] "GET /v1/event HTTP/1.1" 200 -
172.17.0.1 - - [02/May/2018 03:02:46] "GET /v1/event HTTP/1.1" 200 -
172.17.0.1 - - [02/May/2018 03:02:46] "GET /v1/event HTTP/1.1" 200 -
172.17.0.1 - - [02/May/2018 03:02:47] "GET /v1/event HTTP/1.1" 200 -
Thanks for your help!
you did more or less correct.
Please use application factory: http://flask.pocoo.org/docs/0.12/patterns/appfactories/
I use a custom extension for logging, but the essential is:
'''
handler = logging.StreamHandler()
handler.setLevel(config['LOGGING_LEVEL'])
handler.setFormatter(logging.Formatter(config['LOGGING_FORMAT']))
app.logger.addHandler(handler)
app.logger.setLevel(app.config['LOGGING_LEVEL'])
'''
after you use the the logger with the correct level.
Instead of StreamHandler it could be any other handler. Or it could be even proxy.
Do you have an example @roman-telepathy-ai ?
logging example is above. a note here: if accessing connexion app, then use app.app.
regarding - App factories just have a look at docs or search for "flask tutorial" (miguel will be on top).
I have figured this out. I'll explain now. I didn't use the app factory pattern though but hopefully my code is clear enough.
I have a special validator class. The code is as follows:
```#!/usr/bin/env python3
import datetime
from connexion.decorators.validation import RequestBodyValidator
from jsonschema import ValidationError
from connexion import problem
from flask import Flask
app = Flask(__name__)
BAD_REQUEST = 'Bad Request'
class RequestBodyValidatorVerboseErrorLogging(RequestBodyValidator):
def validate_schema(self, data, url):
if self.is_null_value_valid and is_null(data):
return None
try:
self.validator.validate(data)
except ValidationError as exception:
app.logger.error("{timestamp} {url} VALIDATION_ERROR: {error} REQUEST_BODY: {request_body}".format(timestamp=datetime.datetime.utcnow().isoformat(),url=url, error=exception.message, request_body=data))
return problem(400, BAD_REQUEST, str(exception.message))
return None
I want to log the error messages of this class to a rotating file. Earlier, I was using the common logger namespace convention but my suspicion was that the Flask application was taking precedence. I changed the logging to use `app.logger.error` instead of `logger.error`. Notice my import above.
My main API file is as follows:
import connexion
import logging
import sys
from event_api_validators import RequestBodyValidatorVerboseErrorLogging
from logging.handlers import RotatingFileHandler
SWAGGER_PATH = '/event_api/'
LOG_PATH = '/error_logs/event_api_error_log.log'
RESOLVED_SWAGGER_FILE = 'api_index_resolved.json'
log_handler = RotatingFileHandler(LOG_PATH, mode='a', maxBytes=10010241024,
backupCount=10, encoding=None, delay=False)
log_handler.setLevel(logging.ERROR)
validator_map = {
'body': RequestBodyValidatorVerboseErrorLogging
}
event_api = connexion.App(__name__, validator_map=validator_map)
event_api.app.logger.addHandler(log_handler)
event_api.app.logger.setLevel(logging.ERROR)
event_api.add_api(RESOLVED_SWAGGER_FILE, swagger_path=SWAGGER_PATH)
if __name__ == '__main__':
event_api.run(port=80)
```
This works with the RotatingFileHandler. Additionally, I still write to stream with the default log handler as well.
exactly
event_api.app.logger.addHandler(log_handler)
event_api.app.logger.setLevel(logging.ERROR)
in your validator class, use
``
from flask import current_app
current_app.logger.info("flask logger: foo")
...
instead ofapp = Flask(__name__)`
Thanks! Much cleaner.
Most helpful comment
exactly
in your validator class, use
``
from flask import current_app current_app.logger.info("flask logger: foo") ... instead ofapp = Flask(__name__)`