|
| 1 | +# Send Platform.sh logs to Logz.io |
| 2 | + |
| 3 | +Platform.sh log files are stored on disk (in /var/log) and trimmed |
| 4 | +to 100 MB automatically. For busy environments this means that logs |
| 5 | +may only contain entries for the last 24 hours or even less |
| 6 | +depending on the volume of log entries an environment is generating. |
| 7 | +By shipping logs to a centralised logging service like Logz.io, it |
| 8 | +makes it possible to retain logs for a longer period as well as |
| 9 | +having nice tools to search through the logs. |
| 10 | + |
| 11 | +Platform.sh grid hosted environments currently do not support |
| 12 | +installation of logging services or daemons. For example, syslog nor |
| 13 | +rsyslog are available. To get around this, we can use cron to run a |
| 14 | +script which periodically uploads batches of log entries using cURL. |
| 15 | + |
| 16 | +This solution is loosely based on |
| 17 | +[this solution for uploading logs to Amazon S3 storage](https://gitlab.com/contextualcode/platformsh-store-logs-at-s3/). |
| 18 | + |
| 19 | +The solution only ever uploads the newest |
| 20 | +log entries rather than uploading an entire log file. This is |
| 21 | +necessary because log management solutions set a maximum limit on |
| 22 | +the size of files that can be uploaded in a single request. |
| 23 | + |
| 24 | +## 1. Add nicsdru-logging repo to the project root using `git subtree` |
| 25 | + |
| 26 | +[git subtree](https://www.atlassian.com/git/tutorials/git-subtree) lets you nest one repository inside another as a |
| 27 | +sub-directory. |
| 28 | + |
| 29 | +In your local copy of a platform hosted Drupal project, |
| 30 | +run the following command in the project root (which should contain |
| 31 | +the `.platform/` directory and the `.platform.app.yaml` file): |
| 32 | + |
| 33 | +```shell |
| 34 | +git subtree add --prefix nicsdru-logging [email protected]:dof-dss/nicsdru-logging.git main --squash |
| 35 | +``` |
| 36 | + |
| 37 | +This will generate a couple of new commits into your project repo. |
| 38 | + |
| 39 | +### Updating the repo |
| 40 | + |
| 41 | +If you want to later update to the latest version of the nicsdru-logging |
| 42 | +repo, run the following command in the project root: |
| 43 | + |
| 44 | +```shell |
| 45 | +git subtree pull --prefix nicsdru-logging [email protected]:dof-dss/nicsdru-logging.git main --squash |
| 46 | +``` |
| 47 | + |
| 48 | +## 2. Copy example.cronjob.sh to cronjob.sh |
| 49 | + |
| 50 | +Copy `nicsdru-logging/scripts/example.cronjob.sh` into the project root renaming to `cronjob.sh`. |
| 51 | + |
| 52 | +```shell |
| 53 | +cp nicsdru-logging/scripts/example.cronjob.sh cronjob.sh |
| 54 | +``` |
| 55 | + |
| 56 | +The directory structure for a typical dof-dss D9 project should |
| 57 | +end up looking something like this: |
| 58 | + |
| 59 | +``` |
| 60 | +├── .circleci/ |
| 61 | +├── .platform/ |
| 62 | +│ ├── solr_config |
| 63 | +│ ├── routes.yaml |
| 64 | +│ └── services.yaml |
| 65 | +├── config/ |
| 66 | +├── drush/ |
| 67 | +├── nicsdru-logging/ |
| 68 | +│ └── scripts/ |
| 69 | +│ │ ├── example.cronjob.sh |
| 70 | +│ │ └── shiplog.sh |
| 71 | +│ └── README.md |
| 72 | +├── private/ |
| 73 | +├── vendor/ |
| 74 | +├── web/ |
| 75 | +├── .platform.app.yaml |
| 76 | +├── composer.json |
| 77 | +├── composer.lock |
| 78 | +├── cronjob.sh |
| 79 | +├── LICENSE |
| 80 | +├── phpcs.sh |
| 81 | +└── README.md |
| 82 | +``` |
| 83 | + |
| 84 | + |
| 85 | +## 3. Make the new `cronjob.sh` file executable |
| 86 | + |
| 87 | +```shell |
| 88 | +chmod +x cronjob.sh |
| 89 | +``` |
| 90 | + |
| 91 | +## 4. Edit `cronjob.sh` to configure log files to be shipped |
| 92 | + |
| 93 | +`cronjob.sh` contains calls to `shiplog.sh` to ship specifc logs in the following format: |
| 94 | + |
| 95 | +```shell |
| 96 | +/bin/bash /app/nicsdru-logging/scripts/shiplog.sh "LOG_NAME" "LOG_PATH" "LOG_DATE_PATTERN" "LOG_TYPE" |
| 97 | +``` |
| 98 | + |
| 99 | +Where: |
| 100 | + |
| 101 | +- `LOG_NAME` is unique name of a log (e.g "access"). NO SPACES! |
| 102 | +- `LOG_PATH` is the full path to source log file to be shipped (e.g. "/var/log/access.log") |
| 103 | +- `LOG_DATE_PATTERN` is a date formatted to match datetime stamps in individual log entries |
| 104 | +(e.g. "$(date +%d/%b/%Y:)") |
| 105 | +- `LOG_TYPE` identifies [the type of log file to Logz.io](https://docs.logz.io/user-guide/log-shipping/built-in-log-types.html) (e.g. "nginx_access"). NO SPACES! |
| 106 | + |
| 107 | +For example, the following line ships the /var/log/access.log generated by nginx. |
| 108 | + |
| 109 | +```shell |
| 110 | +/bin/bash /app/nicsdru-logging/scripts/shiplog.sh "access" "/var/log/access.log" "$(date +%d/%b/%Y:)" "nginx_access" |
| 111 | +``` |
| 112 | + |
| 113 | +*For D9 sites*, with the [filelog contrib module](https://www.drupal.org/project/filelog) |
| 114 | +installed, ensure the module is configured to write to logs to `/app/log` and then |
| 115 | +uncomment or add the following line to `cronjob.sh`: |
| 116 | + |
| 117 | +```shell |
| 118 | +/bin/bash /app/nicsdru-logging/scripts/shiplog.sh "drupal" "/app/log/drupal.log" "$(date +'%a, %d/%m/%Y -')" "drupal" |
| 119 | +``` |
| 120 | + |
| 121 | +(Note the LOG_TYPE specified is "drupal" which is a custom log type we have asked |
| 122 | +Logz.io to configure for us.) |
| 123 | + |
| 124 | +*For D9 multisite projects* using the [filelog contrib module](https://www.drupal.org/project/filelog), |
| 125 | +ensure the module is configured on each site to write to logs to a sub-directory of |
| 126 | +`/app/log` - for example `/app/log/sitename` and then add a line like the |
| 127 | +following to ship the drupal.log for that specific site: |
| 128 | + |
| 129 | +```shell |
| 130 | +/bin/bash /app/nicsdru-logging/scripts/shiplog.sh "drupal-sitename" "/app/log/sitename/drupal.log" "$(date +'%a, %d/%m/%Y -')" "drupal" |
| 131 | +``` |
| 132 | + |
| 133 | +## 5. Create a writable mount in .platform.app.yaml for storing logs |
| 134 | + |
| 135 | +The normal log directory `/var/log` is not writeable. So we create |
| 136 | +a writeable mount in `.platform.app.yaml` for the shiplog script to write logs to: |
| 137 | + |
| 138 | +```yaml |
| 139 | +mounts: |
| 140 | + '/log': |
| 141 | + source: local |
| 142 | + source_path: 'log' |
| 143 | +``` |
| 144 | +
|
| 145 | +## 6. Add cron job in .platform.app.yaml |
| 146 | +
|
| 147 | +```yaml |
| 148 | +crons: |
| 149 | + # Log shipping cron. |
| 150 | + logging: |
| 151 | + spec: '*/5 * * * *' |
| 152 | + commands: |
| 153 | + start: '/bin/bash /app/cronjob.sh' |
| 154 | + shutdown_timeout: 290 |
| 155 | +``` |
| 156 | +
|
| 157 | +## 7. Create LOGZ_TOKEN and LOGZ_URL environment variables |
| 158 | +
|
| 159 | +Obtain an account token from Logz.io. Then create a project |
| 160 | +environment variable LOGZ_TOKEN to store the token securely. |
| 161 | +
|
| 162 | +```shell |
| 163 | +platform variable:create -l environment -e [ENVIRONMENT_NAME] --prefix env: --name LOGZ_TOKEN --value '[LOGZ_IO_TOKEN]' --visible-runtime true --inheritable false --sensitive true |
| 164 | +``` |
| 165 | +
|
| 166 | +**Optionally**, set the "listener URL" for sending logs to |
| 167 | +Logz.io. By default the URL is `https://listener-uk.logz.io:8022` |
| 168 | +You can override this by setting the project environment variable |
| 169 | +LOGZ_URL. The URL should begin with "https://" with no end |
| 170 | +forward slash. |
| 171 | + |
| 172 | +```shell |
| 173 | +platform variable:create -l environment -e [ENVIRONMENT_NAME] --prefix env: --name LOGZ_URL --value 'https://listener-uk.logz.io:8022' --visible-runtime true --inheritable true --sensitive false |
| 174 | +``` |
| 175 | + |
| 176 | +## 8. Deploy to Platform.sh and verify logs are being shipped |
| 177 | + |
| 178 | +Cron will run cronjob.sh to ship latest log entries to Logz.io. |
| 179 | +You should start to see log entries arrive in Logz.io's Kibana |
| 180 | +interface. If you don't, there are a number of things to check. |
| 181 | + |
| 182 | +### Check cron is running |
| 183 | + |
| 184 | +Run this platform CLI command |
| 185 | +```shell |
| 186 | +$ platform activity:list |
| 187 | +``` |
| 188 | +And gives output like this ... |
| 189 | + |
| 190 | +```shell |
| 191 | +Activities on the project NIDirect-D8 (wcjm3mu7bacfm), environment logz (type: development): |
| 192 | ++---------------+---------------------------+----------------------------------+----------+----------+---------+ |
| 193 | +| ID | Created | Description | Progress | State | Result | |
| 194 | ++---------------+---------------------------+----------------------------------+----------+----------+---------+ |
| 195 | +| cc3s4jkfkb5ke | 2022-05-11T16:01:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 196 | +| yado3ie3w4rqu | 2022-05-11T15:56:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 197 | +| tuckl2vxeecss | 2022-05-11T15:51:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 198 | +| z7jx33erazc3a | 2022-05-11T15:46:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 199 | +| iq43xajukyn5e | 2022-05-11T15:41:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 200 | +| q64gu6qqiw6s4 | 2022-05-11T15:36:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 201 | +| dc2hifwrzgm6y | 2022-05-11T15:31:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 202 | +| 3l737f5rmp6m4 | 2022-05-11T15:26:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 203 | +| kuydxo23aeczy | 2022-05-11T15:21:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 204 | +| 6jnwgge2ufivk | 2022-05-11T15:16:27+00:00 | Platform.sh Bot ran cron logging | 100% | complete | success | |
| 205 | ++---------------+---------------------------+----------------------------------+----------+----------+---------+ |
| 206 | +``` |
| 207 | + |
| 208 | +### SSH onto the environment and check logs are being generated in the `/app/log` mount |
| 209 | + |
| 210 | +The logging scripts create and rotate their own log files in the `/app/log` |
| 211 | +mounted directory. |
| 212 | + |
| 213 | +If the project is a D9 project with the filelog module enabled and you |
| 214 | +have configured `cronjob.sh` to ship the access and drupal logs (as described above), |
| 215 | +then you should see something like the following in `/app/log`: |
| 216 | + |
| 217 | +```shell |
| 218 | + |
| 219 | + |
| 220 | +total 88 |
| 221 | +drwxr-xr-x 2 web web 4096 May 11 16:26 . |
| 222 | +drwxr-xr-x 18 web web 514 May 11 12:21 .. |
| 223 | +-r--r--r-- 1 web web 686 Apr 13 16:41 .htaccess |
| 224 | +-rw-r--r-- 1 web web 15743 May 11 12:31 2022-05-11-access.log |
| 225 | +-rw-r--r-- 1 web web 8038 May 11 12:31 2022-05-11-drupal.log |
| 226 | +-rw-rw-r-- 1 web web 51256 May 11 12:29 drupal.log |
| 227 | + |
| 228 | +``` |
| 229 | + |
| 230 | +The logs prefixed with a YYYY-MM-DD format date are created by `shiplog.sh` |
| 231 | +and rotated daily. The drupal.log is created by the filelog module which |
| 232 | +can also be rotated daily (depending on module settings). |
| 233 | + |
| 234 | +### If all else fails, run `cronjob.sh` from the command-line and check the output |
| 235 | + |
| 236 | +```shell |
| 237 | +/bin/bash /app/cronjob.sh |
| 238 | +``` |
| 239 | + |
| 240 | +Healthy output looks like this ... |
| 241 | + |
| 242 | +```shell |
| 243 | +[email protected]:~$ /bin/bash /app/cronjob.sh |
| 244 | +Shipping log ... |
| 245 | +Shipping today's newest log entries from /var/log/access.log ... |
| 246 | +Creating 2022-05-11-access.log ... |
| 247 | +2022-05-11-access.log already exists |
| 248 | +Deleting 2022-05-10-access.log ... |
| 249 | +2022-05-10-access.log does not exist |
| 250 | +Retrieving latest log entries from /var/log/access.log and writing to 2022-05-11-access.log |
| 251 | +Shipping latest log entries from 2022-05-11-access.log to Logz.io using cURL |
| 252 | +Log shipping succeeded with: 200 |
| 253 | +Shipping log ... |
| 254 | +Shipping today's newest log entries from /app/log/drupal.log ... |
| 255 | +Creating 2022-05-11-drupal.log ... |
| 256 | +2022-05-11-drupal.log already exists |
| 257 | +Deleting 2022-05-10-drupal.log ... |
| 258 | +2022-05-10-drupal.log does not exist |
| 259 | +Retrieving latest log entries from /app/log/drupal.log and writing to 2022-05-11-drupal.log |
| 260 | +Shipping latest log entries from 2022-05-11-drupal.log to Logz.io using cURL |
| 261 | +Log shipping succeeded with: 200 |
| 262 | +``` |
| 263 | + |
0 commit comments