Təsəvvür elə ki, botunu database-də sərbəst buraxmısan ki, orda çətin əməliyyatlar aparsın. Tez ya gec o, nəyisə səhv edəcək, ilişəcək və ya gözlənilməz bir vəziyyətlə qarşılaşacaq. Loglama olmadan o, sadəcə susacaq və sən başa düşməyəcəksən ki, nə baş verdi. Avtomatik loglama sənə kömək edir:
- Error və warning-lərin baş verməsini izləməyə.
- Problem və nasazlıqların səbəbini və təbiətini anlamağa.
- Kodun diaqnostikasını və performansını yaxşılaşdırmağa.
Avtomatik loglama ilə sən database-də baş verənləri qeyd edən "qara qutu" yaradırsan və error-ları tapmaqda özünü birinci dərəcəli detektiv kimi hiss edirsən.
Funksiyalar vasitəsilə avtomatik loglamanın yaradılması
- Loglar üçün cədvəl təyin edirik
Error-ları loglamaq üçün onları saxlamaq üçün yer lazımdır. Biz artıq əvvəlki mühazirədə error_log cədvəlini yaratmışdıq:
CREATE TABLE error_log (
id SERIAL PRIMARY KEY, -- Qeyd üçün unikal identifikator
error_message TEXT NOT NULL, -- Error mesajı
error_time TIMESTAMP DEFAULT NOW(), -- Error-un baş vermə vaxtı
function_name TEXT -- Error-u çağıran funksiyanın adı
);
Bu cədvəldə error yazmaq üçün lazım olan hər şey var: error-un mətni, vaxtı və hansı funksiyadan gəldiyi.
- Log yazmaq üçün funksiya yaradırıq
Növbəti addım — universal funksiya yaratmaqdır ki, error-ları error_log cədvəlinə yazsın. Bu funksiya istədiyimiz vaxt error-u qeyd etmək üçün çağırılacaq.
CREATE OR REPLACE FUNCTION log_error(p_error_message TEXT, p_function_name TEXT)
RETURNS VOID AS $$
BEGIN
INSERT INTO error_log (error_message, function_name)
VALUES (p_error_message, p_function_name);
-- Uğurlu loglama barədə mesaj
RAISE NOTICE 'Error logged: %', p_error_message;
END;
$$ LANGUAGE plpgsql;
Bu kodu izah edək:
p_error_messagevəp_function_name— funksiyanın parametrləridir, error mesajını və çağıran funksiyanın adını qəbul edir.INSERT INTO error_logcədvələ qeyd əlavə edir.RAISE NOTICEkonsolda mesaj çıxarır ki, developer loglama prosesindən xəbərdar olsun.
İndi birinci tapşırığın həllini tapdıq: error-ları cədvələ minimal səylə yaza bilirik.
log_error funksiyasının real tapşırıqlarda istifadəsi
Nümunə 1: Sıfıra bölmə zamanı error-un loglanması
Bir funksiya yaradaq ki, sadə bölmə aparır, amma əgər məxrəc 0-dırsa, error-u loglayır.
CREATE OR REPLACE FUNCTION divide_numbers(a NUMERIC, b NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
result NUMERIC;
BEGIN
IF b = 0 THEN
-- Loglama funksiyasını çağırırıq
PERFORM log_error('Sıfıra bölmə cəhdi!', 'divide_numbers');
-- Exception yaradırıq
RAISE EXCEPTION 'Sıfıra bölmək olmaz.';
END IF;
-- Bölməni icra edirik
result := a / b;
RETURN result;
END;
$$ LANGUAGE plpgsql;
- Əgər məxrəc 0-dırsa,
log_errorfunksiyası çağırılır və error cədvələ yazılır. - Error yazıldıqdan sonra
RAISE EXCEPTIONilə istifadəçiyə bildiriş gedir.
Çağırış nümunəsi:
SELECT divide_numbers(10, 0);
Nəticə:
- Bu funksiyanı sıfıra bölmə ilə çağıranda error
error_logcədvəlinə yazılacaq. - İstifadəçi konsolda error mesajı görəcək.
Nümunə 2: Yanlış məlumat əlavə edəndə loglama
Bir funksiya nümunəsinə baxaq ki, yeni tələbəni students cədvəlinə əlavə edir. Əgər tələbənin adı boşdursa, hadisəni loglayırıq və icranı dayandırırıq.
CREATE OR REPLACE FUNCTION add_student(p_name TEXT)
RETURNS VOID AS $$
BEGIN
IF p_name IS NULL OR p_name = '' THEN
PERFORM log_error('Tələbə adı daxil edilməlidir!', 'add_student');
RAISE EXCEPTION 'Tələbə adı boş ola bilməz.';
END IF;
INSERT INTO students (name) VALUES (p_name);
END;
$$ LANGUAGE plpgsql;
Çağırış nümunəsi:
SELECT add_student('');
Əgər tələbəni ad olmadan əlavə etməyə çalışsaq, funksiya error_log-da uyğun mesajla qeyd yaradacaq.
Nümunə 3: Warning-lərin loglanması
Həmişə istifadəçiyə exception göstərmək lazım deyil. Bəzən sadəcə warning qeyd etmək kifayətdir. Tələbənin yaşını yoxlayan funksiya düzəldək:
CREATE OR REPLACE FUNCTION check_age(p_age INT)
RETURNS VOID AS $$
BEGIN
IF p_age < 18 THEN
-- Warning loglayırıq, amma icranı dayandırmırıq
PERFORM log_error('Tələbənin yaşı 18-dən aşağıdır.', 'check_age');
RAISE NOTICE 'Diqqət: Tələbənin yaşı 18-dən aşağıdır.';
END IF;
RAISE NOTICE 'Yaş yoxlaması keçdi.';
END;
$$ LANGUAGE plpgsql;
Çağırış nümunəsi:
SELECT check_age(16);
Nəticə:
- Warning
error_logcədvəlinə yazılır. - Konsolda tələbənin yaşının 18-dən az olduğu barədə bildiriş çıxır.
Loglama və exception-ların işlənməsi
Gəlin error yazma və exception işləməyi bir az daha mürəkkəb funksiyada birləşdirək. Təsəvvür elə ki, grades cədvəlində tələbələrin qiymətlərini yenidən hesablamaq tapşırığımız var. Əgər proses hansısa tələbə üçün icra olunmasa, error loglanır, amma əməliyyat davam edir.
CREATE OR REPLACE FUNCTION recalculate_grades()
RETURNS VOID AS $$
DECLARE
student RECORD;
BEGIN
FOR student IN SELECT * FROM students LOOP
BEGIN
-- Tapşırıq nümunəsi: tələbənin qiymətlərini yeniləmək
UPDATE grades SET final_grade = final_grade + 1
WHERE student_id = student.id;
RAISE NOTICE 'Tələbə üçün qiymətlər yeniləndi %', student.name;
EXCEPTION WHEN OTHERS THEN
-- Error-u loglayırıq və icranı davam etdiririk
PERFORM log_error('Tələbə üçün qiymətləri yeniləmək alınmadı ' || student.name, 'recalculate_grades');
END;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Çağırış nümunəsi:
SELECT recalculate_grades();
Bu yanaşma funksiyanı daha dayanıqlı edir, çünki error-lar ayrıca loglanır və bütün məlumatlar üçün icra dayanmaz.
GO TO FULL VERSION