Merge ~tcuthbert/container-log-archive-charm:master into container-log-archive-charm:master

Proposed by Thomas Cuthbert
Status: Merged
Approved by: Thomas Cuthbert
Approved revision: d9dc3c38ffad698efdac6416b6851a4e31a3cd34
Merged at revision: 15e5780ea039a712d25937961e36a72ac662a716
Proposed branch: ~tcuthbert/container-log-archive-charm:master
Merge into: container-log-archive-charm:master
Diff against target: 192 lines (+45/-17)
7 files modified
files/archive-to-azure.py (+2/-4)
files/archive-to-gce.py (+2/-4)
files/archive-to-s3.py (+2/-4)
files/archive-to-swift.py (+2/-4)
files/archive.py (+12/-1)
files/container-log-archive.logrotate (+12/-0)
hooks/hooks.py (+13/-0)
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Canonical IS Reviewers Pending
Review via email: mp+387730@code.launchpad.net

Commit message

Implement console and filebased logging

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Stuart Bishop (stub) wrote :

This looks mostly fine. Per inline comments, it would be better if the log file didn't get created at import time. And we want to use a different class to FileHandler because we are rotating the logs. You could drop the logrotate stuff entirely if you use one of the Python builtin log rotating handlers, but they might not have all the features you want such as compression.

review: Needs Fixing
Revision history for this message
Stuart Bishop (stub) wrote :

If we have focal/python3.8, I think the following will lazily instantiate the log:

_log = None

def __getattr__(name):
    if name == 'log':
        global _log
        if _log is None:
            _log = create_logger()
        return _log
    raise AttributeError(name)

