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
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
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
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
576 MongoDB, Inc
577
579 2017-present, MongoDB, Inc
580
581
582
583
5841.23.1 OcMtON2G0O,C_2A0P2P2LICATION_PERFORMANCE_MONITORING(3)