1MONGOC_APPLICATION_PERFORMANCE_MONIMTlOOiNRbGImONoCGn_(gA3oP)cPLICATION_PERFORMANCE_MONITORING(3)
2
3
4
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
23 example-command-monitoring.c
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
163 This 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
214 example-sdam-monitoring.c
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
511 Start a 3-node replica set on localhost with set name "rs" and start
512 the program:
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
575 MongoDB, Inc
576
578 2017-present, MongoDB, Inc
579
580
581
582
5831.20.0 NoMvON1G8O,C_2A0P2P1LICATION_PERFORMANCE_MONITORING(3)