Rechercher dans le manuel MySQL
29.2.4.11 Writing Protocol Trace Plugins
MySQL supports the use of protocol trace plugins: client-side plugins that implement tracing of communication between a client and the server that takes place using the client/server protocol.
29.2.4.11.1 Using the Test Protocol Trace Plugin
MySQL includes a test protocol trace plugin that serves to illustrate the information available from such plugins, and as a guide to writing other protocol trace plugins. To see how the test plugin works, use a MySQL source distribution; binary distributions are built with the test plugin disabled.
Enable the test protocol trace plugin by configuring MySQL
with the
WITH_TEST_TRACE_PLUGIN
CMake option enabled. This causes the
test trace plugin to be built and MySQL client programs to
load it, but the plugin has no effect by default. Control
the plugin using these environment variables:
MYSQL_TEST_TRACE_DEBUG
: Set this variable to a value other than 0 to cause the test plugin to produce diagnostic output onstderr
.MYSQL_TEST_TRACE_CRASH
: Set this variable to a value other than 0 to cause the test plugin to abort the client program if it detects an invalid trace event.
Diagnostic output from the test protocol trace plugin can disclose passwords and other sensitive information.
Given a MySQL installation built from source with the test plugin enabled, you can see a trace of the communication between the mysql client and the MySQL server as follows:
shell> export MYSQL_TEST_TRACE_DEBUG=1
shqll> mysql
test_trace: Test trace plugin initialized
test_trace: Starting tracing in stage CONNECTING
test_trace: stage: CONNECTING, event: CONNECTING
test_trace: stage: CONNECTING, event: CONNECTED
test_trace: stage: WAIT_FOR_INIT_PACKET, event: READ_PACKET
test_trace: stage: WAIT_FOR_INIT_PACKET, event: PACKET_RECEIVED
test_trace: packet received: 87 bytes
0A 35 2E 37 2E 33 2D 6D 31 33 2D 64 65 62 75 67 .5.7.3-m13-debug
2D 6C 6F 67 00 04 00 00 00 2B 7C 4F 55 3F 79 67 -log.....+|OU?yg
test_trace: 004: stage: WAIT_FOR_INIT_PACKET, event: INIT_PACKET_RECEIVED
test_trace: 004: stage: AUTHENTICATE, event: AUTH_PLUGIN
test_trace: 004: Using authentication plugin: mysql_native_password
test_trace: 004: stage: AUTHENTICATE, event: SEND_AUTH_RESPONSE
test_trace: 004: sending packet: 188 bytes
85 A6 7F 00 00 00 00 01 21 00 00 00 00 00 00 00 .?......!.......
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
...
mysql> quit
test_trace: 008: stage: READY_FOR_COMMAND, event: SEND_COMMAND
test_trace: 008: QUIT
test_trace: 008: stage: READY_FOR_COMMAND, event: PACKET_SENT
test_trace: 008: packet sent: 0 bytes
test_trace: 008: stage: READY_FOR_COMMAND, event: DISCONNECTED
test_trace: 008: Connection closed
test_trace: 008: Tracing connection has ended
Bye
test_trace: Test trace plugin de-initialized
To disable trace output, do this:
shell> MYSQL_TEST_TRACE_DEBUG=
To use your own protocol trace plugins, you must configure
MySQL with the
WITH_TEST_TRACE_PLUGIN
CMake option
disabled because only one protocol
trace plugin can be loaded at a time and an error occurs
for attempts to load a second one. If you have already
built MySQL with the test protocol trace plugin enabled to
see how it works, you must rebuild MySQL without it before
you can use your own plugins.
This section discusses how to write a basic protocol trace
plugin named simple_trace
. This plugin
provides a framework showing how to set up the client plugin
descriptor and create the trace-related callback functions.
In simple_trace
, these functions are
rudimentary and do little other than illustrate the
arguments required. To see in detail how a trace plugin can
make use of trace event information, check the source file
for the test protocol trace plugin
(test_trace_plugin.cc
in the
libmysql
directory of a MySQL source
distribution). However, note that the
st_mysql_client_plugin_TRACE
structure
used there differs from the structures used with the usual
client plugin declaration macros. In particular, the first
two members are defined explicitly, not implicitly by
declaration macros.
Several header files contain information relevant to protocol trace plugins:
client_plugin.h
: Defines the API for client plugins. This includes the client plugin descriptor and function prototypes for client plugin C API calls (see Section 28.7.17, “C API Client Plugin Functions”).plugin_trace.h
: Contains declarations for client-side plugins of typeMYSQL_CLIENT_TRACE_PLUGIN
. It also contains descriptions of the permitted protocol stages, transitions between stages, and the types of events permitted at each stage.
To write a protocol trace plugin, include the following header files in the plugin source file. Other MySQL or general header files might also be needed, depending on the plugin capabilities and requirements.
#include <mysql/plugin_trace.h>
#include <mysql.h>
plugin_trace.h
includes
client_plugin.h
, so you need not
include the latter file explicitly.
Declare the client-side plugin descriptor with the
mysql_declare_client_plugin()
and
mysql_end_client_plugin
macros (see
Section 29.2.4.2.3, “Client Plugin Descriptors”). For the
simple_trace
plugin, the descriptor looks
like this:
mysql_declare_client_plugin(TRACE)
"simple_trace", /* plugin name */
"Author Name", /* author */
"Simple protocol trace plugin", /* description */
{1,0,0}, /* version = 1.0.0 */
"GPL", /* license type */
NULL, /* for internal use */
plugin_init, /* initialization function */
plugin_deinit, /* deinitialization function */
plugin_options, /* option-handling function */
trace_start, /* start-trace function */
trace_stop, /* stop-trace function */
trace_event /* event-handling function */
mysql_end_client_plugin;
The descriptor members from the plugin name through the option-handling function are common to all client plugin types. The members following the common members implement trace event handling.
Function members for which the plugin needs no processing
can be declared as NULL
in the
descriptor, in which case you need not write any
corresponding function. For illustration purposes and to
show the argument syntax, the following discussion
implements all functions listed in the descriptor, even
though some of them do nothing,
The initialization, deinitialization, and options functions common to all client plugins are declared as follows. For a description of the arguments and return values, see Section 29.2.4.2.3, “Client Plugin Descriptors”.
static int
plugin_init(char *errbuf, size_t errbuf_len, int argc, va_list args)
{
return 0;
}
static int
plugin_deinit()
{
return 0;
}
static int
plugin_options(const char *option, const void *value)
{
return 0;
}
The trace-specific members of the client plugin descriptor are callback functions. The following descriptions provide more detail on how they are used. Each has a first argument that is a pointer to the plugin instance in case your implementation needs to access it.
trace_start()
: This function is called at
the start of each traced connection (each connection that
starts after the plugin is loaded). It is passed the
connection handler and the protocol stage at which tracing
starts. trace_start()
allocates memory
needed by the trace_event()
function, if
any, and returns a pointer to it. If no memory is needed,
this function returns NULL
.
static void*
trace_start(struct st_mysql_client_plugin_TRACE *self,
MYSQL *conn,
enum protocol_stage stage)
{
struct st_trace_data *plugin_data= malloc(sizeof(struct st_trace_data));
fprintf(stderr, "Initializing trace: stage %d\n", stage);
if (plugin_data)
{
memset(plugin_data, 0, sizeof(struct st_trace_data));
fprintf(stderr, "Trace initialized\n");
return plugin_data;
}
fprintf(stderr, "Could not initialize trace\n");
exit(1);
}
trace_stop()
: This function is called
when tracing of the connection ends. That usually happens
when the connection is closed, but can happen earlier. For
example, trace_event()
can return a
nonzero value at any time and that causes tracing of the
connection to terminate. trace_stop()
is
then called even though the connection has not ended.
trace_stop()
is passed the connection
handler and a pointer to the memory allocated by
trace_start()
(NULL
if
none). If the pointer is non-NULL
,
trace_stop()
should deallocate the
memory. This function returns no value.
static void
trace_stop(struct st_mysql_client_plugin_TRACE *self,
MYSQL *conn,
void *plugin_data)
{
fprintf(stderr, "Terminating trace\n");
if (plugin_data)
free(plugin_data);
}
trace_event()
: This function is called
for each event occurrence. It is passed a pointer to the
memory allocated by trace_start()
(NULL
if none), the connection handler,
the current protocol stage and event codes, and event data.
This function returns 0 to continue tracing, nonzero if
tracing should stop.
static int
trace_event(struct st_mysql_client_plugin_TRACE *self,
void *plugin_data,
MYSQL *conn,
enum protocol_stage stage,
enum trace_event event,
struct st_trace_event_args args)
{
fprintf(stderr, "Trace event received: stage %d, event %d\n", stage, event);
if (event == TRACE_EVENT_DISCONNECTED)
fprintf(stderr, "Connection closed\n");
return 0;
}
The tracing framework shuts down tracing of the connection
when the connection ends, so
trace_event()
should return nonzero only
if you want to terminate tracing of the connection early.
Suppose that you want to trace only connections for a
certain MySQL account. After authentication, you can check
the user name for the connection and stop tracing if it is
not the user in whom you are interested.
For each call to trace_event()
, the
st_trace_event_args
structure contains
the event data. It has this definition:
struct st_trace_event_args
{
const char *plugin_name;
int cmd;
const unsigned char *hdr;
size_t hdr_len;
const unsigned char *pkt;
size_t pkt_len;
};
For different event types, the
st_trace_event_args
structure contains
the information described following. All lengths are in
bytes. Unused members are set to
0
/NULL
.
AUTH_PLUGIN
event:
plugin_name The name of the plugin
SEND_COMMAND
event:
cmd The command code
hdr Pointer to the command packet header
hdr_len Length of the header
pkt Pointer to the command arguments
pkt_len Length of the arguments
Other SEND_
and
xxx
events:
xxx
_RECEIVED
pkt Pointer to the data sent or received
pkt_len Length of the data
PACKET_SENT
event:
pkt_len Number of bytes sent
To compile and install a plugin library file, use the
instructions in
Section 29.2.4.3, “Compiling and Installing Plugin Libraries”. To make the
library file available for use, install it in the plugin
directory (the directory named by the
plugin_dir
system
variable).
After the plugin library file is compiled and installed in
the plugin directory, you can test it easily by setting the
LIBMYSQL_PLUGINS
environment variable to
the plugin name, which affects any client program that uses
that variable. mysql is one such program:
shell> export LIBMYSQL_PLUGINS=simple_trace
shqll> mysql
Initializing trace: stage 0
Trace initialized
Trace event received: stage 0, event 1
Trace event received: stage 0, event 2
...
Welcome to the MySQL monitor. Commands end with ; or \g.
Trace event received
Trace event received
...
mysql> SELECT 1;
Trace event received: stage 4, event 12
Trace event received: stage 4, event 16
...
Trace event received: stage 8, event 14
Trace event received: stage 8, event 15
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> quit
Trace event received: stage 4, event 12
Trace event received: stage 4, event 16
Trace event received: stage 4, event 3
Connection closed
Terminating trace
Bye
To stop the trace plugin from being loaded, do this:
shell> LIBMYSQL_PLUGINS=
It is also possible to write client programs that directly
load the plugin. You can tell the client where the plugin
directory is located by calling
mysql_options()
to set the
MYSQL_PLUGIN_DIR
option:
char *plugin_dir = "path_to_plugin_dir";
/* ... process command-line options ... */
mysql_options(&mysql, MYSQL_PLUGIN_DIR, plugin_dir);
Typically, the program will also accept a
--plugin-dir
option that enables users to
override the default value.
Should a client program require lower-level plugin
management, the client library contains functions that take
an st_mysql_client_plugin
argument. See
Section 28.7.17, “C API Client Plugin Functions”.
Document created the 26/06/2006, last modified the 26/10/2018
Source of the printed document:https://www.gaudry.be/en/mysql-rf-writing-protocol-trace-plugins.html
The infobrol is a personal site whose content is my sole responsibility. The text is available under CreativeCommons license (BY-NC-SA). More info on the terms of use and the author.
References
These references and links indicate documents consulted during the writing of this page, or which may provide additional information, but the authors of these sources can not be held responsible for the content of this page.
The author This site is solely responsible for the way in which the various concepts, and the freedoms that are taken with the reference works, are presented here. Remember that you must cross multiple source information to reduce the risk of errors.