stripe-python icon indicating copy to clipboard operation
stripe-python copied to clipboard

JSON log formatting

Open neilpanchal opened this issue 3 years ago • 0 comments

Hello,

It would be great to allow users to format logs in json format instead of the hardcoded logfmt format in the library. For those looking to make this work, this is how we did it:

# strip_log_formatter.py
import datetime
import json

from pythonjsonlogger import jsonlogger


class StripeJsonLogFormatter(jsonlogger.JsonFormatter):  # pragma: no cover
    def add_fields(self, log_record, record, message_dict):
        """
        This method allows us to inject custom data into resulting log messages
        """
        for field in self._required_fields:
            log_record[field] = record.__dict__.get(field)
        log_record.update(message_dict)

        # Add timestamp and application name if not present
        if 'timestamp' not in log_record:
            now = datetime.datetime.utcnow()
            log_record['timestamp'] = now.isoformat()
        if 'application' not in log_record:
            log_record['application'] = 'myapp'

        if 'level' not in log_record:
            log_record['level'] = record.levelname

        jsonlogger.merge_record_extra(record, log_record, reserved=self._skip_fields)

Reference this class from stripe_log_formatter.py in log ini configuration file as follows:

[loggers]
keys=stripe

[handlers]
keys=stripe_file

[formatters]
keys=stripe_json

[logger_stripe]
level=INFO
handlers=stripe_file
qualname=stripe
propagate=0

[handler_stripe_file]
class=logging.handlers.WatchedFileHandler
formatter=stripe_json
args=('/var/log/myapp/stripe.json',)

[formatter_stripe_json]
class=app.stripe_log_formatter.StripeJsonLogFormatter

And then at import time, monkey patch stripe library:

# Monkey patch Stripe logfmt formatter
# Watch for this code if it ever changes, things will break:
# https://github.com/stripe/stripe-python/blob/v2.67.0/stripe/util.py#L82

old_log_fmt = stripe.util.logfmt

def new_logfmt(props):
    return OrderedDict(sorted(props.items(), key=lambda x: x[0]))

stripe.util.logfmt = new_logfmt

Any chance we can get an ability to configure our own log formatter?

neilpanchal avatar Mar 09 '22 05:03 neilpanchal