Skip to content

Commit c020b34

Browse files
authored
Merge pull request #17 from bcgov/fix/fileChangeTimeallback
feat: document and use change time instead of birth time with rotated…
2 parents 0f1cd75 + eb1b9ae commit c020b34

File tree

6 files changed

+95
-27
lines changed

6 files changed

+95
-27
lines changed

README.md

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,76 @@
11
# NR Object Storage Rotate
22

3-
A Sidecar container for rotating, compressing and backing up log files to Object Storage.
3+
A sidecar container for rotating, compressing and backing up log files to object storage.
44

55
## Architecture
66

77
The container is a Typescipt Node.js application that uses a SQLite database to track the files as they are stepped through each stage. The stages run independantely on a configurable cron schedule.
88

9-
COnfigurable environment variables will be shown like `ENV_VAR` below.
9+
Configurable environment variables will be shown like `ENV_VAR` below.
1010

1111
### Stage 0 - Log file generated
1212

1313
The application logs to disk. Files to be rotated must end with `LOGROTATE_SUFFIX`.
1414

1515
### Stage 1 - Rotate log file
1616

17-
The environment variable `CRON_ROTATE` is used to schedule the rotation of the files. Matching files are rotated by renaming the files to append a timestamp.
17+
The environment variable `CRON_ROTATE` is used to schedule the rotation of the files. The `LOGROTATE_DIRECTORY` is examined for files with the `LOGROTATE_SUFFIX` (default: log).
1818

1919
If any files are rotated then, optionally, `LOGROTATE_POSTROTATE_COMMAND` is called. It can be necessary to signal the application that the rotation occurred so it can open a new file.
2020

21+
Rotated files are appended with the file's change date and the current UTC timestamp. See: https://nodejs.org/api/fs.html#stat-time-values
22+
2123
### Stage 2 - Compress log file
2224

23-
The environment variable `CRON_COMPRESS` is used to schedule the compression of the rotated files.
25+
The environment variable `CRON_COMPRESS` is used to schedule the compression of the rotated files. The each file is compressed into a 'tgz' archive.
26+
27+
This stage can run frequently with little cost.
2428

2529
### Stage 3 - Backup log file
2630

27-
The environment variable `CRON_BACKUP` is used to schedule the back of the compressed files to Object Storage. To identify the source, a prefix can be configured by setting `OBJECT_STORAGE_FILENAME_PREFIX`. Any arbitrary metadata can be set by setting `OBJECT_STORAGE_METADATA` to be a key/value JSON string.
31+
The environment variable `CRON_BACKUP` is used to schedule the backup of the compressed files to object storage.
32+
33+
If you have massive files or slow connectivity, increase the cron settings period. Otherwise, this stage can run frequently with little cost.
34+
35+
Any arbitrary metadata can be set by setting `OBJECT_STORAGE_METADATA` to be a key/value JSON string.
36+
37+
If you are sending similarly named files from multiple sources (OpenShift/Kubernetes nodes), then it is recommended that you set `OBJECT_STORAGE_FILENAME_PREFIX` to identify the source and avoid collisions.
38+
39+
If you set `OBJECT_STORAGE_ENABLED` to anything but the default of 'true' then the backup to object storage is skipped.
40+
41+
#### Required Configuration
42+
43+
The following are the environment variables that need to be set for the tool to use object storage.
44+
45+
* `OBJECT_STORAGE_END_POINT`
46+
* `OBJECT_STORAGE_ACCESS_KEY`
47+
* `OBJECT_STORAGE_BUCKET`
48+
* `OBJECT_STORAGE_SECRET_KEY`
2849

2950
### Stage 4 - Janitor
3051

3152
The environment variable `CRON_JANITOR` is used to schedule the janitor which removes files after they have been backed up. The number of log files to retain can be configured by setting `JANITOR_COPIES`.
3253

54+
This stage can run frequently with little cost.
55+
56+
## SQLite Database
57+
58+
The SQLite database can be viewed by running a command like:
59+
60+
`sqlite3 ./logs/cron.db 'select * from logs'`
61+
62+
### Missing Files
63+
64+
Prior to each stage, the database and the file system are compared. Any file missing from the file system will be logged and deleted from the database.
65+
66+
### Moving the Log Directory
67+
68+
If you are moving the location of the files, you will need to update the path column of the logs table in the SQLite database. As well, you should take care not to trigger the missing files process.
69+
70+
## Object Storage Lifecycle Policies
71+
72+
This tool does not manage the lifecycle policies for the bucket the data is uploaded to. Please refer to the documentation for the object storage service you are using to setup a bucket lifecycle.
73+
3374
## Rotation Setups
3475

