1MONGOC_APPLICATION_PERFORMANCE_MONIMTlOOiNRbGImONoCGn_(gA3oP)cPLICATION_PERFORMANCE_MONITORING(3)
2
3
4

NAME

6       mongoc_application_performance_monitoring   -  Application  Performance
7       Monitoring (APM)
8
9       The MongoDB C Driver allows you to monitor all the  MongoDB  operations
10       the  driver  executes.  This  event-notification system conforms to two
11       MongoDB driver specs:
12
13Command Logging and Monitoring: events related to all application op‐
14         erations.
15
16SDAM  Monitoring: events related to the driver's Server Discovery And
17         Monitoring logic.
18
19       To  receive  notifications,  create   a   mongoc_apm_callbacks_t   with
20       mongoc_apm_callbacks_new(),  set  callbacks  on  it,  then  pass  it to
21       mongoc_client_set_apm_callbacks()                                    or
22       mongoc_client_pool_set_apm_callbacks().
23

COMMAND-MONITORING EXAMPLE

25       example-command-monitoring.c
26
27          /* gcc example-command-monitoring.c -o example-command-monitoring \
28           *     $(pkg-config --cflags --libs libmongoc-1.0) */
29
30          /* ./example-command-monitoring [CONNECTION_STRING] */
31
32          #include <mongoc/mongoc.h>
33          #include <stdio.h>
34
35
36          typedef struct {
37             int started;
38             int succeeded;
39             int failed;
40          } stats_t;
41
42
43          void
44          command_started (const mongoc_apm_command_started_t *event)
45          {
46             char *s;
47
48             s = bson_as_relaxed_extended_json (
49                mongoc_apm_command_started_get_command (event), NULL);
50             printf ("Command %s started on %s:\n%s\n\n",
51                     mongoc_apm_command_started_get_command_name (event),
52                     mongoc_apm_command_started_get_host (event)->host,
53                     s);
54
55             ((stats_t *) mongoc_apm_command_started_get_context (event))->started++;
56
57             bson_free (s);
58          }
59
60
61          void
62          command_succeeded (const mongoc_apm_command_succeeded_t *event)
63          {
64             char *s;
65
66             s = bson_as_relaxed_extended_json (
67                mongoc_apm_command_succeeded_get_reply (event), NULL);
68             printf ("Command %s succeeded:\n%s\n\n",
69                     mongoc_apm_command_succeeded_get_command_name (event),
70                     s);
71
72             ((stats_t *) mongoc_apm_command_succeeded_get_context (event))->succeeded++;
73
74             bson_free (s);
75          }
76
77
78          void
79          command_failed (const mongoc_apm_command_failed_t *event)
80          {
81             bson_error_t error;
82
83             mongoc_apm_command_failed_get_error (event, &error);
84             printf ("Command %s failed:\n\"%s\"\n\n",
85                     mongoc_apm_command_failed_get_command_name (event),
86                     error.message);
87
88             ((stats_t *) mongoc_apm_command_failed_get_context (event))->failed++;
89          }
90
91
92          int
93          main (int argc, char *argv[])
94          {
95             mongoc_client_t *client;
96             mongoc_apm_callbacks_t *callbacks;
97             stats_t stats = {0};
98             mongoc_collection_t *collection;
99             bson_error_t error;
100             const char *uri_string =
101                "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
102             mongoc_uri_t *uri;
103             const char *collection_name = "test";
104             bson_t *docs[2];
105
106             mongoc_init ();
107
108             if (argc > 1) {
109                uri_string = argv[1];
110             }
111
112             uri = mongoc_uri_new_with_error (uri_string, &error);
113             if (!uri) {
114                fprintf (stderr,
115                         "failed to parse URI: %s\n"
116                         "error message:       %s\n",
117                         uri_string,
118                         error.message);
119                return EXIT_FAILURE;
120             }
121
122             client = mongoc_client_new_from_uri (uri);
123             if (!client) {
124                return EXIT_FAILURE;
125             }
126
127             mongoc_client_set_error_api (client, 2);
128             callbacks = mongoc_apm_callbacks_new ();
129             mongoc_apm_set_command_started_cb (callbacks, command_started);
130             mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
131             mongoc_apm_set_command_failed_cb (callbacks, command_failed);
132             mongoc_client_set_apm_callbacks (
133                client, callbacks, (void *) &stats /* context pointer */);
134
135             collection = mongoc_client_get_collection (client, "test", collection_name);
136             mongoc_collection_drop (collection, NULL);
137
138             docs[0] = BCON_NEW ("_id", BCON_INT32 (0));
139             docs[1] = BCON_NEW ("_id", BCON_INT32 (1));
140             mongoc_collection_insert_many (
141                collection, (const bson_t **) docs, 2, NULL, NULL, NULL);
142
143             /* duplicate key error on the second insert */
144             mongoc_collection_insert_one (collection, docs[0], NULL, NULL, NULL);
145
146             mongoc_collection_destroy (collection);
147             mongoc_apm_callbacks_destroy (callbacks);
148             mongoc_uri_destroy (uri);
149             mongoc_client_destroy (client);
150
151             printf ("started: %d\nsucceeded: %d\nfailed: %d\n",
152                     stats.started,
153                     stats.succeeded,
154                     stats.failed);
155
156             bson_destroy (docs[0]);
157             bson_destroy (docs[1]);
158
159             mongoc_cleanup ();
160
161             return EXIT_SUCCESS;
162          }
163
164
165       This example program prints:
166
167          Command drop started on 127.0.0.1:
168          { "drop" : "test" }
169
170          Command drop succeeded:
171          { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }
172
173          Command insert started on 127.0.0.1:
174          {
175            "insert" : "test",
176            "ordered" : true,
177            "documents" : [
178              { "_id" : 0 }, { "_id" : 1 }
179            ]
180          }
181
182          Command insert succeeded:
183          { "n" : 2, "ok" : 1.0 }
184
185          Command insert started on 127.0.0.1:
186          {
187            "insert" : "test",
188            "ordered" : true,
189            "documents" : [
190              { "_id" : 0 }
191            ]
192          }
193
194          Command insert succeeded:
195          {
196            "n" : 0,
197            "writeErrors" : [
198              { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
199            ],
200            "ok" : 1.0
201          }
202
203          started: 3
204          succeeded: 3
205          failed: 0
206
207       The output has been edited and formatted for clarity. Depending on your
208       server configuration, messages may include metadata like database name,
209       logical session ids, or cluster times that are not shown here.
210
211       The  final  "insert"  command  is  considered  successful,  despite the
212       writeError, because the server replied  to  the  overall  command  with
213       "ok": 1.
214

SDAM MONITORING EXAMPLE

216       example-sdam-monitoring.c
217
218          /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
219           *     $(pkg-config --cflags --libs libmongoc-1.0) */
220
221          /* ./example-sdam-monitoring [CONNECTION_STRING] */
222
223          #include <mongoc/mongoc.h>
224          #include <stdio.h>
225
226
227          typedef struct {
228             int server_changed_events;
229             int server_opening_events;
230             int server_closed_events;
231             int topology_changed_events;
232             int topology_opening_events;
233             int topology_closed_events;
234             int heartbeat_started_events;
235             int heartbeat_succeeded_events;
236             int heartbeat_failed_events;
237          } stats_t;
238
239
240          static void
241          server_changed (const mongoc_apm_server_changed_t *event)
242          {
243             stats_t *context;
244             const mongoc_server_description_t *prev_sd, *new_sd;
245
246             context = (stats_t *) mongoc_apm_server_changed_get_context (event);
247             context->server_changed_events++;
248
249             prev_sd = mongoc_apm_server_changed_get_previous_description (event);
250             new_sd = mongoc_apm_server_changed_get_new_description (event);
251
252             printf ("server changed: %s %s -> %s\n",
253                     mongoc_apm_server_changed_get_host (event)->host_and_port,
254                     mongoc_server_description_type (prev_sd),
255                     mongoc_server_description_type (new_sd));
256          }
257
258
259          static void
260          server_opening (const mongoc_apm_server_opening_t *event)
261          {
262             stats_t *context;
263
264             context = (stats_t *) mongoc_apm_server_opening_get_context (event);
265             context->server_opening_events++;
266
267             printf ("server opening: %s\n",
268                     mongoc_apm_server_opening_get_host (event)->host_and_port);
269          }
270
271
272          static void
273          server_closed (const mongoc_apm_server_closed_t *event)
274          {
275             stats_t *context;
276
277             context = (stats_t *) mongoc_apm_server_closed_get_context (event);
278             context->server_closed_events++;
279
280             printf ("server closed: %s\n",
281                     mongoc_apm_server_closed_get_host (event)->host_and_port);
282          }
283
284
285          static void
286          topology_changed (const mongoc_apm_topology_changed_t *event)
287          {
288             stats_t *context;
289             const mongoc_topology_description_t *prev_td;
290             const mongoc_topology_description_t *new_td;
291             mongoc_server_description_t **prev_sds;
292             size_t n_prev_sds;
293             mongoc_server_description_t **new_sds;
294             size_t n_new_sds;
295             size_t i;
296             mongoc_read_prefs_t *prefs;
297
298             context = (stats_t *) mongoc_apm_topology_changed_get_context (event);
299             context->topology_changed_events++;
300
301             prev_td = mongoc_apm_topology_changed_get_previous_description (event);
302             prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds);
303             new_td = mongoc_apm_topology_changed_get_new_description (event);
304             new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds);
305
306             printf ("topology changed: %s -> %s\n",
307                     mongoc_topology_description_type (prev_td),
308                     mongoc_topology_description_type (new_td));
309
310             if (n_prev_sds) {
311                printf ("  previous servers:\n");
312                for (i = 0; i < n_prev_sds; i++) {
313                   printf ("      %s %s\n",
314                           mongoc_server_description_type (prev_sds[i]),
315                           mongoc_server_description_host (prev_sds[i])->host_and_port);
316                }
317             }
318
319             if (n_new_sds) {
320                printf ("  new servers:\n");
321                for (i = 0; i < n_new_sds; i++) {
322                   printf ("      %s %s\n",
323                           mongoc_server_description_type (new_sds[i]),
324                           mongoc_server_description_host (new_sds[i])->host_and_port);
325                }
326             }
327
328             prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
329
330             /* it is safe, and unfortunately necessary, to cast away const here */
331             if (mongoc_topology_description_has_readable_server (
332                    (mongoc_topology_description_t *) new_td, prefs)) {
333                printf ("  secondary AVAILABLE\n");
334             } else {
335                printf ("  secondary UNAVAILABLE\n");
336             }
337
338             if (mongoc_topology_description_has_writable_server (
339                    (mongoc_topology_description_t *) new_td)) {
340                printf ("  primary AVAILABLE\n");
341             } else {
342                printf ("  primary UNAVAILABLE\n");
343             }
344
345             mongoc_read_prefs_destroy (prefs);
346             mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds);
347             mongoc_server_descriptions_destroy_all (new_sds, n_new_sds);
348          }
349
350
351          static void
352          topology_opening (const mongoc_apm_topology_opening_t *event)
353          {
354             stats_t *context;
355
356             context = (stats_t *) mongoc_apm_topology_opening_get_context (event);
357             context->topology_opening_events++;
358
359             printf ("topology opening\n");
360          }
361
362
363          static void
364          topology_closed (const mongoc_apm_topology_closed_t *event)
365          {
366             stats_t *context;
367
368             context = (stats_t *) mongoc_apm_topology_closed_get_context (event);
369             context->topology_closed_events++;
370
371             printf ("topology closed\n");
372          }
373
374
375          static void
376          server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event)
377          {
378             stats_t *context;
379
380             context =
381                (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event);
382             context->heartbeat_started_events++;
383
384             printf ("%s heartbeat started\n",
385                     mongoc_apm_server_heartbeat_started_get_host (event)->host_and_port);
386          }
387
388
389          static void
390          server_heartbeat_succeeded (
391             const mongoc_apm_server_heartbeat_succeeded_t *event)
392          {
393             stats_t *context;
394             char *reply;
395
396             context =
397                (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event);
398             context->heartbeat_succeeded_events++;
399
400             reply = bson_as_canonical_extended_json (
401                mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL);
402
403             printf (
404                "%s heartbeat succeeded: %s\n",
405                mongoc_apm_server_heartbeat_succeeded_get_host (event)->host_and_port,
406                reply);
407
408             bson_free (reply);
409          }
410
411
412          static void
413          server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event)
414          {
415             stats_t *context;
416             bson_error_t error;
417
418             context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event);
419             context->heartbeat_failed_events++;
420             mongoc_apm_server_heartbeat_failed_get_error (event, &error);
421
422             printf ("%s heartbeat failed: %s\n",
423                     mongoc_apm_server_heartbeat_failed_get_host (event)->host_and_port,
424                     error.message);
425          }
426
427
428          int
429          main (int argc, char *argv[])
430          {
431             mongoc_client_t *client;
432             mongoc_apm_callbacks_t *cbs;
433             stats_t stats = {0};
434             const char *uri_string =
435                "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
436             mongoc_uri_t *uri;
437             bson_t cmd = BSON_INITIALIZER;
438             bson_t reply;
439             bson_error_t error;
440
441             mongoc_init ();
442
443             if (argc > 1) {
444                uri_string = argv[1];
445             }
446
447             uri = mongoc_uri_new_with_error (uri_string, &error);
448             if (!uri) {
449                fprintf (stderr,
450                         "failed to parse URI: %s\n"
451                         "error message:       %s\n",
452                         uri_string,
453                         error.message);
454                return EXIT_FAILURE;
455             }
456
457             client = mongoc_client_new_from_uri (uri);
458             if (!client) {
459                return EXIT_FAILURE;
460             }
461
462             mongoc_client_set_error_api (client, 2);
463             cbs = mongoc_apm_callbacks_new ();
464             mongoc_apm_set_server_changed_cb (cbs, server_changed);
465             mongoc_apm_set_server_opening_cb (cbs, server_opening);
466             mongoc_apm_set_server_closed_cb (cbs, server_closed);
467             mongoc_apm_set_topology_changed_cb (cbs, topology_changed);
468             mongoc_apm_set_topology_opening_cb (cbs, topology_opening);
469             mongoc_apm_set_topology_closed_cb (cbs, topology_closed);
470             mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started);
471             mongoc_apm_set_server_heartbeat_succeeded_cb (cbs,
472                                                           server_heartbeat_succeeded);
473             mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed);
474             mongoc_client_set_apm_callbacks (
475                client, cbs, (void *) &stats /* context pointer */);
476
477             /* the driver connects on demand to perform first operation */
478             BSON_APPEND_INT32 (&cmd, "buildinfo", 1);
479             mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error);
480             mongoc_uri_destroy (uri);
481             mongoc_client_destroy (client);
482
483             printf ("Events:\n"
484                     "   server changed: %d\n"
485                     "   server opening: %d\n"
486                     "   server closed: %d\n"
487                     "   topology changed: %d\n"
488                     "   topology opening: %d\n"
489                     "   topology closed: %d\n"
490                     "   heartbeat started: %d\n"
491                     "   heartbeat succeeded: %d\n"
492                     "   heartbeat failed: %d\n",
493                     stats.server_changed_events,
494                     stats.server_opening_events,
495                     stats.server_closed_events,
496                     stats.topology_changed_events,
497                     stats.topology_opening_events,
498                     stats.topology_closed_events,
499                     stats.heartbeat_started_events,
500                     stats.heartbeat_succeeded_events,
501                     stats.heartbeat_failed_events);
502
503             bson_destroy (&cmd);
504             bson_destroy (&reply);
505             mongoc_apm_callbacks_destroy (cbs);
506
507             mongoc_cleanup ();
508
509             return EXIT_SUCCESS;
510          }
511
512
513       Start  a  3-node  replica set on localhost with set name "rs" and start
514       the program:
515
516          ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"
517
518       This example program prints something like:
519
520          topology opening
521          topology changed: Unknown -> ReplicaSetNoPrimary
522            secondary UNAVAILABLE
523            primary UNAVAILABLE
524          server opening: localhost:27017
525          server opening: localhost:27018
526          localhost:27017 heartbeat started
527          localhost:27018 heartbeat started
528          localhost:27017 heartbeat succeeded: { ... reply ... }
529          server changed: localhost:27017 Unknown -> RSPrimary
530          server opening: localhost:27019
531          topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
532            new servers:
533                RSPrimary localhost:27017
534            secondary UNAVAILABLE
535            primary AVAILABLE
536          localhost:27019 heartbeat started
537          localhost:27018 heartbeat succeeded: { ... reply ... }
538          server changed: localhost:27018 Unknown -> RSSecondary
539          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
540            previous servers:
541                RSPrimary localhost:27017
542            new servers:
543                RSPrimary localhost:27017
544                RSSecondary localhost:27018
545            secondary AVAILABLE
546            primary AVAILABLE
547          localhost:27019 heartbeat succeeded: { ... reply ... }
548          server changed: localhost:27019 Unknown -> RSSecondary
549          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
550            previous servers:
551                RSPrimary localhost:27017
552                RSSecondary localhost:27018
553            new servers:
554                RSPrimary localhost:27017
555                RSSecondary localhost:27018
556                RSSecondary localhost:27019
557            secondary AVAILABLE
558            primary AVAILABLE
559          topology closed
560
561          Events:
562             server changed: 3
563             server opening: 3
564             server closed: 0
565             topology changed: 4
566             topology opening: 1
567             topology closed: 1
568             heartbeat started: 3
569             heartbeat succeeded: 3
570             heartbeat failed: 0
571
572       The driver connects to the mongods on ports 27017 and 27018, which were
573       specified  in the URI, and determines which is primary. It also discov‐
574       ers the third member, "localhost:27019", and adds it to the topology.
575

AUTHOR

577       MongoDB, Inc
578
580       2017-present, MongoDB, Inc
581
582
583
584
5851.24.3                           AuMgON1G7O,C_2A0P2P3LICATION_PERFORMANCE_MONITORING(3)
Impressum