Skip to content

Instantly share code, notes, and snippets.

Last active Nov 13, 2017
What would you like to do?
unattended loggly config file for Amazon linux, such as used by ElasticBeanstalk.
#!/usr/bin/env python
For configuring loggly on AWD elastic beanstalk instances.
Tested on the following EB configurations:
64 bit Amazon Linux 2017.03 v.2.5.2 running Python 3.4
This is a RHEL-like linux, with rsyslog and no journald.
No checks are made at runtime to test the validity of the account/token or to verify
log delivery. Use the regular '' script interactively for that.
Settings are taken from environment variables, overridable with command line arguments:
- LOGGLY_ACCOUNT - the account name at Loggly
- LOGGLY_TOKEN - the loggly authentication token (a UUID) for submitting data
- LOGGLY_TAGS - a space-separated string of additional tags to apply to the log
- LOGGLY_HOSTNAME - the hostname to report in syslog. If not specified, the default
as reported by gethostname() is used.
- LOGGLY_DOMAIN - domain name appended to hostname. Useful to name a cluster of
virtual hosts.
from __future__ import print_function
import os
import os.path
import sys
import argparse
import subprocess
import shlex
import textwrap
import shutil
import socket
import six
LOGS_01_HOST = ''
# directory location for syslog
RSYSLOG_ETCDIR_CONF = '/etc/rsyslog.d'
# name and location of loggly syslog file
# name and location of loggly syslog backup file
# rsyslog service name
def main():
# parse args
parser = argparse.ArgumentParser(description='Initialize loggly logging')
parser.add_argument('--account', '-a', default=os.environ.get('LOGGLY_ACCOUNT'), help='The Loggly account name (default from LOGGLY_ACCOUNT)')
parser.add_argument('--token', '-t', default=os.environ.get('LOGGLY_TOKEN'), help='The Loggly authentication token (default from LOGGLY_TOKEN)')
parser.add_argument('--tags', nargs='*', help='Additional tags (default from LOGGLY_TAGS)')
parser.add_argument('--hostname', default=os.environ.get('LOGGLY_HOSTNAME'))
parser.add_argument('--domain', default=os.environ.get('LOGGLY_DOMAIN'))
parser.add_argument('--remove', '-r', action='store_true', help='remove loggly configuration')
args = parser.parse_args()
if args.remove:
if not args.account or not args.token:
# No loggly configuration
print("No Loggly credentials. '%s -h' for help" % parser.prog)
if args.tags is not None:
tags = args.tags
elif os.environ.get('LOGGLY_TAGS'):
tags = shlex.split(os.environ['LOGGLY_TAGS'])
tags = None
config = {
'account': args.account,
'token': args.token,
'tags': tags,
'hostname': args.hostname,
'domain' : args.domain,
def configure(config):
log("INFO: Initiating Configure Loggly for Linux.")
# if all the above check passes, write the 22-loggly.conf file
# restart rsyslog service
log("SUCCESS: Linux system successfully configured to send logs via Loggly.")
def write_rsyslog_conf(config):
'''write the contents to 22-loggly.conf file'''
contents = get_loggly_conf(config)
write_script = False
if os.path.exists(LOGGLY_RSYSLOG_CONFFILE):
log("INFO: Loggly rsyslog file %r already exist." % LOGGLY_RSYSLOG_CONFFILE)
with open(LOGGLY_RSYSLOG_CONFFILE, "rb") as fd:
old_contents =
if six.b(contents) != old_contents:
log("WARN: Loggly rsyslog file %r content has changed." % LOGGLY_RSYSLOG_CONFFILE)
log("INFO: Going to back up the conf file: %r to %r" % (LOGGLY_RSYSLOG_CONFFILE, LOGGLY_RSYSLOG_CONFFILE_BACKUP))
write_script = True
write_script = True
if write_script:
with open(LOGGLY_RSYSLOG_CONFFILE, "wb") as fd:
log("INFO: Loggly rsyslog file %r written." % LOGGLY_RSYSLOG_CONFFILE)
def unconfigure(quiet=False):
# in quiet mode, don't log anything if not configured
if quiet and not os.path.exists(LOGGLY_RSYSLOG_CONFFILE):
log("INFO: Initiating uninstall Loggly for Linux.")
# remove 22-loggly.conf file
# restart rsyslog service
log("SUCCESS: Uninstalled Loggly configuration from Linux system.")
def remove_loggly_conf():
'''delete 22-loggly.conf file'''
if os.path.exists(LOGGLY_RSYSLOG_CONFFILE):
return True
def restart_rsyslog():
'''restart rsyslog'''
log("INFO: Restarting the %s service." % RSYSLOG_SERVICE)
code =['service', RSYSLOG_SERVICE, 'restart'])
if code:
log("WARNING: %s did not restart gracefully. Please restart %s manually." % (RSYSLOG_SERVICE, RSYSLOG_SERVICE))
def log(msg):
if msg.startswith('ERROR'):
def get_loggly_conf(config):
template = r'''
# -------------------------------------------------------
# Syslog Logging Directives for Loggly (%(account)
# -------------------------------------------------------
# Define the template used for sending logs to Loggly. Do not change this format.
$template LogglyFormat,"<%%pri%%>%%protocol-version%% %%timestamp:::date-rfc3339%% %(hostname)s %%app-name%% %%procid%% %%msgid%% [%(token)s@%(distribution_id)s %(tags)s] %%msg%%\n"
$WorkDirectory /var/spool/rsyslog # where to place spool files
$ActionQueueFileName fwdRule1 # unique name prefix for spool files
$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible)
$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
$ActionQueueType LinkedList # run asynchronously
$ActionResumeRetryCount -1 # infinite retries if host is down
# Send messages to Loggly over TCP using the template.
*.* @@%(logs_host)s:%(logs_port)d;LogglyFormat
# -------------------------------------------------------
# preprocess data
args = dict(config)
if not args.get('hostname') and not args.get('domain'):
# simply use the rsyslog macro
args['hostname'] = '%HOSTNAME%'
# construct a fixed hostname to send
if not args.get('hostname'):
args['hostname'] = socket.gethostname()
if args.get('domain'):
args['hostname'] = args['hostname'].split('.')[0] + '.' + args['domain']
tags = ['Rsyslog']
if args.get('tags'):
tags += args['tags']
args['tags'] = ' '.join((r'tag=\"%s\"' % tag) for tag in tags)
args['distribution_id'] = LOGGLY_DISTRIBUTION_ID
args['logs_host'] = LOGS_01_HOST
args['logs_port'] = LOGGLY_SYSLOG_PORT
return textwrap.dedent(template[1:]) % args
if __name__ == '__main__':
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment