MySQL 9.2.0
Source Code Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
log_builtins.h
Go to the documentation of this file.
1/* Copyright (c) 2017, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24/**
25 This defines built-in functions for use by logging services.
26 These helpers are organized into a number of APIs grouping
27 related functionality.
28
29 For documentation of the individual functions, see log_builtins.cc
30*/
31
32#ifndef LOG_BUILTINS_H
33#define LOG_BUILTINS_H
34
40#if defined(MYSQL_DYNAMIC_PLUGIN)
42#endif
43#include <stdarg.h>
44#include <stdio.h>
45#include <string.h>
46
47#include <my_compiler.h>
48#if defined(MYSQL_SERVER) && !defined(MYSQL_DYNAMIC_PLUGIN)
49#include "sql/log.h"
50#endif
51
52/**
53 typedef for log-processing functions ("buffer this event",
54 "process this event", etc.)
55*/
56typedef bool (*log_line_processor)(log_line *ll);
57
58/**
59 Set the log-event processor.
60
61 When a log-event is submitted, a function is applied to that event.
62 That function usually either buffers the event for later processing,
63 or filters and logs the event.
64
65 That function can be set here.
66
67 @param llp A log-processor
68*/
70
71/**
72 Get current log-event processor.
73
74 When a log-event is submitted, a function is applied to that event.
75 That function usually either buffers the event for later processing,
76 or filters and logs the event.
77 log_line_process_hook_get() returns a pointer to that function.
78
79 @retval a pointer to a log-event processing function
80*/
82
83/**
84 Primitives for services to interact with the structured logger:
85 functions pertaining to log_line and log_item data
86*/
88/**
89 See whether a type is wellknown.
90
91 @param t log item type to examine
92
93 @retval LOG_ITEM_TYPE_NOT_FOUND: key not found
94 @retval >0: index in array of wellknowns
95*/
96DECLARE_METHOD(int, wellknown_by_type, (log_item_type t));
97
98/**
99 See whether a string is a wellknown field name.
100
101 @param key potential key starts here
102 @param length length of the string to examine
103
104 @retval LOG_ITEM_TYPE_RESERVED: reserved, but not "wellknown" key
105 @retval LOG_ITEM_TYPE_NOT_FOUND: key not found
106 @retval >0: index in array of wellknowns
107*/
108DECLARE_METHOD(int, wellknown_by_name, (const char *key, size_t length));
109
110/**
111 Accessor: from a record describing a wellknown key, get its type
112
113 @param idx index in array of wellknowns, see log_item_wellknown_by_...()
114
115 @retval the log item type for the wellknown key
116*/
117DECLARE_METHOD(log_item_type, wellknown_get_type, (uint idx));
118
119/**
120 Accessor: from a record describing a wellknown key, get its name
121
122 @param idx index in array of wellknowns, see log_item_wellknown_by_...()
123
124 @retval name (NTBS)
125*/
126DECLARE_METHOD(const char *, wellknown_get_name, (uint idx));
127
128/**
129 Sanity check an item.
130 Certain log sinks have very low requirements with regard to the data
131 they receive; they write keys as strings, and then data according to
132 the item's class (string, integer, or float), formatted to the sink's
133 standards (e.g. JSON, XML, ...).
134 Code that has higher requirements can use this check to see whether
135 the given item is of a known type (whether generic or wellknown),
136 whether the given type and class agree, and whether in case of a
137 well-known type, the given key is correct for that type.
138 If your code generates items that don't pass this check, you should
139 probably go meditate on it.
140
141 @param li the log_item to check
142
143 @retval LOG_ITEM_OK no problems
144 @retval LOG_ITEM_TYPE_NOT_FOUND unknown item type
145 @retval LOG_ITEM_CLASS_MISMATCH item_class derived from type isn't
146 what's set on the item
147 @retval LOG_ITEM_KEY_MISMATCH class not generic, so key should
148 match wellknown
149 @retval LOG_ITEM_STRING_NULL class is string, pointer is nullptr
150 @retval LOG_ITEM_KEY_NULL no key set (this is legal e.g. on aux
151 items of filter rules, but should not
152 occur in a log_line, i.e., log_sinks are
153 within their rights to discard such items)
154*/
155DECLARE_METHOD(int, item_inconsistent, (log_item * li));
156
157// helpers: predicates to find out about types and classes
158
159/**
160 Predicate used to determine whether a type is generic
161 (generic string, generic float, generic integer) rather
162 than a well-known type.
163
164 @param t log item type to examine
165
166 @retval true if generic type
167 @retval false if wellknown type
168*/
169DECLARE_METHOD(bool, item_generic_type, (log_item_type t));
170
171/**
172 Predicate used to determine whether a class is a string
173 class (C-string or Lex-string).
174
175 @param c log item class to examine
176
177 @retval true if of a string class
178 @retval false if not of a string class
179*/
180DECLARE_METHOD(bool, item_string_class, (log_item_class c));
181
182/**
183 Predicate used to determine whether a class is a numeric
184 class (integer or float).
185
186 @param c log item class to examine
187
188 @retval true if of a numeric class
189 @retval false if not of a numeric class
190*/
191DECLARE_METHOD(bool, item_numeric_class, (log_item_class c));
192
193/**
194 Set an integer value on a log_item.
195 Fails gracefully if no log_item_data is supplied, so it can safely
196 wrap log_line_item_set[_with_key]().
197
198 @param lid log_item_data struct to set the value on
199 @param i integer to set
200
201 @retval true lid was nullptr (possibly: OOM, could not set up log_item)
202 @retval false all's well
203*/
204DECLARE_METHOD(bool, item_set_int, (log_item_data * lid, longlong i));
205/**
206 Set a floating point value on a log_item.
207 Fails gracefully if no log_item_data is supplied, so it can safely
208 wrap log_line_item_set[_with_key]().
209
210 @param lid log_item_data struct to set the value on
211 @param f float to set
212
213 @retval true lid was nullptr (possibly: OOM, could not set up log_item)
214 @retval false all's well
215*/
216DECLARE_METHOD(bool, item_set_float, (log_item_data * lid, double f));
217
218/**
219 Set a string value on a log_item.
220 Fails gracefully if no log_item_data is supplied, so it can safely
221 wrap log_line_item_set[_with_key]().
222
223 @param lid log_item_data struct to set the value on
224 @param s pointer to string
225 @param s_len length of string
226
227 @retval true lid was nullptr (possibly: OOM, could not set up log_item)
228 @retval false all's well
229*/
230DECLARE_METHOD(bool, item_set_lexstring,
231 (log_item_data * lid, const char *s, size_t s_len));
232
233/**
234 Set a string value on a log_item.
235 Fails gracefully if no log_item_data is supplied, so it can safely
236 wrap log_line_item_set[_with_key]().
237
238 @param lid log_item_data struct to set the value on
239 @param s pointer to NTBS
240
241 @retval true lid was nullptr (possibly: OOM, could not set up log_item)
242 @retval false all's well
243*/
244DECLARE_METHOD(bool, item_set_cstring, (log_item_data * lid, const char *s));
245
246/**
247 Set/reset one or more log line flags.
248
249 Example to set the flag:
250 log_line_set_flag(ll, LOG_LINE_EMIT_TELEMETRY, LOG_LINE_EMIT_TELEMETRY);
251 to reset the flag:
252 log_line_set_flag(ll, LOG_LINE_EMIT_TELEMETRY, 0);
253*/
254DECLARE_METHOD(void, line_set_flag,
257
258/**
259 Create new log item with key name "key", and allocation flags of
260 "alloc" (see enum_log_item_free).
261 Will return a pointer to the item's log_item_data struct for
262 convenience.
263 This is mostly interesting for filters and other services that create
264 items that are not part of a log_line; sources etc. that intend to
265 create an item for a log_line (the more common case) should usually
266 use the below line_item_set_with_key() which creates an item (like
267 this function does), but also correctly inserts it into a log_line.
268
269 @param li the log_item to work on
270 @param t the item-type
271 @param key the key to set on the item.
272 ignored for non-generic types (may pass nullptr for those)
273 see alloc
274 @param alloc LOG_ITEM_FREE_KEY if key was allocated by caller
275 LOG_ITEM_FREE_NONE if key was not allocated
276 Allocated keys will automatically free()d when the
277 log_item is.
278 The log_item's alloc flags will be set to the
279 submitted value; specifically, any pre-existing
280 value will be clobbered. It is therefore WRONG
281 a) to use this on a log_item that already has a key;
282 it should only be used on freshly init'd log_items;
283 b) to use this on a log_item that already has a
284 value (specifically, an allocated one); the correct
285 order is to init a log_item, then set up type and
286 key, and finally to set the value. If said value is
287 an allocated string, the log_item's alloc should be
288 bitwise or'd with LOG_ITEM_FREE_VALUE.
289
290 @retval a pointer to the log_item's log_data, for easy chaining:
291 log_item_set_with_key(...)->data_integer= 1;
292*/
293DECLARE_METHOD(log_item_data *, item_set_with_key,
294 (log_item * li, log_item_type t, const char *key, uint32 alloc));
295
296/**
297 As log_item_set_with_key(), except that the key is automatically
298 derived from the wellknown log_item_type t.
299
300 Create new log item with type "t".
301 Will return a pointer to the item's log_item_data struct for
302 convenience.
303 This is mostly interesting for filters and other services that create
304 items that are not part of a log_line; sources etc. that intend to
305 create an item for a log_line (the more common case) should usually
306 use the below line_item_set_with_key() which creates an item (like
307 this function does), but also correctly inserts it into a log_line.
308
309 The allocation of this item will be LOG_ITEM_FREE_NONE;
310 specifically, any pre-existing value will be clobbered.
311 It is therefore WRONG
312 a) to use this on a log_item that already has a key;
313 it should only be used on freshly init'd log_items;
314 b) to use this on a log_item that already has a
315 value (specifically, an allocated one); the correct
316 order is to init a log_item, then set up type and
317 key, and finally to set the value. If said value is
318 an allocated string, the log_item's alloc should be
319 bitwise or'd with LOG_ITEM_FREE_VALUE.
320
321 @param li the log_item to work on
322 @param t the item-type
323
324 @retval a pointer to the log_item's log_data, for easy chaining:
325 log_item_set_with_key(...)->data_integer= 1;
326*/
328
329/**
330 Create new log item in log line "ll", with key name "key", and
331 allocation flags of "alloc" (see enum_log_item_free).
332 On success, the number of registered items on the log line is increased,
333 the item's type is added to the log_line's "seen" property,
334 and a pointer to the item's log_item_data struct is returned for
335 convenience.
336
337 @param ll the log_line to work on
338 @param t the item-type
339 @param key the key to set on the item.
340 ignored for non-generic types (may pass nullptr for those)
341 see alloc
342 @param alloc LOG_ITEM_FREE_KEY if key was allocated by caller
343 LOG_ITEM_FREE_NONE if key was not allocated
344 Allocated keys will automatically free()d when the
345 log_item is.
346 The log_item's alloc flags will be set to the
347 submitted value; specifically, any pre-existing
348 value will be clobbered. It is therefore WRONG
349 a) to use this on a log_item that already has a key;
350 it should only be used on freshly init'd log_items;
351 b) to use this on a log_item that already has a
352 value (specifically, an allocated one); the correct
353 order is to init a log_item, then set up type and
354 key, and finally to set the value. If said value is
355 an allocated string, the log_item's alloc should be
356 bitwise or'd with LOG_ITEM_FREE_VALUE.
357
358 @retval a pointer to the log_item's log_data, for easy chaining:
359 log_line_item_set_with_key(...)->data_integer= 1;
360*/
361DECLARE_METHOD(log_item_data *, line_item_set_with_key,
362 (log_line * ll, log_item_type t, const char *key, uint32 alloc));
363
364/**
365 Create a new log item of well-known type "t" in log line "ll".
366 On success, the number of registered items on the log line is increased,
367 the item's type is added to the log_line's "seen" property,
368 and a pointer to the item's log_item_data struct is returned for
369 convenience.
370
371 The allocation of this item will be LOG_ITEM_FREE_NONE;
372 specifically, any pre-existing value will be clobbered.
373 It is therefore WRONG
374 a) to use this on a log_item that already has a key;
375 it should only be used on freshly init'd log_items;
376 b) to use this on a log_item that already has a
377 value (specifically, an allocated one); the correct
378 order is to init a log_item, then set up type and
379 key, and finally to set the value. If said value is
380 an allocated string, the log_item's alloc should be
381 bitwise or'd with LOG_ITEM_FREE_VALUE.
382
383 @param ll the log_line to work on
384 @param t the item-type
385
386 @retval a pointer to the log_item's log_data, for easy chaining:
387 log_line_item_set_with_key(...)->data_integer= 1;
388*/
389DECLARE_METHOD(log_item_data *, line_item_set,
391
392/**
393 Dynamically allocate and initialize a log_line.
394
395 @retval nullptr could not set up buffer (too small?)
396 @retval other address of the newly initialized log_line
397*/
398DECLARE_METHOD(log_line *, line_init, ());
399
400/**
401 Release a log_line allocated with line_init()
402
403 @param ll a log_line previously allocated with line_init()
404*/
405DECLARE_METHOD(void, line_exit, (log_line * ll));
406
407/**
408 How many items are currently set on the given log_line?
409
410 @param ll the log-line to examine
411
412 @retval the number of items set
413*/
414DECLARE_METHOD(int, line_item_count, (log_line * ll));
415
416/**
417 Test whether a given type is presumed present on the log line.
418
419 @param ll the log_line to examine
420 @param m the log_type to test for
421
422 @retval 0 not present
423 @retval !=0 present
424*/
425DECLARE_METHOD(log_item_type_mask, line_item_types_seen,
427
428/**
429 Get log-line's output buffer.
430 If the logger core provides this buffer, the log-service may use it
431 to assemble its output therein and implicitly return it to the core.
432 Participation is required for services that support populating
433 performance_schema.error_log, and optional for all others.
434
435 @param ll the log_line to examine
436
437 @retval nullptr success, an output buffer is available
438 @retval otherwise failure, no output buffer is available
439*/
440DECLARE_METHOD(log_item *, line_get_output_buffer, (log_line * ll));
441
442/**
443 Get an iterator for the items in a log_line.
444 For now, only one iterator may exist per log_line.
445
446 @param ll the log_line to examine
447
448 @retval a log_iter_iter, or nullptr on failure
449*/
450DECLARE_METHOD(log_item_iter *, line_item_iter_acquire, (log_line * ll));
451
452/**
453 Release an iterator for the items in a log_line.
454
455 @param it the iterator to release
456*/
457DECLARE_METHOD(void, line_item_iter_release, (log_item_iter * it));
458/**
459 Use the log_line iterator to get the first item from the set.
460
461 @param it the iterator to use
462
463 @retval pointer to the first log_item in the collection, or nullptr
464*/
465DECLARE_METHOD(log_item *, line_item_iter_first, (log_item_iter * it));
466
467/**
468 Use the log_line iterator to get the next item from the set.
469
470 @param it the iterator to use
471
472 @retval pointer to the next log_item in the collection, or nullptr
473*/
474DECLARE_METHOD(log_item *, line_item_iter_next, (log_item_iter * it));
475
476/**
477 Use the log_line iterator to get the current item from the set.
478
479 @param it the iterator to use
480
481 @retval pointer to the current log_item in the collection, or nullptr
482*/
483DECLARE_METHOD(log_item *, line_item_iter_current, (log_item_iter * it));
484
485/**
486 Complete, filter, and write submitted log items.
487
488 This expects a log_line collection of log-related key/value pairs,
489 e.g. from log_message().
490
491 Where missing, timestamp, priority, thread-ID (if any) and so forth
492 are added.
493
494 Log item source services, log item filters, and log item sinks are
495 then called; then all applicable resources are freed.
496
497 This interface is intended to facilitate the building of submission
498 interfaces other than the variadic message() one below. See the
499 example fluent C++ LogEvent() wrapper for an example of how to leverage
500 it.
501
502 @param ll key/value pairs describing info to log
503
504 @retval int number of fields in created log line
505*/
506DECLARE_METHOD(int, line_submit, (log_line * ll));
507
508/**
509 Submit a log-message for log "log_type".
510 Variadic convenience function for logging.
511
512 This fills in the array that is used by the filter and log-writer
513 services. Where missing, timestamp, priority, and thread-ID (if any)
514 are added. Log item source services, log item filters, and log item
515 writers are called.
516
517
518 The variadic list accepts a list of "assignments" of the form
519 - log_item_type, value, for well-known types, and
520 - log_item_type, key, value, for ad-hoc types (LOG_ITEM_GEN_*)
521
522 As its last item, the list should have
523 - an element of type LOG_ITEM_LOG_MESSAGE, containing a printf-style
524 format string, followed by all variables necessary to satisfy the
525 substitutions in that string
526
527 OR
528
529 - an element of type LOG_ITEM_LOG_LOOKUP, containing a MySQL error code,
530 which will be looked up in the list or regular error messages, followed
531 by all variables necessary to satisfy the substitutions in that string
532
533 OR
534
535 - an element of type LOG_ITEM_LOG_VERBATIM, containing a string that will
536 be used directly, with no % substitutions
537
538 see log_vmessage() for more information.
539*/
540DECLARE_METHOD(int, message, (int log_type, ...));
541
542/**
543 Escape \0 bytes, add \0 terminator. For log-writers and other sinks
544 that terminate in an API using C-strings.
545
546
547 @param li list_item to process
548
549 @retval -1 out of memory
550 @retval 0 success
551*/
552DECLARE_METHOD(int, sanitize, (log_item * li));
553
554/**
555 Return MySQL error message for a given error code.
556
557 @param mysql_errcode the error code the message for which to look up
558
559 @retval the message (a printf-style format string)
560*/
561DECLARE_METHOD(const char *, errmsg_by_errcode, (int mysql_errcode));
562
563/**
564 Return MySQL error code for a given error symbol.
565
566 @param sym the symbol to look up
567
568 @retval -1 failure
569 @retval >=0 the MySQL error code
570*/
571DECLARE_METHOD(longlong, errcode_by_errsymbol, (const char *sym));
572
573/**
574 Convenience function: Derive a log label ("error", "warning",
575 "information") from a severity.
576
577 @param prio the severity/prio in question
578
579 @return a label corresponding to that priority.
580 @retval "System" for prio of SYSTEM_LEVEL
581 @retval "Error" for prio of ERROR_LEVEL
582 @retval "Warning" for prio of WARNING_LEVEL
583 @retval "Note" for prio of INFORMATION_LEVEL
584*/
585DECLARE_METHOD(const char *, label_from_prio, (int prio));
586
587/**
588 Parse a ISO8601 timestamp and return the number of microseconds
589 since the epoch. Heeds +/- timezone info if present.
590
591 @see make_iso8601_timestamp()
592
593 @param timestamp an ASCII string containing an ISO8601 timestamp
594 @param len Length in bytes of the aforementioned string
595
596 @return microseconds since the epoch
597*/
598DECLARE_METHOD(ulonglong, parse_iso8601_timestamp,
599 (const char *timestamp, size_t len));
600
601/**
602 open an error log file
603
604 @param name_or_ext if beginning with '.':
605 @@global.log_error, except with this extension
606 otherwise:
607 use this as file name in the same location as
608 @@global.log_error
609
610 Value not contain folder separators!
611
612 @param[out] my_errstream an error log handle, or nullptr on failure
613
614 @returns LOG_SERVICE_SUCCESS success
615 @returns LOG_SERVICE_INVALID_ARGUMENT no my_errstream, or bad log name
616 @returns LOG_SERVICE_OUT_OF_MEMORY could not allocate file handle
617 @returns LOG_SERVICE_LOCK_ERROR couldn't lock lock
618 @returns LOG_SERVICE_UNABLE_TO_WRITE couldn't write to given location
619 @returns LOG_SERVICE_COULD_NOT_MAKE_LOG_NAME could not make log name
620*/
621DECLARE_METHOD(log_service_error, open_errstream,
622 (const char *name_or_ext, void **my_errstream));
623
624/**
625 write to an error log file previously opened with open_errstream()
626
627 @param my_errstream a handle describing the log file
628 @param buffer pointer to the string to write
629 @param length length of the string to write
630
631 @returns LOG_SERVICE_SUCCESS success
632 @returns otherwise failure
633*/
634DECLARE_METHOD(log_service_error, write_errstream,
635 (void *my_errstream, const char *buffer, size_t length));
636
637/**
638 are we writing to a dedicated errstream, or are we sharing it?
639
640 @param my_errstream a handle describing the log file
641
642 @retval 0 not dedicated (multiplexed, stderr, ...)
643 @retval 1 dedicated
644*/
645DECLARE_METHOD(int, dedicated_errstream, (void *my_errstream));
646
647/**
648 close an error log file previously opened with open_errstream()
649
650 @param my_stream a handle describing the log file
651
652 @returns LOG_SERVICE_SUCCESS on success
653*/
654DECLARE_METHOD(log_service_error, close_errstream, (void **my_errstream));
655
656/**
657 re-open an error log file
658 (primarily to facilitate flush/log-rotation)
659
660 If the new file can be opened, update the my_errstream descriptor to
661 use it and close the old file. Otherwise, keep using the old file.
662
663 @param name_or_ext if beginning with '.':
664 @@global.log_error, except with this extension
665 otherwise:
666 use this as file name in the same location as
667 @@global.log_error
668
669 Value may not contain folder separators!
670
671 In the general case, the caller will be a
672 log-writer, the log-writer will just pass
673 its preferred file extension, and the resulting
674 file name and path will therefore be the same
675 as for the original log file.
676
677 @param[in,out] my_errstream an error log handle
678
679 @returns LOG_SERVICE_INVALID_ARGUMENT, or the result of open_errstream()
680*/
681DECLARE_METHOD(log_service_error, reopen_errstream,
682 (const char *file, void **my_errstream));
683
685
686/**
687 String primitives for logging services.
688*/
689BEGIN_SERVICE_DEFINITION(log_builtins_string)
690// alloc (len+1) bytes
691DECLARE_METHOD(void *, malloc, (size_t len));
692// alloc (len+1) bytes, then copy len bytes from fm, and \0 terminate
693// like my_strndup(), and unlike strndup(), \0 in input won't end copying
694DECLARE_METHOD(char *, strndup, (const char *fm, size_t len));
695// free allocated memory
696DECLARE_METHOD(void, free, (void *ptr));
697
698// length of nul terminated byte string
699DECLARE_METHOD(size_t, length, (const char *s));
700// find char in string, from the left
701DECLARE_METHOD(char *, find_first, (const char *s, int c));
702// find char in string, from the right
703DECLARE_METHOD(char *, find_last, (const char *s, int c));
704
705// compare two NUL-terminated byte-strings
707 (const char *a, const char *b, size_t len,
708 bool case_insensitive));
709
710/**
711 Wrapper for std::snprintf()
712 Replace all % in format string with variables from list.
713 Do not use in new code; use std::snprintf() instead.
714
715 @param to buffer to write the result to
716 @param n size of that buffer
717 @param fmt format string
718 @param ap va_list with valuables for all substitutions in format string
719
720 @retval return value of snprintf
721*/
722DECLARE_METHOD(size_t, substitutev,
723 (char *to, size_t n, const char *fmt, va_list ap))
724MY_ATTRIBUTE((format(printf, 3, 0)));
725
726// replace all % in format string with variables from list (std::snprintf())
727DECLARE_METHOD(size_t, substitute, (char *to, size_t n, const char *fmt, ...))
728MY_ATTRIBUTE((format(printf, 3, 4)));
729
730END_SERVICE_DEFINITION(log_builtins_string)
731
732/**
733 Temporary primitives for logging services.
734*/
736// Are we shutting down yet? Windows EventLog needs to know.
737DECLARE_METHOD(size_t, notify_client,
738 (void *thd, uint severity, uint code, char *to, size_t n,
739 const char *format, ...))
740MY_ATTRIBUTE((format(printf, 6, 7)));
741END_SERVICE_DEFINITION(log_builtins_tmp)
742
743/**
744 Syslog/Eventlog functions for logging services.
745*/
746BEGIN_SERVICE_DEFINITION(log_builtins_syseventlog)
748 (const char *name, int option, int facility));
750 (enum loglevel level, const char *msg));
752END_SERVICE_DEFINITION(log_builtins_syseventlog)
753
754#ifdef __cplusplus
755
756#if !defined(LOG_H)
757
758extern SERVICE_TYPE(log_builtins) * log_bi;
759extern SERVICE_TYPE(log_builtins_string) * log_bs;
760
761#define log_line_init log_bi->line_init
762#define log_line_exit log_bi->line_exit
763#define log_line_item_set_with_key log_bi->line_item_set_with_key
764#define log_line_item_set log_bi->line_item_set
765#define log_line_item_types_seen log_bi->line_item_types_seen
766#define log_line_submit log_bi->line_submit
767#define log_set_int log_bi->item_set_int
768#define log_set_float log_bi->item_set_float
769#define log_set_lexstring log_bi->item_set_lexstring
770#define log_set_cstring log_bi->item_set_cstring
771#define log_line_set_flag log_bi->line_set_flag
772#define log_malloc log_bs->malloc
773#define log_free log_bs->free
774#define log_msg log_bs->substitutev
775#define error_msg_by_errcode log_bi->errmsg_by_errcode
776#define error_code_by_errsymbol log_bi->errcode_by_errsymbol
777#else
778
779#include "sql/derror.h"
780
781#define log_malloc(s) my_malloc(0, (s), MYF(0))
782#define log_free my_free
783#define log_msg vsnprintf
784#define error_msg_by_errcode error_message_for_error_log
785#define error_code_by_errsymbol mysql_symbol_to_errno
786#define log_set_int log_item_set_int
787#define log_set_float log_item_set_float
788#define log_set_lexstring log_item_set_lexstring
789#define log_set_cstring log_item_set_cstring
790
791#endif // LOG_H
792
793#ifndef DISABLE_ERROR_LOGGING
794
795#if defined(LOG_COMPONENT_TAG)
796
797#define LogErr(severity, ecode, ...) \
798 LogEvent() \
799 .prio(severity) \
800 .errcode(ecode) \
801 .subsys(LOG_SUBSYSTEM_TAG) \
802 .component(LOG_COMPONENT_TAG) \
803 .source_line(__LINE__) \
804 .source_file(MY_BASENAME) \
805 .function(__FUNCTION__) \
806 .lookup(ecode, ##__VA_ARGS__)
807
808#ifdef HAVE_LOG_DIAGNOSTIC
809#define LogDiag(severity, ecode, ...) \
810 LogEvent() \
811 .prio(severity) \
812 .errcode(ecode) \
813 .subsys(LOG_SUBSYSTEM_TAG) \
814 .component(LOG_COMPONENT_TAG) \
815 .source_line(__LINE__) \
816 .source_file(MY_BASENAME) \
817 .function(__FUNCTION__) \
818 .type(LOG_TYPE_DIAG) \
819 .lookup(ecode, ##__VA_ARGS__)
820#else
821#define LogDiag(...)
822#endif /* HAVE_LOG_DIAGNOSTIC */
823
824#define LogComponentErr(severity, ecode, ...) \
825 LogEvent() \
826 .prio(severity) \
827 .errcode(ecode) \
828 .subsys(LOG_SUBSYSTEM_TAG) \
829 .component("component:" LOG_COMPONENT_TAG) \
830 .source_line(__LINE__) \
831 .source_file(MY_BASENAME) \
832 .function(__FUNCTION__) \
833 .lookup_quoted(ecode, "Component " LOG_COMPONENT_TAG " reported", \
834 ##__VA_ARGS__)
835
836#define LogPluginErr(severity, ecode, ...) \
837 LogEvent() \
838 .prio(severity) \
839 .errcode(ecode) \
840 .subsys(LOG_SUBSYSTEM_TAG) \
841 .component("plugin:" LOG_COMPONENT_TAG) \
842 .source_line(__LINE__) \
843 .source_file(MY_BASENAME) \
844 .function(__FUNCTION__) \
845 .lookup_quoted(ecode, "Plugin " LOG_COMPONENT_TAG " reported", \
846 ##__VA_ARGS__)
847
848#define LogPluginErrV(severity, ecode, vl) \
849 LogEvent() \
850 .prio(severity) \
851 .errcode(ecode) \
852 .subsys(LOG_SUBSYSTEM_TAG) \
853 .component("plugin:" LOG_COMPONENT_TAG) \
854 .source_line(__LINE__) \
855 .source_file(MY_BASENAME) \
856 .function(__FUNCTION__) \
857 .lookup_quotedv(ecode, "Plugin " LOG_COMPONENT_TAG " reported", vl)
858
859#define LogPluginErrMsg(severity, ecode, ...) \
860 LogEvent() \
861 .prio(severity) \
862 .errcode(ecode) \
863 .subsys(LOG_SUBSYSTEM_TAG) \
864 .component("plugin:" LOG_COMPONENT_TAG) \
865 .source_line(__LINE__) \
866 .source_file(MY_BASENAME) \
867 .function(__FUNCTION__) \
868 .message_quoted("Plugin " LOG_COMPONENT_TAG " reported", ##__VA_ARGS__)
869
870#else
871
872#define LogErr(severity, ecode, ...) \
873 LogEvent() \
874 .prio(severity) \
875 .errcode(ecode) \
876 .subsys(LOG_SUBSYSTEM_TAG) \
877 .source_line(__LINE__) \
878 .source_file(MY_BASENAME) \
879 .function(__FUNCTION__) \
880 .lookup(ecode, ##__VA_ARGS__)
881
882#ifdef HAVE_LOG_DIAGNOSTIC
883#define LogDiag(severity, ecode, ...) \
884 LogEvent() \
885 .prio(severity) \
886 .errcode(ecode) \
887 .subsys(LOG_SUBSYSTEM_TAG) \
888 .source_line(__LINE__) \
889 .source_file(MY_BASENAME) \
890 .function(__FUNCTION__) \
891 .type(LOG_TYPE_DIAG) \
892 .lookup(ecode, ##__VA_ARGS__)
893#else
894#define LogDiag(...)
895#endif /* HAVE_LOG_DIAGNOSTIC */
896#endif
897
898#else
899
900inline void dummy_log_message(longlong severity [[maybe_unused]],
901 longlong ecode [[maybe_unused]], ...) {
902 return;
903}
904
905#define LogErr(severity, ecode, ...) \
906 dummy_log_message(severity, ecode, ##__VA_ARGS__)
907
908#define LogPluginErr(severity, ecode, ...) \
909 dummy_log_message(severity, ecode, ##__VA_ARGS__)
910#define LogPluginErrV(severity, ecode, ...) \
911 dummy_log_message(severity, ecode, ##__VA_ARGS__)
912#define LogPluginErrMsg(severity, ecode, ...) \
913 dummy_log_message(severity, ecode, ##__VA_ARGS__)
914
915#endif // DISABLE_ERROR_LOGGING
916
917/**
918 Modular logger: fluid API. Server-internal. Lets you use safe and
919 expressive syntax, like so:
920
921 LogEvent(LOG_TYPE_ERROR).prio(INFORMATION_LEVEL).message("Meow! %d", 4711);
922*/
923
924class LogEvent {
925 private:
926 log_line *ll; // Temporary allocation to hold a log-event.
927 char *msg; // Temporary allocation to hold a message.
928 const char *msg_tag;
929 bool have_msg; // Was a message set in `msg` using set_message()?
930
931 /**
932 Set MySQL error-code if none has been set yet.
933
934 @param errcode the error code (not operating system errno!)
935
936 @retval true an error occurred, value not set (OOM?)
937 @retval false value was set without incident, or did not need to be set
938 */
940 if (ll == nullptr) return true;
941
945 }
946 return false; // already set, that's OK then
947 }
948
949 /**
950 Set the error message.
951
952 @param fmt format string. % substitution will be performed.
953 @param ap va_list of the arguments for % substitution.
954 */
955 void set_message(const char *fmt, va_list ap)
956 MY_ATTRIBUTE((format(printf, 2, 0)));
957
958 /**
959 Set the error message (by MySQL error code).
960 The actual message will be looked up using this errcode.
961 As the message is a printf-style format string, % substitution
962 will be performed.
963
964 @param errcode MySQL error code to fetch the message string for
965 @param ap va_list of the arguments for % substitution.
966 */
967 void set_message_by_errcode(longlong errcode, va_list ap);
968
969 public:
970 /**
971 Destructor automatically sends the event on.
972 It is auto-free()d after processing.
973 */
975 if (ll != nullptr) {
976 log_line_submit(this->ll);
978 /*
979 If a message was set on the LogEvent using set_message,
980 the message became part of a log_item on the log_line.
981 have_msg is true. The log_line's log_items were released
982 in log_line_submit(). Null `msg` here to prevent double-free.
983
984 On the other hand, if set_message() was not used, the
985 convenience buffer was never associated with the log_line,
986 and therefore wasn't freed when the log_line was submitted.
987 In that case, we'll leave the pointer intact for clean-up
988 further down.
989 */
990 if (have_msg) msg = nullptr;
991 }
992
993 /*
994 If set_message() attached the buffer `msg` to the log_line,
995 the allocation has either been freed in log_line_submit()
996 above, or it is now owned by someone who stole it using steal().
997 In either case, msg==nullptr and we do nothing here.
998 */
999 if (msg != nullptr) log_free(msg);
1000 }
1001
1002 /**
1003 "Full customization" constructor. Use one of the LogErr() macro
1004 where possible; it's there to help you remember the minimum set
1005 of particles and their data-types. Be prepared for stern looks
1006 from your reviewers if you use this constructor except for external
1007 (loadable) services that have no error messages registered with the
1008 server, and therefore need to submit them free-form.
1009 */
1011 have_msg = false;
1012 if ((ll = log_line_init()) != nullptr) {
1013 if ((msg = (char *)log_malloc(LOG_BUFF_MAX)) == nullptr) {
1015 ll = nullptr;
1016 }
1017 } else
1018 msg = nullptr;
1019 msg_tag = nullptr;
1020 }
1021
1022 /**
1023 Save the log-event allocated by LogEvent().
1024
1025 LogEvent() internally represents the log-event in a log_line
1026 structure it allocates. steal() saves this pointer to the
1027 method's argument. The pointer in the LogEvent() is then
1028 cleared to prevent the destructor from freeing the log_line.
1029 Freeing allocated memory is now the caller's responsibility:
1030
1031 log_line *ll;
1032 LogEvent().prio(SYSTEM_LEVEL).message("Hi %s!", user).steal(&ll);
1033
1034 // Do some things with the event ...
1035
1036 log_line_item_free_all(ll);
1037 log_line_exit(ll);
1038
1039 If a message was set, the message buffer pointed to by `msg`
1040 becomes part of the log_line and is released on
1041 log_line_item_free_all() (or equivalent).
1042
1043 If no message was set, the message buffer is released when
1044 the LogEvent's destructor is called.
1045
1046 Note that verbatim() does NOT copy its argument to the
1047 LogEvent's internal allocation `msg`.
1048 Hence the life-cycle management of verbatim()'s argument
1049 would be up to the developer. When using steal(), using it
1050 with one of the set_message() wrappers is generally preferable:
1051
1052 LogEvent().message("%s", my_verbatim_string).steal(&ll);
1053
1054 @param save_to where to save the pointer to the log-event
1055 */
1056 void steal(log_line **save_to) {
1057 *save_to = ll;
1058 ll = nullptr;
1059 /*
1060 If the message was set, the allocation is now part of a log_item
1061 on the log_line. Thus, it is now owned by the called and will
1062 be released when they release the log_items on the log_line.
1063 In that case, we null our pointer to it so we won't double-free
1064 the allocation.
1065
1066 Conversely, if the buffer exists, but hasn't become part of
1067 the log_line through use of a set_message() wrapper, we'll hold
1068 on to the pointer so the empty buffer is released when we dest
1069 the LogEvent().
1070 */
1071 if (have_msg) msg = nullptr;
1072 }
1073
1074 /**
1075 Set log type.
1076
1077 @param val the log type (LOG_TYPE_ERROR)
1078
1079 @retval the LogEvent, for easy fluent-style chaining.
1080 */
1083 return *this;
1084 }
1085
1086 /**
1087 Append a numeric error code
1088
1089 @param val the MySQL error code (not operating system errno!).
1090
1091 @retval the LogEvent, for easy fluent-style chaining.
1092 */
1095 return *this;
1096 }
1097
1098 /**
1099 Append a (string) error symbol
1100
1101 @param val error symbol. NTBS.
1102
1103 @retval the LogEvent, for easy fluent-style chaining.
1104 */
1105 LogEvent &errsymbol(const char *val) {
1107 return *this;
1108 }
1109
1110 /**
1111 Append a (string) SQL state
1112
1113 @param val the SQLstate. NTBS.
1114
1115 @retval the LogEvent, for easy fluent-style chaining.
1116 */
1117 LogEvent &sqlstate(const char *val) {
1119 return *this;
1120 }
1121
1122 /**
1123 Append a numeric (operating system, as opposed to MySQL) error number.
1124
1125 @param val the operating system errno.
1126
1127 @retval the LogEvent, for easy fluent-style chaining.
1128 */
1131 return *this;
1132 }
1133
1134 /**
1135 Append a textual (operating system, as opposed to MySQL) error message,
1136 vulgo, strerror()
1137
1138 @param val the error message returned by the operating system. NTBS.
1139
1140 @retval the LogEvent, for easy fluent-style chaining.
1141 */
1142 LogEvent &os_errmsg(const char *val) {
1144 return *this;
1145 }
1146
1147 /**
1148 Which source file was the problem detected in?
1149
1150 @param val the source file's name. NTBS.
1151
1152 @retval the LogEvent, for easy fluent-style chaining.
1153 */
1154 LogEvent &source_file(const char *val) {
1156 return *this;
1157 }
1158
1159 /**
1160 Which line in the source file was the problem detected on?
1161
1162 @param val the line number.
1163
1164 @retval the LogEvent, for easy fluent-style chaining.
1165 */
1168 return *this;
1169 }
1170
1171 /**
1172 Which function in the source was the problem detected in?
1173
1174 @param val the function's name. NTBS.
1175
1176 @retval the LogEvent, for easy fluent-style chaining.
1177 */
1178 LogEvent &function(const char *val) {
1180 return *this;
1181 }
1182
1183 /**
1184 Which subsystem in the source was the problem detected in?
1185 ("Repl"/"InnoDB"/"Server")
1186
1187 @param val the subsystem. NTBS.
1188
1189 @retval the LogEvent, for easy fluent-style chaining.
1190 */
1191 LogEvent &subsys(const char *val) {
1192 if (val != nullptr)
1194 return *this;
1195 }
1196
1197 /**
1198 Which component in the source was the problem detected in?
1199 This should be the same string that is given to the
1200 component/service framework.
1201
1202 @param val the component. NTBS.
1203
1204 @retval the LogEvent, for easy fluent-style chaining.
1205 */
1206 LogEvent &component(const char *val) {
1207 if (val != nullptr)
1209 return *this;
1210 }
1211
1212 /**
1213 What user were we working for at the time of the issue?
1214
1215 @param val the user part (of "user@host"). LEX_CSTRING.
1216
1217 @retval the LogEvent, for easy fluent-style chaining.
1218 */
1221 val.length);
1222 return *this;
1223 }
1224
1225 /**
1226 What user were we working for at the time of the issue?
1227
1228 @param val the user part (of "user@host"). NTBS.
1229
1230 @retval the LogEvent, for easy fluent-style chaining.
1231 */
1232 LogEvent &user(const char *val) {
1234 return *this;
1235 }
1236
1237 /**
1238 Whose session did the issue appear in?
1239
1240 @param val the host part (of "user@host"). LEX_CSTRING.
1241
1242 @retval the LogEvent, for easy fluent-style chaining.
1243 */
1246 val.length);
1247 return *this;
1248 }
1249
1250 /**
1251 Whose session did the issue appear in?
1252
1253 @param val the host part (of "user@host"). NTBS.
1254
1255 @retval the LogEvent, for easy fluent-style chaining.
1256 */
1257 LogEvent &host(const char *val) {
1259 return *this;
1260 }
1261
1262 /**
1263 What thread / "connection ID" was the issue detected in?
1264
1265 @param val the thread_ID of the session the issue appeared in
1266
1267 @retval the LogEvent, for easy fluent-style chaining.
1268 */
1271 return *this;
1272 }
1273
1274 /**
1275 What query apparently caused the issue?
1276
1277 @param val the query_ID of the offending query
1278
1279 @retval the LogEvent, for easy fluent-style chaining.
1280 */
1283 return *this;
1284 }
1285
1286 /**
1287 What table were we working on?
1288
1289 @param val the table's name/alias. NTBS.
1290
1291 @retval the LogEvent, for easy fluent-style chaining.
1292 */
1293 LogEvent &table_name(const char *val) {
1295 return *this;
1296 }
1297
1298 /**
1299 Set error message priority.
1300 Assign one of ERROR_LEVEL, WARNING_LEVEL, INFORMATION_LEVEL.
1301 log-writers and other sinks should use this value (rather
1302 than that of LOG_ITEM_LOG_EPRIO):
1303
1304 - file writers should use the value to determine
1305 what label to write (perhaps by submitting it to label_from_prio())
1306
1307 - sinks that submit the event data to a sub-system outside of
1308 the MySQL server (such as syslog, EventLog, systemd journal, etc.)
1309 should translate this value into a priority/log level understood
1310 by that target subsystem.
1311
1312 @param val The priority for this LogEvent.
1313
1314 @retval the LogEvent, for easy fluent-style chaining.
1315 */
1318 return *this;
1319 }
1320
1321 /**
1322 Set a label (usually "warning"/"error"/"information").
1323 Will be derived from prio if not set explicitly.
1324 Some log services may ignore custom labels.
1325
1326 @param val the (custom) label to set
1327
1328 @retval the LogEvent, for easy fluent-style chaining.
1329 */
1330 LogEvent &label(const char *val) {
1332 return *this;
1333 }
1334
1335 /**
1336 Add a message to the event, verbatim (i.e. with no % substitutions).
1337 This is an analog of message("%s", message); it can be used when
1338 message may contain user input or a message from another subsystem
1339 that could contain % that must not be interpreted as an invitation
1340 to do % substitutions.
1341
1342 If you use this in a context other than an external service that
1343 has no messages registered with the server, your reviewers will
1344 say unkind things about you. Use registered messages and their
1345 error codes wherever possible!
1346
1347 Combining verbatim() with steal() is discouraged as it burdens
1348 the developer with the life-cycle management of verbatim's
1349 argument. This is a result of verbatim() using its argument
1350 verbatim, rather than setting it up in the LogEvent's internal
1351 allocation `msg` using set_message(). Hence, the LogEvent has
1352 no copy of the message, which is an optimization for the
1353 common, non-steal() case.
1354
1355 @param msg_arg the message. % substitution will not happen.
1356
1357 @retval the LogEvent, for easy fluent-style chaining.
1358 */
1359 LogEvent &verbatim(const char *msg_arg) {
1361 return *this;
1362 }
1363
1364 /**
1365 Fill in a format string by substituting the % with the given
1366 arguments, then add the result as the event's message.
1367 This should be used very sparingly; use registered messages
1368 and their error codes wherever possible!
1369
1370 @param fmt message (treated as a printf-style format-string,
1371 so % substitution will happen)
1372 @param ap valist to satisfy any % in the message
1373
1374 @retval the LogEvent, for easy fluent-style chaining.
1375 */
1376 LogEvent &messagev(const char *fmt, va_list ap)
1377 MY_ATTRIBUTE((format(printf, 2, 0))) {
1378 set_message(fmt, ap);
1379 return *this;
1380 }
1381
1382 /**
1383 Fill in a format string by substituting the % with the given
1384 arguments, then add the result as the event's message.
1385
1386 If you use this in a context other than an external service that
1387 has no messages registered with the server, your reviewers will
1388 say unkind things about you. Use registered messages and their
1389 error codes wherever possible!
1390
1391 @param fmt message (treated as a printf-style format-string,
1392 so % substitution will happen)
1393 @param ... varargs to satisfy any % in the message
1394
1395 @retval the LogEvent, for easy fluent-style chaining.
1396 */
1397 LogEvent &message(const char *fmt, ...) MY_ATTRIBUTE((format(printf, 2, 3)));
1398
1399 /**
1400 Fill in a format string by substituting the % with the given
1401 arguments and tag, then add the result as the event's message.
1402
1403 @param tag Tag to prefix to message.
1404 @param fmt message (treated as a printf-style format-string,
1405 so % substitution will happen)
1406 @param ... varargs to satisfy any % in the message
1407
1408 @retval the LogEvent, for easy fluent-style chaining.
1409 */
1410 LogEvent &message_quoted(const char *tag, const char *fmt, ...)
1411 MY_ATTRIBUTE((format(printf, 3, 4))) {
1412 msg_tag = tag;
1413
1414 va_list args;
1415 va_start(args, fmt);
1416 set_message(fmt, args);
1417 va_end(args);
1418
1419 return *this;
1420 }
1421
1422 /**
1423 Find an error message by its MySQL error code.
1424 Substitute the % in that message with the given
1425 arguments, then add the result as the event's message.
1426
1427 @param errcode MySQL error code for the message in question,
1428 e.g. ER_STARTUP
1429 @param ... varargs to satisfy any % in the message
1430
1431 @retval the LogEvent, for easy fluent-style chaining.
1432 */
1434 va_list args;
1435 va_start(args, errcode);
1437 va_end(args);
1438
1439 return *this;
1440 }
1441
1442 /**
1443 Find an error message by its MySQL error code. Substitute the % in that
1444 message with the given arguments list, then add the result as the event's
1445 message.
1446
1447 @param errcode MySQL error code for the message in question,
1448 e.g. ER_STARTUP
1449 @param args varargs to satisfy any % in the message
1450
1451 @retval the LogEvent, for easy fluent-style chaining.
1452 */
1455
1456 return *this;
1457 }
1458
1459 LogEvent &lookup_quoted(longlong errcode, const char *tag, ...) {
1460 msg_tag = tag;
1461
1462 va_list args;
1463 va_start(args, tag);
1465 va_end(args);
1466
1467 return *this;
1468 }
1469
1470 LogEvent &lookup_quotedv(longlong errcode, const char *tag, va_list vl) {
1471 msg_tag = tag;
1473
1474 return *this;
1475 }
1476
1477 /**
1478 Add a ad hoc integer value with the given key.
1479
1480 @param key user-defined key (i.e. not wellknown). NTBS.
1481 @param val value.
1482
1483 @retval the LogEvent, for easy fluent-style chaining.
1484 */
1485 LogEvent &int_value(const char *key, longlong val) {
1488 val);
1489 return *this;
1490 }
1491
1492 /**
1493 Add a ad hoc (not "well-known") float value with the given key.
1494
1495 @param key user-defined key (i.e. not wellknown). NTBS.
1496 @param val value.
1497
1498 @retval the LogEvent, for easy fluent-style chaining.
1499 */
1500 LogEvent &float_value(const char *key, double val) {
1503 val);
1504 return *this;
1505 }
1506
1507 /**
1508 Add a ad hoc string value with the given key.
1509
1510 @param key user-defined key (i.e. not wellknown). NTBS.
1511 @param val value.
1512 @param len length in bytes of the value.
1513
1514 @retval the LogEvent, for easy fluent-style chaining.
1515 */
1516 LogEvent &string_value(const char *key, const char *val, size_t len) {
1520 val, len);
1521 return *this;
1522 }
1523
1524 /**
1525 Add a ad hoc string value with the given key.
1526
1527 @param key user-defined key (i.e. not wellknown). NTBS.
1528 @param val value. NTBS.
1529
1530 @retval the LogEvent, for easy fluent-style chaining.
1531 */
1532 LogEvent &string_value(const char *key, const char *val) {
1536 val);
1537 return *this;
1538 }
1539
1540 /**
1541 Mark log line to skip being additionally emitted as a telemetry log record.
1542
1543 @retval the LogEvent, for easy fluent-style chaining.
1544 */
1547 return *this;
1548 }
1549};
1550
1551inline void LogEvent::set_message_by_errcode(longlong errcode, va_list ap) {
1552 const char *fmt = error_msg_by_errcode((int)errcode);
1553
1554 if ((fmt == nullptr) || (*fmt == '\0')) fmt = "invalid error code";
1555
1557 set_message(fmt, ap);
1558}
1559
1560inline void LogEvent::set_message(const char *fmt, va_list ap) {
1561 if ((ll != nullptr) && (msg != nullptr)) {
1562 char buf[LOG_BUFF_MAX];
1563 if (msg_tag != nullptr) {
1564 snprintf(buf, LOG_BUFF_MAX, "%s: \'%s\'", msg_tag, fmt);
1565 fmt = buf;
1566 }
1567 size_t len = log_msg(msg, LOG_BUFF_MAX, fmt, ap);
1568 if (len >= LOG_BUFF_MAX) {
1569 const char ellipsis[] = " <...>";
1570 len = LOG_BUFF_MAX - 1;
1571 strcpy(&msg[LOG_BUFF_MAX - sizeof(ellipsis)], ellipsis);
1572 }
1573 log_item_data *lid;
1574 lid = log_line_item_set_with_key(this->ll, LOG_ITEM_LOG_MESSAGE, nullptr,
1576 log_set_lexstring(lid, msg, len);
1577 have_msg = true;
1578 }
1579}
1580
1581inline LogEvent &LogEvent::message(const char *fmt, ...) {
1582 va_list args;
1583 va_start(args, fmt);
1584 set_message(fmt, args);
1585 va_end(args);
1586
1587 return *this;
1588}
1589
1590// Methods initialize and de-initialize logging service for plugins.
1591#if defined(MYSQL_DYNAMIC_PLUGIN)
1592
1593/**
1594 Method to de-initialize logging service in plugin.
1595
1596 param[in,out] reg_srv Plugin registry service.
1597 param[in,out] log_bi Error logging service.
1598 param[in,out] log_bs String service for error logging.
1599*/
1600inline void deinit_logging_service_for_plugin(
1601 SERVICE_TYPE(registry) * *reg_srv, SERVICE_TYPE(log_builtins) * *log_bi,
1602 SERVICE_TYPE(log_builtins_string) * *log_bs) {
1603 using log_builtins_t = SERVICE_TYPE_NO_CONST(log_builtins);
1604 using log_builtins_string_t = SERVICE_TYPE_NO_CONST(log_builtins_string);
1605 if (*log_bi)
1606 (*reg_srv)->release(
1607 reinterpret_cast<my_h_service>(const_cast<log_builtins_t *>(*log_bi)));
1608 if (*log_bs)
1609 (*reg_srv)->release(reinterpret_cast<my_h_service>(
1610 const_cast<log_builtins_string_t *>(*log_bs)));
1612 *log_bi = nullptr;
1613 *log_bs = nullptr;
1614 *reg_srv = nullptr;
1615}
1616
1617/**
1618 Method to de-initialize logging service in plugin.
1619
1620 param[in,out] reg_srv Plugin registry service.
1621 param[in,out] log_bi Error logging service.
1622 param[in,out] log_bs String service for error logging.
1623
1624 @retval false Success.
1625 @retval true Failed.
1626*/
1627inline bool init_logging_service_for_plugin(
1628 SERVICE_TYPE(registry) * *reg_srv, SERVICE_TYPE(log_builtins) * *log_bi,
1629 SERVICE_TYPE(log_builtins_string) * *log_bs) {
1630 my_h_service log_srv = nullptr;
1631 my_h_service log_str_srv = nullptr;
1633 if (!(*reg_srv)->acquire("log_builtins.mysql_server", &log_srv) &&
1634 !(*reg_srv)->acquire("log_builtins_string.mysql_server", &log_str_srv)) {
1635 (*log_bi) = reinterpret_cast<SERVICE_TYPE(log_builtins) *>(log_srv);
1636 (*log_bs) =
1637 reinterpret_cast<SERVICE_TYPE(log_builtins_string) *>(log_str_srv);
1638 } else {
1639 deinit_logging_service_for_plugin(reg_srv, log_bi, log_bs);
1640 return true;
1641 }
1642 return false;
1643}
1644
1645#elif defined(EXTRA_CODE_FOR_UNIT_TESTING)
1646
1647/**
1648 Method is used by unit tests.
1649
1650 param[in,out] reg_srv Plugin registry service.
1651 param[in,out] log_bi Error logging service.
1652 param[in,out] log_bs String service for error logging.
1653
1654 @retval false Success.
1655 @retval true Failed.
1656*/
1657inline bool init_logging_service_for_plugin(
1658 SERVICE_TYPE(registry) * *reg_srv [[maybe_unused]],
1659 SERVICE_TYPE(log_builtins) * *log_bi [[maybe_unused]],
1660 SERVICE_TYPE(log_builtins_string) * *log_bs [[maybe_unused]])
1661
1662{
1663 return false;
1664}
1665
1666/**
1667 Method is used by unit tests.
1668
1669 param[in,out] reg_srv Plugin registry service.
1670 param[in,out] log_bi Error logging service.
1671 param[in,out] log_bs String service for error logging.
1672*/
1673inline void deinit_logging_service_for_plugin(
1674 SERVICE_TYPE(registry) * *reg_srv [[maybe_unused]],
1675 SERVICE_TYPE(log_builtins) * *log_bi [[maybe_unused]],
1676 SERVICE_TYPE(log_builtins_string) * *log_bs [[maybe_unused]]) {}
1677
1678#endif // MYSQL_DYNAMIC_PLUGIN
1679
1680#endif // __cplusplus
1681
1682#endif
Modular logger: fluid API.
Definition: log_builtins.h:924
~LogEvent()
Destructor automatically sends the event on.
Definition: log_builtins.h:974
LogEvent & host(const char *val)
Whose session did the issue appear in?
Definition: log_builtins.h:1257
LogEvent & user(const char *val)
What user were we working for at the time of the issue?
Definition: log_builtins.h:1232
LogEvent & string_value(const char *key, const char *val, size_t len)
Add a ad hoc string value with the given key.
Definition: log_builtins.h:1516
LogEvent()
"Full customization" constructor.
Definition: log_builtins.h:1010
char * msg
Definition: log_builtins.h:927
LogEvent & lookup_quoted(longlong errcode, const char *tag,...)
Definition: log_builtins.h:1459
LogEvent & lookup_quotedv(longlong errcode, const char *tag, va_list vl)
Definition: log_builtins.h:1470
bool have_msg
Definition: log_builtins.h:929
LogEvent & prio(longlong val)
Set error message priority.
Definition: log_builtins.h:1316
LogEvent & subsys(const char *val)
Which subsystem in the source was the problem detected in? ("Repl"/"InnoDB"/"Server")
Definition: log_builtins.h:1191
LogEvent & errcode(longlong val)
Append a numeric error code.
Definition: log_builtins.h:1093
LogEvent & source_file(const char *val)
Which source file was the problem detected in?
Definition: log_builtins.h:1154
bool set_errcode(longlong errcode)
Set MySQL error-code if none has been set yet.
Definition: log_builtins.h:939
LogEvent & os_errno(longlong val)
Append a numeric (operating system, as opposed to MySQL) error number.
Definition: log_builtins.h:1129
LogEvent & type(enum_log_type val)
Set log type.
Definition: log_builtins.h:1081
LogEvent & thread_id(longlong val)
What thread / "connection ID" was the issue detected in?
Definition: log_builtins.h:1269
LogEvent & os_errmsg(const char *val)
Append a textual (operating system, as opposed to MySQL) error message, vulgo, strerror()
Definition: log_builtins.h:1142
LogEvent & component(const char *val)
Which component in the source was the problem detected in? This should be the same string that is giv...
Definition: log_builtins.h:1206
LogEvent & lookupv(longlong errcode, va_list args)
Find an error message by its MySQL error code.
Definition: log_builtins.h:1453
const char * msg_tag
Definition: log_builtins.h:928
LogEvent & verbatim(const char *msg_arg)
Add a message to the event, verbatim (i.e.
Definition: log_builtins.h:1359
LogEvent & message(const char *fmt,...)
Fill in a format string by substituting the % with the given arguments, then add the result as the ev...
Definition: log_builtins.h:1581
LogEvent & errsymbol(const char *val)
Append a (string) error symbol.
Definition: log_builtins.h:1105
void steal(log_line **save_to)
Definition: log_builtins.h:1056
LogEvent & table_name(const char *val)
What table were we working on?
Definition: log_builtins.h:1293
LogEvent & label(const char *val)
Set a label (usually "warning"/"error"/"information").
Definition: log_builtins.h:1330
LogEvent & source_line(longlong val)
Which line in the source file was the problem detected on?
Definition: log_builtins.h:1166
LogEvent & query_id(longlong val)
What query apparently caused the issue?
Definition: log_builtins.h:1281
LogEvent & message_quoted(const char *tag, const char *fmt,...)
Fill in a format string by substituting the % with the given arguments and tag, then add the result a...
Definition: log_builtins.h:1410
LogEvent & messagev(const char *fmt, va_list ap)
Fill in a format string by substituting the % with the given arguments, then add the result as the ev...
Definition: log_builtins.h:1376
LogEvent & sqlstate(const char *val)
Append a (string) SQL state.
Definition: log_builtins.h:1117
LogEvent & float_value(const char *key, double val)
Add a ad hoc (not "well-known") float value with the given key.
Definition: log_builtins.h:1500
log_line * ll
Definition: log_builtins.h:926
LogEvent & int_value(const char *key, longlong val)
Add a ad hoc integer value with the given key.
Definition: log_builtins.h:1485
LogEvent & user(LEX_CSTRING val)
What user were we working for at the time of the issue?
Definition: log_builtins.h:1219
LogEvent & string_value(const char *key, const char *val)
Add a ad hoc string value with the given key.
Definition: log_builtins.h:1532
void set_message_by_errcode(longlong errcode, va_list ap)
Set the error message (by MySQL error code).
Definition: log_builtins.h:1551
void set_message(const char *fmt, va_list ap)
Set the error message.
Definition: log_builtins.h:1560
LogEvent & lookup(longlong errcode,...)
Find an error message by its MySQL error code.
Definition: log_builtins.h:1433
LogEvent & host(LEX_CSTRING val)
Whose session did the issue appear in?
Definition: log_builtins.h:1244
LogEvent & no_telemetry()
Mark log line to skip being additionally emitted as a telemetry log record.
Definition: log_builtins.h:1545
Specifies macros to define Components.
static char buf[MAX_BUF]
Definition: conf_to_src.cc:73
void write(W *w, const T &t, const char *key, size_t key_sz)
Definition: sdi_impl.h:335
struct my_h_service_imp * my_h_service
A handle type for acquired Service.
Definition: registry.h:33
#define malloc(A)
Definition: lexyy.cc:914
#define free(A)
Definition: lexyy.cc:915
Error logging, slow query logging, general query logging: If it's server-internal,...
#define log_line_init
Definition: log_builtins.h:761
#define log_line_item_types_seen
Definition: log_builtins.h:765
const mysql_service_log_builtins_string_t * log_bs
string built-ins
Definition: connection_control.cc:42
void log_line_process_hook_set(log_line_processor llp)
Set the log-event processor.
Definition: log_builtins.cc:126
#define log_set_cstring
Definition: log_builtins.h:770
#define log_set_float
Definition: log_builtins.h:768
log_line_processor log_line_process_hook_get(void)
Get current log-event processor.
Definition: log_builtins.cc:140
#define log_malloc
Definition: log_builtins.h:772
#define log_line_set_flag
Definition: log_builtins.h:771
#define log_line_exit
Definition: log_builtins.h:762
#define log_line_submit
Definition: log_builtins.h:766
#define log_line_item_set
Definition: log_builtins.h:764
#define log_set_int
Definition: log_builtins.h:767
#define log_msg
Definition: log_builtins.h:774
#define error_msg_by_errcode
Definition: log_builtins.h:775
#define log_free
Definition: log_builtins.h:773
bool(* log_line_processor)(log_line *ll)
This defines built-in functions for use by logging services.
Definition: log_builtins.h:56
#define log_line_item_set_with_key
Definition: log_builtins.h:763
const mysql_service_log_builtins_t * log_bi
accessor built-ins
Definition: connection_control.cc:41
#define log_set_lexstring
Definition: log_builtins.h:769
enum enum_log_service_error log_service_error
Error codes.
@ LOG_LINE_EMIT_TELEMETRY
emit log line as telemetry record
Definition: log_shared.h:162
uint64 log_line_flags_mask
a bit mask with flags describing a log line
Definition: log_shared.h:231
#define LOG_BUFF_MAX
advisory.
Definition: log_shared.h:234
enum enum_log_item_class log_item_class
enum_log_type
log_type – which log to send data to check vs enum_log_table_type and LOG_FILE/LOG_TABLE/LOG_NONE
Definition: log_shared.h:66
@ LOG_ITEM_SRV_COMPONENT
log called from component ...
Definition: log_shared.h:137
@ LOG_ITEM_SRC_FUNC
log called from function ...
Definition: log_shared.h:135
@ LOG_ITEM_LOG_LABEL
label, unless auto-derived
Definition: log_shared.h:144
@ LOG_ITEM_SQL_QUERY_ID
query ID
Definition: log_shared.h:141
@ LOG_ITEM_SQL_ERRSYMBOL
mysql error code (symbolic)
Definition: log_shared.h:129
@ LOG_ITEM_GEN_FLOAT
float not otherwise specified
Definition: log_shared.h:152
@ LOG_ITEM_LOG_TYPE
error log, etc.
Definition: log_shared.h:127
@ LOG_ITEM_SRC_FILE
log called from file ...
Definition: log_shared.h:133
@ LOG_ITEM_SQL_TABLE_NAME
table name
Definition: log_shared.h:142
@ LOG_ITEM_MSC_USER
offending thread owned by ...
Definition: log_shared.h:138
@ LOG_ITEM_LOG_MESSAGE
the message, format string
Definition: log_shared.h:146
@ LOG_ITEM_GEN_INTEGER
integer not otherwise specified
Definition: log_shared.h:153
@ LOG_ITEM_LOG_PRIO
log priority (error, warn, ...)
Definition: log_shared.h:143
@ LOG_ITEM_SRV_SUBSYS
log called from subsystem ...
Definition: log_shared.h:136
@ LOG_ITEM_SYS_ERRNO
OS errno.
Definition: log_shared.h:131
@ LOG_ITEM_SQL_ERRCODE
mysql error code (numeric)
Definition: log_shared.h:128
@ LOG_ITEM_SRV_THREAD
connection ID
Definition: log_shared.h:140
@ LOG_ITEM_SRC_LINE
log called from line ...
Definition: log_shared.h:134
@ LOG_ITEM_GEN_LEX_STRING
lex string not otherwise specified
Definition: log_shared.h:154
@ LOG_ITEM_MSC_HOST
responsible user on host ...
Definition: log_shared.h:139
@ LOG_ITEM_SYS_STRERROR
OS strerror()
Definition: log_shared.h:132
@ LOG_ITEM_SQL_STATE
SQL state.
Definition: log_shared.h:130
@ LOG_ITEM_FREE_NONE
Definition: log_shared.h:185
@ LOG_ITEM_FREE_VALUE
Definition: log_shared.h:187
enum enum_log_item_type log_item_type
item_type – what to log
uint64 log_item_type_mask
a bit mask of log_types.
Definition: log_shared.h:222
static int log_type
Definition: mi_log.cc:47
static mi_bit_type mask[]
Definition: mi_packrec.cc:141
Header for compiler-dependent features.
unsigned long long int ulonglong
Definition: my_inttypes.h:56
long long int longlong
Definition: my_inttypes.h:55
uint32_t uint32
Definition: my_inttypes.h:67
loglevel
Definition: my_loglevel.h:41
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
Definition: buf0block_hint.cc:30
constexpr value_type timestamp
Definition: classic_protocol_constants.h:278
Definition: os0file.h:89
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:76
char * strndup(const char *s, size_t n)
The strndup() function returns a pointer to a new string which is a duplicate of the string s,...
Definition: wrapper_functions.h:123
stdx::expected< void, std::error_code > close(file_handle_type native_handle)
close file handle.
Definition: file.h:239
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
stdx::expected< int, std::error_code > open(const char *fname, int flags, mode_t mode) noexcept
Definition: file_handle.cc:79
required string key
Definition: replication_asynchronous_connection_failover.proto:60
static int compare(size_t a, size_t b)
Function to compare two size_t integers for their relative order.
Definition: rpl_utility.cc:107
#define DECLARE_METHOD(retval, name, args)
Declares a method as a part of the Service definition.
Definition: service.h:103
#define SERVICE_TYPE(name)
Generates the standard Service type name.
Definition: service.h:76
#define END_SERVICE_DEFINITION(name)
A macro to end the last Service definition started with the BEGIN_SERVICE_DEFINITION macro.
Definition: service.h:91
#define SERVICE_TYPE_NO_CONST(name)
Generates the standard Service type name.
Definition: service.h:71
#define BEGIN_SERVICE_DEFINITION(name)
Declares a new Service.
Definition: service.h:86
Specifies macros to define Service Implementations.
Declaration of the registry plugin service.
const mysql_service_registry_t * mysql_plugin_registry_acquire()
Returns a new reference to the "registry" service.
Definition: plugin_registry_service.cc:47
int mysql_plugin_registry_release(const mysql_service_registry_t *)
Releases a registry service reference.
Definition: plugin_registry_service.cc:75
case opt name
Definition: sslopt-case.h:29
Definition: mysql_lex_string.h:40
const char * str
Definition: mysql_lex_string.h:41
size_t length
Definition: mysql_lex_string.h:42
Iterator over the key/value pairs of a log_line.
Definition: keyring_log_builtins_definition.cc:64
Definition: log_shared.h:202
log_line ("log event")
Definition: keyring_log_builtins_definition.cc:72
static const mysql_service_registry_t * reg_srv
Initialize parameters required for error logging.
Definition: test_plugin.cc:62
Definition: log_shared.h:191
int n
Definition: xcom_base.cc:509