1
2 /**
3 * Copyright (C) 2018-present MongoDB, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the Server Side Public License, version 1,
7 * as published by MongoDB, Inc.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * Server Side Public License for more details.
13 *
14 * You should have received a copy of the Server Side Public License
15 * along with this program. If not, see
16 * <http://www.mongodb.com/licensing/server-side-public-license>.
17 *
18 * As a special exception, the copyright holders give permission to link the
19 * code of portions of this program with the OpenSSL library under certain
20 * conditions as described in each individual source file and distribute
21 * linked combinations including the program with the OpenSSL library. You
22 * must comply with the Server Side Public License in all respects for
23 * all of the code used other than as permitted herein. If you modify file(s)
24 * with this exception, you may extend this exception to your version of the
25 * file(s), but you are not obligated to do so. If you do not wish to do so,
26 * delete this exception statement from your version. If you delete this
27 * exception statement from all source files in the program, then also delete
28 * it in the license file.
29 */
30
31 #include "mongo/platform/basic.h"
32
33 #include "mongo/db/ftdc/collector.h"
34
35 #include "mongo/base/string_data.h"
36 #include "mongo/bson/bsonmisc.h"
37 #include "mongo/bson/bsonobjbuilder.h"
38 #include "mongo/db/client.h"
39 #include "mongo/db/ftdc/constants.h"
40 #include "mongo/db/ftdc/util.h"
41 #include "mongo/db/jsobj.h"
42 #include "mongo/db/operation_context.h"
43 #include "mongo/util/time_support.h"
44
45 namespace mongo {
46
add(std::unique_ptr<FTDCCollectorInterface> collector)47 void FTDCCollectorCollection::add(std::unique_ptr<FTDCCollectorInterface> collector) {
48 // TODO: ensure the collectors all have unique names.
49 _collectors.emplace_back(std::move(collector));
50 }
51
collect(Client * client)52 std::tuple<BSONObj, Date_t> FTDCCollectorCollection::collect(Client* client) {
53 // If there are no collectors, just return an empty BSONObj so that that are caller knows we did
54 // not collect anything
55 if (_collectors.empty()) {
56 return std::tuple<BSONObj, Date_t>(BSONObj(), Date_t());
57 }
58
59 BSONObjBuilder builder;
60
61 Date_t start = client->getServiceContext()->getPreciseClockSource()->now();
62 Date_t end;
63 bool firstLoop = true;
64
65 builder.appendDate(kFTDCCollectStartField, start);
66
67 // All collectors should be ok seeing the inconsistent states in the middle of replication
68 // batches. This is desirable because we want to be able to collect data in the middle of
69 // batches that are taking a long time.
70 auto opCtx = client->makeOperationContext();
71 opCtx->lockState()->setShouldConflictWithSecondaryBatchApplication(false);
72 opCtx->lockState()->setShouldAcquireTicket(false);
73
74 for (auto& collector : _collectors) {
75 BSONObjBuilder subObjBuilder(builder.subobjStart(collector->name()));
76
77 // Add a Date_t before and after each BSON is collected so that we can track timing of the
78 // collector.
79 Date_t now = start;
80
81 if (!firstLoop) {
82 now = client->getServiceContext()->getPreciseClockSource()->now();
83 }
84
85 firstLoop = false;
86
87 subObjBuilder.appendDate(kFTDCCollectStartField, now);
88
89 collector->collect(opCtx.get(), subObjBuilder);
90
91 end = client->getServiceContext()->getPreciseClockSource()->now();
92 subObjBuilder.appendDate(kFTDCCollectEndField, end);
93 }
94
95 builder.appendDate(kFTDCCollectEndField, end);
96
97 return std::tuple<BSONObj, Date_t>(builder.obj(), start);
98 }
99
100 } // namespace mongo
101