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

COMMAND-MONITORING EXAMPLE

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

SDAM MONITORING EXAMPLE

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

AUTHOR

573       MongoDB, Inc
574
576       2017-present, MongoDB, Inc
577
578
579
580
5811.25.1                           NoMvON0G8O,C_2A0P2P3LICATION_PERFORMANCE_MONITORING(3)
Impressum