1MONGOC_APPLICATION_PERFORMANCE_MMOoNnIgMToOODNRBGIONCCG_(DA3rP)iPvLeIrCATION_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
13       · Command Monitoring: events related to all application operations.
14
15       · SDAM Monitoring: events related to the driver's Server Discovery  And
16         Monitoring logic.
17
18       To  receive  notifications,  create  a mongoc_apm_callbacks_t with mon‐
19       goc_apm_callbacks_new, set callbacks  on  it,  then  pass  it  to  mon‐
20       goc_client_set_apm_callbacks or mongoc_client_pool_set_apm_callbacks.
21

COMMAND-MONITORING EXAMPLE

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

SDAM MONITORING EXAMPLE

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

AUTHOR

575       MongoDB, Inc
576
578       2017-present, MongoDB, Inc
579
580
581
582
5831.15.2                           NoMvON0G6O,C_2A0P1P9LICATION_PERFORMANCE_MONITORING(3)
Impressum