22
33# Initialize logging with timestamp
44log () {
5- echo " [$( date ' +%Y-%m-%d %H:%M:%S' ) ] $1 "
5+ local level=" ${1:- INFO} "
6+ local message=" $2 "
7+ echo " [$( date ' +%Y-%m-%d %H:%M:%S' ) ] ${level} : ${message} "
68}
79
8- # Generate UUID v4
9- generate_uuid () {
10- if [ -f /proc/sys/kernel/random/uuid ]; then
11- cat /proc/sys/kernel/random/uuid
12- else
13- date +%s%N | sha256sum | head -c 32
14- fi
15- }
16-
17- # Parse Sentry DSN
18- parse_sentry_dsn () {
19- local dsn=$1
20- # Extract components using basic string manipulation
21- local project_id=$( echo " $dsn " | sed ' s/.*\///' )
22- local key=$( echo " $dsn " | sed ' s|https://||' | sed ' s/@.*//' )
23- local host=$( echo " $dsn " | sed ' s|https://[^@]*@||' | sed ' s|/.*||' )
24- echo " $project_id |$key |$host "
25- }
26-
27- # Function to send error to Sentry
10+ # Sentry reporting with validation and backwards compatibility
2811error_to_sentry () {
2912 local error_message=" $1 "
3013 local db_name=" $2 "
3114 local status_code=" $3 "
32-
33- # Check if SENTRY_DSN is set
15+
16+ # Check if SENTRY_DSN is configured - ensures backup continues
3417 if [ -z " ${SENTRY_DSN:- } " ]; then
35- log " ERROR: SENTRY_DSN not set "
36- return 1
18+ log " DEBUG " " Sentry logging skipped - SENTRY_DSN not configured "
19+ return 0
3720 fi
3821
39- # Parse DSN
40- local dsn_parts=($( parse_sentry_dsn " $SENTRY_DSN " | tr ' |' ' ' ) )
41- local project_id=" ${dsn_parts[0]} "
42- local key=" ${dsn_parts[1]} "
43- local host=" ${dsn_parts[2]} "
44-
45- # Generate event ID and timestamp
46- local event_id=$( generate_uuid)
47- local timestamp=$( date -u +" %Y-%m-%dT%H:%M:%S.000Z" )
48-
49- # Create JSON payload
50- local payload=$( cat << EOF
51- {
52- "event_id": "${event_id} ",
53- "timestamp": "${timestamp} ",
54- "level": "error",
55- "message": "${error_message} ",
56- "logger": "postgresql-backup",
57- "platform": "bash",
58- "environment": "production",
59- "tags": {
60- "database": "${db_name} ",
61- "status_code": "${status_code} ",
62- "host": "$( hostname) "
63- },
64- "extra": {
65- "script_path": "$0 ",
66- "timestamp": "${timestamp} "
67- }
68- }
69- EOF
70- )
71-
72- # Send to Sentry
73- local response
74- response=$( curl -s -X POST \
75- " https://${host} /api/${project_id} /store/" \
76- -H " Content-Type: application/json" \
77- -H " X-Sentry-Auth: Sentry sentry_version=7, sentry_key=${key} , sentry_client=bash-script/1.0" \
78- -d " ${payload} " 2>&1 )
79-
80- if [ $? -ne 0 ]; then
81- log " ERROR: Failed to send event to Sentry: ${response} "
82- return 1
22+ # Validate SENTRY_DSN format
23+ if ! [[ " ${SENTRY_DSN} " =~ ^https://[^@]+@[^/]+/[0-9]+$ ]]; then
24+ log " WARN" " Invalid SENTRY_DSN format - Sentry logging will be skipped"
25+ return 0
26+ fi
27+
28+ # Attempt to send event to Sentry
29+ if sentry-cli send-event \
30+ --message " ${error_message} " \
31+ --level error \
32+ --tag " database:${db_name} " \
33+ --tag " status:${status_code} " ; then
34+ log " DEBUG" " Successfully sent error to Sentry - Message: ${error_message} , Database: ${db_name} , Status: ${status_code} "
35+ else
36+ log " WARN" " Failed to send error to Sentry, but continuing backup process"
8337 fi
8438
85- log " Error event sent to Sentry: ${error_message} "
39+ return 0
8640}
8741
8842MYNAME=" postgresql-backup-restore"
10559 log " ${MYNAME} : Backup of ${DB_NAME} completed in $( expr ${end} - ${start} ) seconds, ($( stat -c %s /tmp/${DB_NAME} .sql) bytes)."
10660fi
10761
62+ # Compression
10863start=$( date +%s)
10964gzip -f /tmp/${DB_NAME} .sql || STATUS=$?
11065end=$( date +%s)
@@ -118,10 +73,10 @@ else
11873 log " ${MYNAME} : Compressing backup of ${DB_NAME} completed in $( expr ${end} - ${start} ) seconds."
11974fi
12075
76+ # S3 Upload
12177start=$( date +%s)
12278s3cmd put /tmp/${DB_NAME} .sql.gz ${S3_BUCKET} || STATUS=$?
12379end=$( date +%s)
124-
12580if [ $STATUS -ne 0 ]; then
12681 error_message=" ${MYNAME} : FATAL: Copy backup to ${S3_BUCKET} of ${DB_NAME} returned non-zero status ($STATUS ) in $( expr ${end} - ${start} ) seconds."
12782 log " ${error_message} "
@@ -131,14 +86,15 @@ else
13186 log " ${MYNAME} : Copy backup to ${S3_BUCKET} of ${DB_NAME} completed in $( expr ${end} - ${start} ) seconds."
13287fi
13388
89+ # Backblaze B2 Upload
13490if [ " ${B2_BUCKET} " != " " ]; then
13591 start=$( date +%s)
13692 s3cmd \
137- --access_key=${B2_APPLICATION_KEY_ID} \
138- --secret_key=${B2_APPLICATION_KEY} \
139- --host=${B2_HOST} \
140- --host-bucket=' %(bucket)s.' " ${B2_HOST} " \
141- put /tmp/${DB_NAME} .sql.gz s3://${B2_BUCKET} /${DB_NAME} .sql.gz
93+ --access_key=${B2_APPLICATION_KEY_ID} \
94+ --secret_key=${B2_APPLICATION_KEY} \
95+ --host=${B2_HOST} \
96+ --host-bucket=' %(bucket)s.' " ${B2_HOST} " \
97+ put /tmp/${DB_NAME} .sql.gz s3://${B2_BUCKET} /${DB_NAME} .sql.gz
14298 STATUS=$?
14399 end=$( date +%s)
144100 if [ $STATUS -ne 0 ]; then
@@ -151,4 +107,8 @@ if [ "${B2_BUCKET}" != "" ]; then
151107 fi
152108fi
153109
110+ echo " postgresql-backup-restore: backup: Completed"
111+
154112log " ${MYNAME} : backup: Completed"
113+
114+ exit $STATUS
0 commit comments