3576
The default rotates files once every day. If you change the cron to run hourly, then it will rotate hourly. The minimum file size environment variable can be set to skip rotating files until they grow larger enough. The age maximum can ensure files don't remain on the server indefinitely.
@@ -42,6 +83,28 @@ The minimum file size (in bytes) before the file is rotated. Empty files are alw
4283

4384
The maximum age (in milliseconds) of a file before it is rotated (even if the minimum file size is not met). Values less than 1 are ignored. Default: 0
4485

86+
### Integration with NR Broker
87+
88+
The backup stage can read credentials from NR Vault and report the backed up files to NR Broker if the NR Broker environment variables (`BROKER_*`) are set.
89+
90+
The required environment variables to set are:
91+
92+
* `BROKER_JWT`
93+
* `BROKER_PROJECT`
94+
* `BROKER_SERVICE`
95+
* `BROKER_ENVIRONMENT`
96+
97+
This will set it up to read secrets from the standard key/value credential location in NR Vault for the service. The `VAULT_CRED_PATH_SUFFIX` variable can be set to include a path from the service's root.
98+
99+
The key/value document read from NR Vault will do nothing by default. The `VAULT_CRED_KEYS_*` variables replace the equivalent `OBJECT_STORAGE_*` with the value of the key read from Vault.
100+
101+
* VaultDoc[`VAULT_CRED_KEYS_END_POINT`] -> `OBJECT_STORAGE_END_POINT`
102+
* VaultDoc[`VAULT_CRED_KEYS_ACCESS_KEY`] -> `OBJECT_STORAGE_ACCESS_KEY`
103+
* VaultDoc[`VAULT_CRED_KEYS_SECRET_KEY`] -> `OBJECT_STORAGE_SECRET_KEY`
104+
* VaultDoc[`VAULT_CRED_KEYS_BUCKET`] -> `OBJECT_STORAGE_BUCKET`
105+
106+
You are free to set as many (or as few) of the `VAULT_CRED_KEYS_*`.
107+
45108
## Local Testing
46109

