mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-15 18:13:18 +08:00
SQLSmith finds many internal program errors (`elog`, code `XX000`). Normally these errors shouldn't be triggered by user actions and indicate a bug in the program (like `variable not found in subplan targetlist`). We don't have a capacity to fix all of them currently, especially since some of them seem to be the upstream ones. This commit adds logging for these errors so that we at least can study the current situation.
180 lines
5.2 KiB
Bash
Executable File
180 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -xue
|
|
|
|
if [ -z "${CI_STATS_DB:-}" ]
|
|
then
|
|
# The secret with the stats db connection string is not accessible in forks.
|
|
echo "The statistics database connection string is not specified"
|
|
exit 0
|
|
fi
|
|
|
|
PSQL=${PSQL:-psql}
|
|
PSQL=("${PSQL}" "${CI_STATS_DB}" -qtAX "--set=ON_ERROR_STOP=1")
|
|
|
|
# The tables we are going to use. This schema is here just as a reminder, you'll
|
|
# have to create them manually. After you manually change the actual DB schema,
|
|
# don't forget to append the needed migration code below.
|
|
: "
|
|
create extension if not exists timescaledb;
|
|
|
|
create table job(
|
|
job_date timestamptz, -- Serves as a unique id.
|
|
commit_sha text,
|
|
job_name text,
|
|
repository text,
|
|
ref_name text,
|
|
event_name text,
|
|
pr_number int,
|
|
job_status text,
|
|
url text,
|
|
run_attempt int,
|
|
run_id bigint,
|
|
run_number int
|
|
);
|
|
|
|
create unique index on job(job_date);
|
|
|
|
select create_hypertable('job', 'job_date');
|
|
|
|
create table test(
|
|
job_date timestamptz,
|
|
test_name text,
|
|
test_status text,
|
|
test_duration float
|
|
);
|
|
|
|
create unique index on test(job_date, test_name);
|
|
|
|
select create_hypertable('test', 'job_date');
|
|
|
|
create table log(
|
|
job_date timestamptz,
|
|
test_name text,
|
|
log_contents text
|
|
);
|
|
|
|
create unique index on log(job_date, test_name);
|
|
|
|
select create_hypertable('log', 'job_date');
|
|
|
|
create table ipe(
|
|
job_date timestamptz,
|
|
error text,
|
|
location text,
|
|
statement text
|
|
);
|
|
|
|
select create_hypertable('ipe', 'job_date');
|
|
"
|
|
|
|
# Create the job record.
|
|
COMMIT_SHA=$(git -C "$(dirname "${BASH_SOURCE[0]}")" rev-parse @)
|
|
export COMMIT_SHA
|
|
|
|
JOB_NAME="${JOB_NAME:-test-job}"
|
|
export JOB_NAME
|
|
|
|
JOB_DATE=$("${PSQL[@]}" -c "
|
|
insert into job values (
|
|
now(), '$COMMIT_SHA', '$JOB_NAME',
|
|
'$GITHUB_REPOSITORY', '$GITHUB_REF_NAME', '$GITHUB_EVENT_NAME',
|
|
'$GITHUB_PR_NUMBER', '$JOB_STATUS',
|
|
'https://github.com/timescale/timescaledb/actions/runs/$GITHUB_RUN_ID/attempts/$GITHUB_RUN_ATTEMPT',
|
|
'$GITHUB_RUN_ATTEMPT', '$GITHUB_RUN_ID', '$GITHUB_RUN_NUMBER')
|
|
returning job_date;
|
|
")
|
|
export JOB_DATE
|
|
|
|
# Parse the installcheck.log to find the individual test results. Note that this
|
|
# file might not exist for failed checks or non-regression checks like SQLSmith.
|
|
# We still want to save the other logs.
|
|
if [ -f 'installcheck.log' ]
|
|
then
|
|
gawk -v OFS='\t' '
|
|
match($0, /^(test| ) ([^ ]+)[ ]+\.\.\.[ ]+([^ ]+) (|\(.*\))[ ]+([0-9]+) ms$/, a) {
|
|
print ENVIRON["JOB_DATE"], a[2], tolower(a[3] (a[4] ? (" " a[4]) : "")), a[5];
|
|
}
|
|
' installcheck.log > tests.tsv
|
|
|
|
# Save the test results into the database.
|
|
"${PSQL[@]}" -c "\copy test from tests.tsv"
|
|
|
|
# Split the regression.diffs into per-test files.
|
|
gawk '
|
|
match($0, /^(diff|\+\+\+|\-\-\-) .*\/(.*)[.]out/, a) {
|
|
file = a[2] ".diff";
|
|
next;
|
|
}
|
|
|
|
{ if (file) print $0 > file; }
|
|
' regression.log
|
|
fi
|
|
|
|
# Snip the long sequences of "+" or "-" changes in the diffs.
|
|
for x in *.diff;
|
|
do
|
|
if ! [ -f "$x" ] ; then continue ; fi
|
|
gawk -v max_context_lines=10 -v min_context_lines=2 '
|
|
/^-/ { new_sign = "-" }
|
|
/^+/ { new_sign = "+" }
|
|
/^[^+-]/ { new_sign = " " }
|
|
|
|
{
|
|
if (old_sign != new_sign) {
|
|
to_print = lines_buffered > max_context_lines ? min_context_lines : lines_buffered;
|
|
|
|
if (lines_buffered > to_print)
|
|
print "<" lines_buffered - to_print " lines skipped>";
|
|
|
|
for (i = 0; i < to_print; i++) {
|
|
print buf[(NR + i - to_print) % max_context_lines]
|
|
}
|
|
|
|
printf("c %04d: %s\n", NR, $0);
|
|
old_sign = new_sign;
|
|
lines_printed = 0;
|
|
lines_buffered = 0;
|
|
} else {
|
|
if (lines_printed >= min_context_lines) {
|
|
lines_buffered++;
|
|
buf[NR % max_context_lines] = sprintf("b %04d: %s", NR, $0)
|
|
} else {
|
|
lines_printed++;
|
|
printf("p %04d: %s\n", NR, $0);
|
|
}
|
|
}
|
|
}
|
|
|
|
END {
|
|
to_print = lines_buffered > max_context_lines ? min_context_lines : lines_buffered;
|
|
|
|
if (lines_buffered > to_print)
|
|
print "<" lines_buffered - to_print " lines skipped>";
|
|
|
|
for (i = 0; i < to_print; i++) {
|
|
print buf[(NR + 1 + i - to_print) % max_context_lines]
|
|
}
|
|
}' "$x" > "$x.tmp"
|
|
mv "$x.tmp" "$x"
|
|
done
|
|
|
|
# Save a snippet of logs where a backend was terminated by signal.
|
|
grep -C40 "was terminated by signal" postmaster.log > postgres-failure.log ||:
|
|
|
|
# Find internal program errors in Postgres logs.
|
|
jq 'select(.state_code == "XX000" and .error_severity != "LOG")
|
|
| [env.JOB_DATE, .message, .func_name, .statement] | @tsv
|
|
' -r postmaster.json > ipe.tsv ||:
|
|
"${PSQL[@]}" -c "\copy ipe from ipe.tsv"
|
|
|
|
# Upload the logs.
|
|
# Note that the sanitizer setting log_path means "write logs to 'log_path.pid'".
|
|
for x in sanitizer* sanitizer/* {sqlsmith/sqlsmith,sanitizer,stacktrace,postgres-failure}.log *.diff
|
|
do
|
|
if ! [ -e "$x" ]; then continue ; fi
|
|
"${PSQL[@]}" <<<"
|
|
\set contents \`cat $x\`
|
|
insert into log values ('$JOB_DATE', '$(basename "$x" .diff)', :'contents');
|
|
"
|
|
done
|