Keluaran terkini AWS Powertools untuk Lambda memudahkan untuk melanjutkan Logger dengan fungsi tersuai:
Kelas Logger kini lebih meluas
Anda kini boleh menulis ganti kaedah Logger createAndPopulateLogItem, printLog dan processLogItem, yang sebelum ini bersifat peribadi. Ini membolehkan anda memanjangkan Logger dan menambah fungsi baharu, cth., melaksanakan penimbal mesej anda sendiri.
Keluaran v2.12.0
Saya menggunakan kebolehlanjutan baharu ini untuk melaksanakan ciri berguna: penimbalan log dan pembilasan. Ideanya mudah: dalam persekitaran pengeluaran, kami biasanya hanya log maklumat penting, seperti amaran dan ralat, kerana ruang log boleh menjadi mahal dan ia menghasilkan bunyi. Walau bagaimanapun, apabila ralat berlaku, kami mahu setiap maklumat yang mungkin: semua log nyahpepijat dan maklumat yang bertaburan di seluruh fungsi harus tersedia. Tetapi ini bukan kerana kami menetapkan tahap log kami terlalu rendah.
Bagaimana jika kami mengumpul semua log nyahpepijat dan maklumat ini secara dalaman, dan jika peristiwa penting berlaku seperti ralat, kami mencetaknya ke konsol? Saya mengklasifikasikan log kepada dua kategori: log peringkat rendah dan log peringkat tinggi. Jika tahap log kami yang dikonfigurasikan ialah WARN, log DEBUG atau INFO akan menjadi tahap rendah dan ERROR akan menjadi log tahap tinggi.
Kini apabila kami mencetak log peringkat rendah, bukannya membuangnya seperti sekarang, kami menampan log dalam senarai dalaman. Sebaik sahaja kami mempunyai log peringkat tinggi, kami membuang semua log penimbal ke konsol.
Untuk menambah fungsi ini, kami mencipta kelas baharu yang memanjangkan kelas Logger daripada Powertools dan mengatasi processLogItem(). Ini ialah kaedah pusat yang dipanggil oleh kaedah log yang berbeza seperti logger.debug(). Pelaksanaan asal mencetak item log ke konsol jika ia berada pada tahap yang betul. Dengan mengatasi kaedah ini, kami boleh menambah logik penimbalan dan pemadaman khas kami bergantung pada tahap log.
import { LogItem, Logger as PowertoolsLogger } from '@aws-lambda-powertools/logger'; import type { LogItemExtraInput, LogItemMessage } from '@aws-lambda-powertools/logger/types'; export class Logger extends PowertoolsLogger { #buffer: Record<string, Array<[number, string]>> = {}; get buffer(): Record<string, Array<[number, string]>> { return this.#buffer; } protected override processLogItem(logLevel: number, input: LogItemMessage, extraInput: LogItemExtraInput): void { const xRayTraceId = this['envVarsService'].getXrayTraceId() as string; // Flush buffer when log level is higher than the configured log level if (logLevel > this.level && xRayTraceId) { const buffer = this.#buffer[xRayTraceId] ?? []; // Print all log items in the buffer if (buffer.length) this.info(`Flushing buffer with ${buffer.length} log items`); for (const [bufferLogLevel, bufferLogItem] of buffer) { // Create a new LogItem from the stringified log item this.printLog(bufferLogLevel, new LogItem(JSON.parse(bufferLogItem))); } // Clear the buffer after flushing // This also removes entries from other X-Ray trace IDs this.#buffer = {}; } // Buffer the log item when log level is lower than the configured log level if (logLevel < this.level && xRayTraceId) { const buffer = this.#buffer[xRayTraceId] ?? []; // Add the stringified log item to the buffer // Serializing the log item ensures it is not mutated after being added to the buffer buffer.push([logLevel, JSON.stringify(this.createAndPopulateLogItem(logLevel, input, extraInput))]); // Update the buffer with the new log item // This also removes other X-Ray trace IDs from the buffer this.#buffer = { [xRayTraceId]: buffer, }; } // Call the parent method to ensure the log item is processed super.processLogItem(logLevel, input, extraInput); } }
Anda mungkin bertanya mengapa kami menggunakan X-Ray Trace ID di sini. Ia adalah perkara biasa untuk membuat seketika Logger di luar fungsi pengendali. Walau bagaimanapun, kerana persekitaran pelaksanaan Lambda digunakan semula untuk seruan yang berpotensi berbilang, penimbal boleh mengandungi item log daripada seruan sebelumnya. Itulah sebabnya penimbal dilaksanakan sebagai objek dan bukannya tatasusunan mudah. Kami menggunakan X-Ray Trace ID sebagai pengecam untuk hanya menimbal item log daripada seruan yang sama.
Penampan dilaksanakan sebagai objek dan bukannya tatasusunan mudah. Apabila penimbal disiram, kita hanya boleh menetapkan semula objek dan oleh itu membersihkan item daripada seruan lain.
Mari sahkan pelaksanaan secara tempatan dengan cepat:
// set X-Ray Trace ID manually if running locally process.env._X_AMZN_TRACE_ID = '1-abcdef12-3456abcdef123456abcdef12'; // log level = WARN const logger = new Logger({ logLevel: 'WARN' }); logger.debug('debug'); // < log level logger.info('info'); // < log level logger.warn('warn'); // = log level logger.error('error'); // > log level
Inilah output yang kami dapat:
import { LogItem, Logger as PowertoolsLogger } from '@aws-lambda-powertools/logger'; import type { LogItemExtraInput, LogItemMessage } from '@aws-lambda-powertools/logger/types'; export class Logger extends PowertoolsLogger { #buffer: Record<string, Array<[number, string]>> = {}; get buffer(): Record<string, Array<[number, string]>> { return this.#buffer; } protected override processLogItem(logLevel: number, input: LogItemMessage, extraInput: LogItemExtraInput): void { const xRayTraceId = this['envVarsService'].getXrayTraceId() as string; // Flush buffer when log level is higher than the configured log level if (logLevel > this.level && xRayTraceId) { const buffer = this.#buffer[xRayTraceId] ?? []; // Print all log items in the buffer if (buffer.length) this.info(`Flushing buffer with ${buffer.length} log items`); for (const [bufferLogLevel, bufferLogItem] of buffer) { // Create a new LogItem from the stringified log item this.printLog(bufferLogLevel, new LogItem(JSON.parse(bufferLogItem))); } // Clear the buffer after flushing // This also removes entries from other X-Ray trace IDs this.#buffer = {}; } // Buffer the log item when log level is lower than the configured log level if (logLevel < this.level && xRayTraceId) { const buffer = this.#buffer[xRayTraceId] ?? []; // Add the stringified log item to the buffer // Serializing the log item ensures it is not mutated after being added to the buffer buffer.push([logLevel, JSON.stringify(this.createAndPopulateLogItem(logLevel, input, extraInput))]); // Update the buffer with the new log item // This also removes other X-Ray trace IDs from the buffer this.#buffer = { [xRayTraceId]: buffer, }; } // Call the parent method to ensure the log item is processed super.processLogItem(logLevel, input, extraInput); } }
Amaran ialah mesej pertama kerana log nyahpepijat dan maklumat telah ditimbal. Apabila ralat dilog, kami membuang log penimbal (dan mencetak maklumat) sebelum ralat sebenarnya dicetak.
Pelaksanaan naif saya mempunyai beberapa kaveat. Paling penting, saiz penimbal tidak terhad, yang bermaksud ia boleh menyebabkan masalah ingatan jika penimbal membesar terlalu besar. Terdapat beberapa pendekatan untuk mengurangkan isu ini, contohnya, dengan melaksanakan penimbal sebagai tetingkap gelongsor yang hanya menyimpan log terkini atau mengehadkan jumlah saiz penimbal.
Selain itu, log buffer hanya disiram dalam kes terkawal seperti pada logger.error(), tetapi bukan pada ralat yang tidak dikendalikan. Tingkah laku ini boleh dicapai dengan mudah jika kami membuat penimbal awam dan menggunakan perisian tengah seperti Middy.js. Middy mendedahkan peristiwa onError yang boleh kami gunakan untuk membuang penimbal.
Saya telah menulis tentang perkara ini dengan lebih meluas dalam Permintaan Untuk Ulasan ini pada repositori rasmi AWS Powertools untuk Lambda.
Jika anda ingin melihat ciri ini menjadi sebahagian daripada Powertools untuk Lambda, sila kongsi idea dan maklum balas anda di sana ?
Atas ialah kandungan terperinci Log Penampan dan Siram Secara Automatik pada Ralat dengan Alat Kuasa untuk Lambda. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!