47110
1. Copy `setenv-tmpl.sh` to `setenv-local.sh`.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nr-objectstore-rotate",
3-
"version": "2.0.0",
3+
"version": "2.0.2",
44
"description": "Sidecar for rotating log files to objectstore",
55
"main": "index.js",
66
"scripts": {

setenv-tmpl.sh

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
# export CRON_ROTATE="59 23 * * *"
22
# export CRON_COMPRESS="*/10 * * * *"
3-
# export CRON_BACKUP="*/10 * * * *"
3+
# export CRON_BACKUP="*/20 * * * *"
44
# export CRON_JANITOR="*/10 * * * *"
55

66
export LOGROTATE_DIRECTORY="/logs"
7-
export JANITOR_COPIES=3
8-
# export LOGROTATE_SUFFIX="log"
9-
# export LOGROTATE_POSTROTATE_COMMAND=""
107
# export LOGROTATE_STATUSFILE="cron.db"
8+
# export LOGROTATE_FILESIZE_MIN="1024"
9+
# export LOGROTATE_AGE_MAX="86400"
10+
# export LOGROTATE_SUFFIX="log"
11+
# export LOGROTATE_POSTROTATE_COMMAND="echo 'rotated!'"
12+
export JANITOR_COPIES=3
1113

1214
# Required
1315
# export OBJECT_STORAGE_ENABLED="true"
1416
export OBJECT_STORAGE_END_POINT=""
1517
export OBJECT_STORAGE_ACCESS_KEY=""
16-
export OBJECT_STORAGE_BUCKET=""
1718
export OBJECT_STORAGE_SECRET_KEY=""
19+
export OBJECT_STORAGE_BUCKET=""
20+
# export OBJECT_STORAGE_FILENAME_PREFIX=""
1821

19-
# Set BROKER_JWT to use Broker and Vault
20-
# export BROKER_JWT=""
22+
# Set BROKER_* and VAULT_* values to use NR Broker and Vault
2123
# export BROKER_URL=""
24+
# export BROKER_JWT=""
2225
# export BROKER_USER=""
23-
export BROKER_PROJECT=""
24-
export BROKER_SERVICE=""
25-
export BROKER_ENVIRONMENT=""
26+
# export BROKER_PROJECT=""
27+
# export BROKER_SERVICE=""
28+
# export BROKER_ENVIRONMENT=""
2629

2730
# export VAULT_CRED_PATH=""
2831
# If VAULT_CRED_KEYS_* is set, the value from VAULT_CRED_PATH replaces OBJECT_STORAGE_*

src/constants.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export const CRON_ROTATE = process.env.CRON_ROTATE ?? '59 23 * * *';
22
export const CRON_COMPRESS = process.env.CRON_COMPRESS ?? '*/10 * * * *';
3-
export const CRON_BACKUP = process.env.CRON_BACKUP ?? '*/10 * * * *';
3+
export const CRON_BACKUP = process.env.CRON_BACKUP ?? '*/20 * * * *';
44
export const CRON_JANITOR = process.env.CRON_JANITOR ?? '*/10 * * * *';
55

66
export const LOGROTATE_DIRECTORY = process.env.LOGROTATE_DIRECTORY ?? 'logs';
@@ -30,9 +30,9 @@ export const OBJECT_STORAGE_END_POINT =
3030
process.env.OBJECT_STORAGE_END_POINT ?? '';
3131
export const OBJECT_STORAGE_ACCESS_KEY =
3232
process.env.OBJECT_STORAGE_ACCESS_KEY ?? '';
33-
export const OBJECT_STORAGE_BUCKET = process.env.OBJECT_STORAGE_BUCKET ?? '';
3433
export const OBJECT_STORAGE_SECRET_KEY =
3534
process.env.OBJECT_STORAGE_SECRET_KEY ?? '';
35+
export const OBJECT_STORAGE_BUCKET = process.env.OBJECT_STORAGE_BUCKET ?? '';
3636
export const OBJECT_STORAGE_FILENAME_PREFIX = process.env
3737
.OBJECT_STORAGE_FILENAME_PREFIX
3838
? `${process.env.OBJECT_STORAGE_FILENAME_PREFIX}.`
@@ -63,7 +63,9 @@ export const VAULT_CRED_PATH =
6363
`apps/data/${
6464
ENV_LONG_TO_SHORT[BROKER_ENVIRONMENT]
6565
}/${BROKER_PROJECT}/${BROKER_SERVICE}${
66-
process.env.VAULT_CRED_PATH_SUFFIX ? process.env.VAULT_CRED_PATH_SUFFIX : ''
66+
process.env.VAULT_CRED_PATH_SUFFIX
67+
? `/${process.env.VAULT_CRED_PATH_SUFFIX}`
68+
: ''
6769
}`;
6870
// If VAULT_CRED_KEYS_* is set, the value from VAULT_CRED_PATH replaces OBJECT_STORAGE_*
6971
// Example: VAULT_CRED_KEYS_SECRET_KEY="secret_key" would replace OBJECT_STORAGE_SECRET_KEY
@@ -72,9 +74,9 @@ export const VAULT_CRED_KEYS_END_POINT =
7274
process.env.VAULT_CRED_KEYS_END_POINT ?? '';
7375
export const VAULT_CRED_KEYS_ACCESS_KEY =
7476
process.env.VAULT_CRED_KEYS_ACCESS_KEY ?? '';
75-
export const VAULT_CRED_KEYS_BUCKET = process.env.VAULT_CRED_KEYS_BUCKET ?? '';
7677
export const VAULT_CRED_KEYS_SECRET_KEY =
7778
process.env.VAULT_CRED_KEYS_SECRET_KEY ?? '';
79+
export const VAULT_CRED_KEYS_BUCKET = process.env.VAULT_CRED_KEYS_BUCKET ?? '';
7880
export const VAULT_URL =
7981
process.env.VAULT_URL ?? 'https://knox.io.nrs.gov.bc.ca/';
8082

src/cron/rotate.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,16 @@ async function rotateLog(db: DatabaseService, file: string) {
7070
await db.addLog(file, newPath);
7171
}
7272

73-
// Append date to logname
73+
// Append last change time and current timestamp to logname
7474
export function newLogName(file: string) {
75-
const date = createdDate(path.join(LOGROTATE_DIRECTORY, file));
75+
const date = changeDate(path.join(LOGROTATE_DIRECTORY, file));
7676
return `${file}.${date.getUTCFullYear()}${String(date.getUTCMonth()).padStart(
7777
2,
7878
'0',
7979
)}${String(date.getUTCDate()).padStart(2, '0')}.${new Date().valueOf()}`;
8080
}
8181

82-
function createdDate(filePath: string) {
83-
const { birthtime } = fs.statSync(filePath);
84-
return birthtime;
82+
function changeDate(filePath: string) {
83+
const { ctime } = fs.statSync(filePath);
84+
return ctime;
8585
}

0 commit comments

Comments
 (0)