(per 3rd answer on https://stackoverflow.com/questions/880530/can-modules-have-properties-the-same-way-that-objects-can#880550)

Revision history for this message
Stuart Bishop (stub) wrote :

The log instances are still getting created at import time unfortunately; the 'log = get_log()' lines are still evaluated at import time, so this hasn't changed much. I'd probably revert the last commit (except for the WatchedFileHandler bit, which we need).

I've realized the simplest fix for the issue I raised is to rename create_logger() initialize_logging(), and to initialize the module global 'log' variables with just log=logging.getLogger(). The modules will then get loggers with no handlers attached. You then call initialize_logging() from the __main__ section of your scripts, and the handlers get attached.

Revision history for this message
Stuart Bishop (stub) wrote :

Yup

review: Approve
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision 15e5780ea039a712d25937961e36a72ac662a716

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/files/archive-to-azure.py b/files/archive-to-azure.py
2index 4af0861..82a0d54 100755
3--- a/files/archive-to-azure.py
4+++ b/files/archive-to-azure.py
5@@ -16,7 +16,6 @@
6 # 'archive-to-azure.py -s -f [config_file] -l [logdir1] -l [logdir2] -c [container_name] -a [archive_after] -d [delete_after] -p [retention_days]'
7
8 import os
9-import logging
10 import sys
11 import datetime
12
13@@ -26,9 +25,7 @@ import hmac
14 import hashlib
15 import base64
16 import xml.etree.ElementTree as ET
17-from archive import CloudStorage, main, Status
18-
19-log = logging.getLogger()
20+from archive import CloudStorage, main, initialise_logger, Status
21
22
23 class AzureCloudStorage(CloudStorage):
24@@ -310,4 +307,5 @@ class AzureCloudStorage(CloudStorage):
25
26
27 if __name__ == "__main__":
28+ log = initialise_logger()
29 sys.exit(main(AzureCloudStorage))
30diff --git a/files/archive-to-gce.py b/files/archive-to-gce.py
31index 147626c..d32917f 100755
32--- a/files/archive-to-gce.py
33+++ b/files/archive-to-gce.py
34@@ -18,7 +18,6 @@
35 import os
36 import io
37 import json
38-import logging
39 import sys
40 import datetime
41
42@@ -27,9 +26,7 @@ import apiclient
43 from apiclient import discovery
44 from apiclient.http import MediaIoBaseUpload
45 from oauth2client.service_account import ServiceAccountCredentials
46-from archive import CloudStorage, main, Status
47-
48-log = logging.getLogger()
49+from archive import CloudStorage, main, initialise_logger, Status
50
51
52 class GCECloudStorage(CloudStorage):
53@@ -160,4 +157,5 @@ class GCECloudStorage(CloudStorage):
54
55
56 if __name__ == "__main__":
57+ log = initialise_logger()
58 sys.exit(main(GCECloudStorage))
59diff --git a/files/archive-to-s3.py b/files/archive-to-s3.py
60index 45af6a4..c82cbd0 100755
61--- a/files/archive-to-s3.py
62+++ b/files/archive-to-s3.py
63@@ -16,16 +16,13 @@
64 # 'archive-to-s3.py -s -f [config_file] -l [logdir1] -l [logdir2] -c [container_name] -a [archive_after] -d [delete_after] -p [retention_days]'
65
66 import os
67-import logging
68 import sys
69 import datetime
70
71 import json
72 import boto
73 from boto.s3.connection import OrdinaryCallingFormat
74-from archive import CloudStorage, main, Status
75-
76-log = logging.getLogger()
77+from archive import CloudStorage, main, initialise_logger, Status
78
79
80 class S3CloudStorage(CloudStorage):
81@@ -220,4 +217,5 @@ class S3CloudStorage(CloudStorage):
82
83
84 if __name__ == "__main__":
85+ log = initialise_logger()
86 sys.exit(main(S3CloudStorage))
87diff --git a/files/archive-to-swift.py b/files/archive-to-swift.py
88index ac83a25..535c7f5 100755
89--- a/files/archive-to-swift.py
90+++ b/files/archive-to-swift.py
91@@ -16,15 +16,12 @@
92 # 'archive-to-swift.py -s -f [config_file] -l [logdir1] -l [logdir2] -c [container_name] -a [archive_after] -d [delete_after] -p [retention_days]'
93
94 import os
95-import logging
96 import sys
97 import datetime
98
99 import json
100 import swiftclient
101-from archive import CloudStorage, main, Status
102-
103-log = logging.getLogger()
104+from archive import CloudStorage, main, initialise_logger, Status
105
106
107 class SwiftCloudStorage(CloudStorage):
108@@ -242,4 +239,5 @@ class SwiftCloudStorage(CloudStorage):
109
110
111 if __name__ == "__main__":
112+ log = initialise_logger()
113 sys.exit(main(SwiftCloudStorage))
114diff --git a/files/archive.py b/files/archive.py
115index 7ffd4e0..e47b524 100644
116--- a/files/archive.py
117+++ b/files/archive.py
118@@ -22,7 +22,18 @@ import time
119
120 from preprocessor import get_preprocessor
121
122-log = logging.getLogger()
123+
124+def initialise_logger():
125+ lg = logging.getLogger()
126+ lg.setLevel(logging.DEBUG)
127+ fh = logging.FileHandler('/var/log/container-log-archive.log')
128+ ch = logging.StreamHandler()
129+ lg.addHandler(fh)
130+ lg.addHandler(ch)
131+ return lg
132+
133+
134+log = initialise_logger()
135
136
137 class Status:
138diff --git a/files/container-log-archive.logrotate b/files/container-log-archive.logrotate
139new file mode 100644
140index 0000000..5dd38b0
141--- /dev/null
142+++ b/files/container-log-archive.logrotate
143@@ -0,0 +1,12 @@
144+#-------------------------------------------------#
145+# This file is Juju managed - do not edit by hand #
146+#-------------------------------------------------#
147+/var/log/container-log-archive.log {
148+ rotate 7
149+ daily
150+ dateext
151+ compress
152+ notifempty
153+ missingok
154+ create 0644 root root
155+}
156diff --git a/hooks/hooks.py b/hooks/hooks.py
157index 45b5254..0d36c77 100755
158--- a/hooks/hooks.py
159+++ b/hooks/hooks.py
160@@ -8,6 +8,7 @@ import random
161 import os
162 import stat
163 import os.path
164+import shutil
165 import socket
166 import time
167 sys.path.insert(0, os.path.join(os.environ['CHARM_DIR'], 'lib'))
168@@ -261,6 +262,17 @@ def deconfigure_nrpe():
169 service_reload("nagios-nrpe-server")
170
171
172+def configure_logrotate():
173+ logrotate_etcdir = "/etc/logrotate.d"
174+ logrotate_file = "files/container-log-archive.logrotate"
175+ logrotate_path = os.path.join(logrotate_etcdir, "container-log-archive")
176+ try:
177+ shutil.copyfile(logrotate_file, logrotate_path)
178+ except OSError as e:
179+ log("CHARM: Failed to copy logrotate file {} to {}".format(logrotate_file, logrotate_path))
180+ raise(e)
181+
182+
183 def remove_legacy_files():
184 """ Previous versions of the charm didn't use the service_name in the
185 various system files. This removes those older files if they exist
186@@ -305,6 +317,7 @@ def config_changed():
187 configure_container_creds()
188 configure_sudo()
189 configure_cronjob()
190+ configure_logrotate()
191 configure_nrpe()
192 remove_legacy_files()
193

Subscribers

People subscribed via source and target branches