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 Logging and Monitoring: events related to all application op‐
14 erations.
15
16 • SDAM 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
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
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
577 MongoDB, Inc
578
580 2017-present, MongoDB, Inc
581
582
583
584
5851.24.3 AuMgON1G7O,C_2A0P2P3LICATION_PERFORMANCE_MONITORING(3)