Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ENABLE_JSON_LOGGING #216

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ RUN curl -sL -o go-cron.tar.gz https://github.com/djmaze/go-cron/archive/v${GO_C
#
FROM alpine:3.20

RUN apk add --update --no-cache ca-certificates fuse nfs-utils openssh tzdata bash curl docker-cli gzip tini
RUN apk add --update --no-cache ca-certificates jq fuse nfs-utils openssh tzdata bash curl docker-cli gzip tini

ENV RESTIC_REPOSITORY /mnt/restic

COPY --from=builder /usr/local/bin/* /usr/local/bin/
COPY backup prune check /usr/local/bin/
COPY backup prune check notify /usr/local/bin/
COPY entrypoint /

ENTRYPOINT ["/sbin/tini", "--", "/entrypoint"]
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ _Note: `BACKUP_CRON`, `PRUNE_CRON` and `CHECK_CRON` are mutually exclusive._
- `TZ` - Optional. Set your timezone for the correct cron execution time.
- `SKIP_INIT` - Skip initialization of the restic repository, even if it can not be accessed.
- `SKIP_INIT_CHECK`- Do not fail, if initialization of the restic repository fails for whatever reason.

- `ENABLE_JSON_LOGGING` = Converts Restic's standard output to JSON format. This allows users to leverage tools like `jq` to extract specific fields from the metadata. Additionally, it supports calling external scripts for further processing, such as [executing commands after a backup](#execute-commands-after-backup). For example:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this should also document that the LOG_FILE env variable is set for the commands to be used.

```sh
notify "discord://,telegram://,slack://" "http://apprise:8000/notify"
```
### Using the `rclone` repository type

In order to use the `rclone` repository type, you need to prepare an `rclone.conf` file and mount it inside the container at `/run/secrets/rclone.conf`.
Expand Down
11 changes: 9 additions & 2 deletions backup
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
set -eo pipefail

LOG_FILE=""
function run_commands {
COMMANDS=$1
while IFS= read -r cmd; do echo "$cmd" && eval "$cmd" ; done < <(printf '%s\n' "$COMMANDS")
Expand Down Expand Up @@ -62,7 +62,14 @@ start=$(date +%s)
echo Starting Backup at $(date +"%Y-%m-%d %H:%M:%S")

set +e
restic --repo="${RESTIC_REPOSITORY}" backup "${backup_args[@]}" "${tag_options[@]}" "${backup_sources[@]}"
if [ "$(check_bool "${ENABLE_JSON_LOGGING:-}")" = "true" ]; then
# Set LOG_FILE
LOG_FILE="/var/log/restic_backup_$(date +%Y%m%d_%H%M%S).json"
export LOG_FILE
restic --repo="${RESTIC_REPOSITORY}" backup "${backup_args[@]}" "${tag_options[@]}" "${backup_sources[@]}" --json | tee "$LOG_FILE"
else
restic --repo="${RESTIC_REPOSITORY}" backup "${backup_args[@]}" "${tag_options[@]}" "${backup_sources[@]}"
fi
rc=$?
set -e

Expand Down
72 changes: 72 additions & 0 deletions docker-compose.contributing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
version: "3.3"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why you added this file and what the name is exactly about? IMO we can just remove this.


services:
backup:
build:
context: .
hostname: docker
restart: unless-stopped
environment:
RUN_ON_STARTUP: "true"
BACKUP_CRON: "0 30 3 * * *"
RESTIC_PASSWORD: supersecret
RESTIC_BACKUP_SOURCES: /mnt/volumes
ENABLE_JSON_LOGGING: "true"
POST_COMMANDS_EXIT: |-
notify "discord://" "http://apprise:8080/notify"
RESTIC_BACKUP_ARGS: >-
--tag docker-volumes
--exclude some-folder/cache
--exclude another-folder/with\ space
--exclude *.tmp
RESTIC_FORGET_ARGS: >-
--keep-last 10
--keep-daily 7
--keep-weekly 5
--keep-monthly 12
B2_ACCOUNT_ID: xxxxxxx
B2_ACCOUNT_KEY: yyyyyyyy
TZ: Europe/Berlin
volumes:
- /var/lib/docker/volumes:/mnt/volumes:ro

prune:
build:
context: .
hostname: docker
restart: unless-stopped
environment:
SKIP_INIT: "true"
RUN_ON_STARTUP: "true"
PRUNE_CRON: "0 0 4 * * *"
RESTIC_REPOSITORY: b2:my-repo:/restic
RESTIC_PASSWORD: supersecret
B2_ACCOUNT_ID: xxxxxxx
B2_ACCOUNT_KEY: yyyyyyyy
TZ: Europe/Berlin

check:
build:
context: .
hostname: docker
restart: unless-stopped
environment:
SKIP_INIT: "true"
RUN_ON_STARTUP: "false"
CHECK_CRON: "0 15 5 * * *"
RESTIC_CHECK_ARGS: >-
--read-data-subset=10%
RESTIC_REPOSITORY: b2:my-repo:/restic
RESTIC_PASSWORD: supersecret
B2_ACCOUNT_ID: xxxxxxx
B2_ACCOUNT_KEY: yyyyyyyy
TZ: Europe/Berlin

apprise:
image: caronc/apprise:latest
hostname: docker
restart: unless-stopped
environment:
TZ: Europe/Berlin
ports:
- 8080:8080
83 changes: 83 additions & 0 deletions notify
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/bin/bash
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This functionality should also be tested. I will add a test.

set -eo pipefail
# Define the log file variable (make sure to replace this with the actual log file path)
APPRISE_SERVICES_URL=$1
APPRISE_ENDPOINT=$2
# Check if LOG_FILE is set
if [ -z "$LOG_FILE" ]; then
echo "LOG_FILE is not set"
exit 1
fi

# Perform the notification using LOG_FILE
echo "Notifying about the log file: $LOG_FILE"

# Extract information from the log file
extract_field() {
jq -r "select(.message_type == \"$1\") | .$2" < "$LOG_FILE"
}

# Extract summary information
files_new=$(extract_field "summary" "files_new")
files_changed=$(extract_field "summary" "files_changed")
files_unmodified=$(extract_field "summary" "files_unmodified")
dirs_new=$(extract_field "summary" "dirs_new")
dirs_changed=$(extract_field "summary" "dirs_changed")
dirs_unmodified=$(extract_field "summary" "dirs_unmodified")
data_blobs=$(extract_field "summary" "data_blobs")
tree_blobs=$(extract_field "summary" "tree_blobs")
data_added=$(extract_field "summary" "data_added")
total_files_processed=$(extract_field "summary" "total_files_processed")
total_bytes_processed=$(extract_field "summary" "total_bytes_processed")
total_duration=$(extract_field "summary" "total_duration")
snapshot_id=$(extract_field "summary" "snapshot_id")

# Extract error information
error_message=$(extract_field "error" "error")
error_during=$(extract_field "error" "during")
error_item=$(extract_field "error" "item")

# Handle cases where error and verbose status might be empty
if [[ -z "$error_message" ]]; then
error_section="No errors reported."
else
error_section="Error encountered:
- Message: $error_message
- During: $error_during
- Item: $error_item"
fi

# Create a message with status, summary, error, and verbose details
MESSAGE="Restic Backup Report
Summary:
- Files New: $files_new
- Files Changed: $files_changed
- Files Unmodified: $files_unmodified
- Dirs New: $dirs_new
- Dirs Changed: $dirs_changed
- Dirs Unmodified: $dirs_unmodified
- Data Blobs: $data_blobs
- Tree Blobs: $tree_blobs
- Data Added: $data_added bytes
- Total Files Processed: $total_files_processed
- Total Bytes Processed: $total_bytes_processed
- Total Duration: $total_duration seconds
- Snapshot ID: $snapshot_id
Errors:
$error_section"

# Print the message to the console (for debugging purposes)
echo "$MESSAGE"

# Create the JSON payload for Apprise
PAYLOAD=$(jq -n \
--arg urls "$APPRISE_SERVICES_URL" \
--arg body "$MESSAGE" \
'{
"urls": $urls,
"body": $body
}'
)

# Send the payload using curl
curl -X POST "$APPRISE_ENDPOINT" -H 'Content-Type: application/json' -d "$PAYLOAD"