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 Monitoring: events related to all application operations.
14
15SDAM 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
19       mongoc_apm_callbacks_new(), set  callbacks  on  it,  then  pass  it  to
20       mongoc_client_set_apm_callbacks()                                    or
21       mongoc_client_pool_set_apm_callbacks().
22

COMMAND-MONITORING EXAMPLE

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

SDAM MONITORING EXAMPLE

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

AUTHOR

576       MongoDB, Inc
577
579       2017-present, MongoDB, Inc
580
581
582
583
5841.23.1                           OcMtON2G0O,C_2A0P2P2LICATION_PERFORMANCE_MONITORING(3)
Impressum