Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RHCLOUD-4283 - Enabling stdout logs #650

Merged
merged 25 commits into from
Jul 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f150695
rebasing
tahmidefaz May 1, 2020
4d83a84
using logconfig as default log_config_file
tahmidefaz May 4, 2020
f4d5bc2
Merge branch 'master' into stdout-logging
tahmidefaz May 4, 2020
afca122
Merge remote-tracking branch 'origin' into stdout-logging
tahmidefaz May 22, 2020
c983e0c
resolving conflicts
tahmidefaz May 22, 2020
e693f88
applying suggestions
tahmidefaz May 27, 2020
8e61d98
fixing cloudwatch logs
tahmidefaz May 28, 2020
188767e
Merge branch 'master' into stdout-logging
shdunning Jun 4, 2020
5a794b3
cloudwatch working without global vars :tada:
tahmidefaz Jun 15, 2020
9292e45
Merge branch 'master' into stdout-logging
tahmidefaz Jun 15, 2020
8a9a754
Merge branch 'master' into stdout-logging
Glutexo Jun 24, 2020
dfc53ba
Merge branch 'master' into stdout-logging
Glutexo Jun 29, 2020
3f29d5f
Stdout logging (#673)
tahmidefaz Jul 1, 2020
adc7f91
remove cw handler if creds not present
tahmidefaz Jul 2, 2020
6a0bd5b
freaking lint :man_facepalming:
tahmidefaz Jul 2, 2020
4dee8cb
reverting
tahmidefaz Jul 2, 2020
c7bda5e
reverting
tahmidefaz Jul 2, 2020
36895ea
fix
tahmidefaz Jul 2, 2020
060c8a5
Merge branch 'master' into stdout-logging
tahmidefaz Jul 2, 2020
68dd40a
deleting logconfig.ini
tahmidefaz Jul 2, 2020
a824ae5
Merge branch 'stdout-logging' of github.com:RedHatInsights/insights-h…
tahmidefaz Jul 2, 2020
213a10e
addressing suggestions
tahmidefaz Jul 2, 2020
270d3fe
Remove redundant logging
Glutexo Jul 3, 2020
9628b91
Remove config file variable from Makefile
Glutexo Jul 3, 2020
8ad446c
update README
jharting Jul 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ run_inv_web_service:
#
# KAFKA_TOPIC="platform.system-profile" KAFKA_GROUP="inventory" KAFKA_BOOTSTRAP_SERVERS="localhost:29092"
#
INVENTORY_LOGGING_CONFIG_FILE=logconfig.ini INVENTORY_LOG_LEVEL=DEBUG gunicorn -b :8080 run
INVENTORY_LOG_LEVEL=DEBUG gunicorn -b :8080 run

run_inv_mq_service:
PAYLOAD_TRACKER_SERVICE_NAME=inventory-mq-service INVENTORY_LOGGING_CONFIG_FILE=logconfig.ini \
INVENTORY_LOG_LEVEL=DEBUG python inv_mq_service.py
PAYLOAD_TRACKER_SERVICE_NAME=inventory-mq-service INVENTORY_LOG_LEVEL=DEBUG python inv_mq_service.py

run_inv_mq_service_test_producer:
python utils/kafka_producer.py
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ runs.
A command to run the server in a cluster.

```
gunicorn -c gunicorn.conf.py --log-config=$INVENTORY_LOGGING_CONFIG_FILE run
gunicorn -c gunicorn.conf.py run
```

Running the server locally for development. In this case it’s not necessary to
Expand Down
2 changes: 1 addition & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def create_app(runtime_environment):

# This feels like a hack but it is needed. The logging configuration
# needs to be setup before the flask app is initialized.
configure_logging(runtime_environment)
configure_logging()

app_config = Config(runtime_environment)
app_config.log_configuration()
Expand Down
70 changes: 24 additions & 46 deletions app/logging.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,61 @@
import logging.config
import os
from logging import NullHandler
from threading import local

import logstash_formatter
import watchtower
from boto3.session import Session
from gunicorn import glogging
from yaml import safe_load

OPENSHIFT_ENVIRONMENT_NAME_FILE = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
DEFAULT_AWS_LOGGING_NAMESPACE = "inventory-dev"
LOGGER_PREFIX = "inventory."
DEFAULT_LOGGING_CONFIG_FILE = "logconfig.yaml"
LOGGER_NAME = "inventory"

threadctx = local()


def configure_logging(runtime_environment):
env_var_name = "INVENTORY_LOGGING_CONFIG_FILE"
log_config_file = os.getenv(env_var_name)
if log_config_file is not None:
# The logging module throws an odd error (KeyError) if the
# config file is not found. Hopefully, this makes it more clear.
try:
fh = open(log_config_file)
fh.close()
except FileNotFoundError:
print(
f"Error reading the logging configuration file. Verify the {env_var_name} environment variable is "
"set correctly. Aborting..."
)
raise

logging.config.fileConfig(fname=log_config_file)
def configure_logging():
log_config_file = os.getenv("INVENTORY_LOGGING_CONFIG_FILE", DEFAULT_LOGGING_CONFIG_FILE)
with open(log_config_file) as log_config_file:
logconfig_dict = safe_load(log_config_file)
tahmidefaz marked this conversation as resolved.
Show resolved Hide resolved

if runtime_environment.logging_enabled:
_configure_watchtower_logging_handler()
_configure_contextual_logging_filter()
logging.config.dictConfig(logconfig_dict)
logger = logging.getLogger(LOGGER_NAME)
log_level = os.getenv("INVENTORY_LOG_LEVEL", "INFO").upper()
logger.setLevel(log_level)


def _configure_watchtower_logging_handler():
def cloudwatch_handler():
aws_access_key_id = os.getenv("AWS_ACCESS_KEY_ID", None)
aws_secret_access_key = os.getenv("AWS_SECRET_ACCESS_KEY", None)
aws_region_name = os.getenv("AWS_REGION_NAME", None)
log_group = os.getenv("AWS_LOG_GROUP", "platform")
stream_name = os.getenv("AWS_LOG_STREAM", _get_hostname()) # default to hostname
create_log_group = str(os.getenv("AWS_CREATE_LOG_GROUP")).lower() == "true"

if all([aws_access_key_id, aws_secret_access_key, aws_region_name, stream_name]):
print(f"Configuring watchtower logging (log_group={log_group}, stream_name={stream_name})")
if all((aws_access_key_id, aws_secret_access_key, aws_region_name)):
aws_log_group = os.getenv("AWS_LOG_GROUP", "platform")
aws_log_stream = os.getenv("AWS_LOG_STREAM", _get_hostname())
create_log_group = str(os.getenv("AWS_CREATE_LOG_GROUP")).lower() == "true"
print(f"Configuring watchtower logging (log_group={aws_log_group}, stream_name={aws_log_stream})")
boto3_session = Session(
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name=aws_region_name,
)

root = logging.getLogger()
handler = watchtower.CloudWatchLogHandler(
return watchtower.CloudWatchLogHandler(
boto3_session=boto3_session,
log_group=log_group,
stream_name=stream_name,
log_group=aws_log_group,
stream_name=aws_log_stream,
create_log_group=create_log_group,
)
handler.setFormatter(logstash_formatter.LogstashFormatterV1())
root.addHandler(handler)
else:
print("Unable to configure watchtower logging. Please verify watchtower logging configuration!")
return NullHandler()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉


tahmidefaz marked this conversation as resolved.
Show resolved Hide resolved

def _get_hostname():
return os.uname()[1]


def _configure_contextual_logging_filter():
# Only enable the contextual filter if not in "testing" mode
root = logging.getLogger()
root.addFilter(ContextualFilter())
return os.uname().nodename
tahmidefaz marked this conversation as resolved.
Show resolved Hide resolved


class ContextualFilter(logging.Filter):
Expand Down Expand Up @@ -119,8 +101,4 @@ def setup(self, cfg):


def get_logger(name):
log_level = os.getenv("INVENTORY_LOG_LEVEL", "INFO").upper()
logger = logging.getLogger(LOGGER_PREFIX + name)
logger.addFilter(ContextualFilter())
logger.setLevel(log_level)
return logger
return logging.getLogger(f"{LOGGER_NAME}.{name}")
2 changes: 1 addition & 1 deletion host_reaper.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def main(logger):


if __name__ == "__main__":
configure_logging(RUNTIME_ENVIRONMENT)
configure_logging()

logger = get_logger(LOGGER_NAME)
sys.excepthook = partial(_excepthook, logger)
Expand Down
85 changes: 0 additions & 85 deletions logconfig.ini

This file was deleted.

54 changes: 54 additions & 0 deletions logconfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
version: 1
root:
level: INFO
handlers:
- logstash
loggers:
gunicorn.error:
level: ERROR
handlers:
- logstash
propagate: true
gunicorn.access:
level: ERROR
handlers:
- logstash
propagate: true
sqlalchemy.engine:
level: WARNING
handlers:
- logstash
propagate: true
inventory:
level: INFO
handlers:
- logstash
- cloudwatch
propagate: false
inventory.xjoin:
level: WARNING
handlers:
- logstash
propagate: false
handlers:
logstash:
class: logging.StreamHandler
# formatter: logstash
formatter: human_readable
stream: ext://sys.stdout
filters:
- contextual
cloudwatch:
"()": app.logging.cloudwatch_handler
formatter: logstash
filters:
- contextual
formatters:
human_readable:
format: "[%(asctime)s] [%(process)d] [%(thread)d] [%(name)s] [%(levelname)s] %(message)s"
logstash:
class: logstash_formatter.LogstashFormatterV1
filters:
contextual:
"()": app.logging.ContextualFilter
2 changes: 1 addition & 1 deletion run_gunicorn.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def run_server():
variables.
"""
bind = f"0.0.0.0:{LISTEN_PORT}"
run(("gunicorn", "--log-config=logconfig.ini", "--log-level=debug", f"--bind={bind}", "run"))
run(("gunicorn", "--log-level=debug", f"--bind={bind}", "run"))


if __name__ == "__main__":
Expand Down