1 // counters.cpp
2
3 /**
4 * Copyright (C) 2018-present MongoDB, Inc.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the Server Side Public License, version 1,
8 * as published by MongoDB, Inc.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * Server Side Public License for more details.
14 *
15 * You should have received a copy of the Server Side Public License
16 * along with this program. If not, see
17 * <http://www.mongodb.com/licensing/server-side-public-license>.
18 *
19 * As a special exception, the copyright holders give permission to link the
20 * code of portions of this program with the OpenSSL library under certain
21 * conditions as described in each individual source file and distribute
22 * linked combinations including the program with the OpenSSL library. You
23 * must comply with the Server Side Public License in all respects for
24 * all of the code used other than as permitted herein. If you modify file(s)
25 * with this exception, you may extend this exception to your version of the
26 * file(s), but you are not obligated to do so. If you do not wish to do so,
27 * delete this exception statement from your version. If you delete this
28 * exception statement from all source files in the program, then also delete
29 * it in the license file.
30 */
31
32 #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault
33
34 #include "mongo/platform/basic.h"
35
36 #include "mongo/db/stats/counters.h"
37
38 #include "mongo/db/jsobj.h"
39 #include "mongo/util/debug_util.h"
40 #include "mongo/util/log.h"
41
42 namespace mongo {
43
44 using std::endl;
45
OpCounters()46 OpCounters::OpCounters() {}
47
gotInserts(int n)48 void OpCounters::gotInserts(int n) {
49 RARELY _checkWrap();
50 _insert.fetchAndAdd(n);
51 }
52
gotInsert()53 void OpCounters::gotInsert() {
54 RARELY _checkWrap();
55 _insert.fetchAndAdd(1);
56 }
57
gotQuery()58 void OpCounters::gotQuery() {
59 RARELY _checkWrap();
60 _query.fetchAndAdd(1);
61 }
62
gotUpdate()63 void OpCounters::gotUpdate() {
64 RARELY _checkWrap();
65 _update.fetchAndAdd(1);
66 }
67
gotDelete()68 void OpCounters::gotDelete() {
69 RARELY _checkWrap();
70 _delete.fetchAndAdd(1);
71 }
72
gotGetMore()73 void OpCounters::gotGetMore() {
74 RARELY _checkWrap();
75 _getmore.fetchAndAdd(1);
76 }
77
gotCommand()78 void OpCounters::gotCommand() {
79 RARELY _checkWrap();
80 _command.fetchAndAdd(1);
81 }
82
gotOp(int op,bool isCommand)83 void OpCounters::gotOp(int op, bool isCommand) {
84 switch (op) {
85 case dbInsert: /*gotInsert();*/
86 break; // need to handle multi-insert
87 case dbQuery:
88 if (isCommand)
89 gotCommand();
90 else
91 gotQuery();
92 break;
93
94 case dbUpdate:
95 gotUpdate();
96 break;
97 case dbDelete:
98 gotDelete();
99 break;
100 case dbGetMore:
101 gotGetMore();
102 break;
103 case dbKillCursors:
104 case opReply:
105 break;
106 default:
107 log() << "OpCounters::gotOp unknown op: " << op << endl;
108 }
109 }
110
_checkWrap()111 void OpCounters::_checkWrap() {
112 const unsigned MAX = 1 << 30;
113
114 bool wrap = _insert.loadRelaxed() > MAX || _query.loadRelaxed() > MAX ||
115 _update.loadRelaxed() > MAX || _delete.loadRelaxed() > MAX ||
116 _getmore.loadRelaxed() > MAX || _command.loadRelaxed() > MAX;
117
118 if (wrap) {
119 _insert.store(0);
120 _query.store(0);
121 _update.store(0);
122 _delete.store(0);
123 _getmore.store(0);
124 _command.store(0);
125 }
126 }
127
getObj() const128 BSONObj OpCounters::getObj() const {
129 BSONObjBuilder b;
130 b.append("insert", _insert.loadRelaxed());
131 b.append("query", _query.loadRelaxed());
132 b.append("update", _update.loadRelaxed());
133 b.append("delete", _delete.loadRelaxed());
134 b.append("getmore", _getmore.loadRelaxed());
135 b.append("command", _command.loadRelaxed());
136 return b.obj();
137 }
138
hitPhysicalIn(long long bytes)139 void NetworkCounter::hitPhysicalIn(long long bytes) {
140 static const int64_t MAX = 1ULL << 60;
141
142 // don't care about the race as its just a counter
143 const bool overflow = _physicalBytesIn.loadRelaxed() > MAX;
144
145 if (overflow) {
146 _physicalBytesIn.store(bytes);
147 } else {
148 _physicalBytesIn.fetchAndAdd(bytes);
149 }
150 }
151
hitPhysicalOut(long long bytes)152 void NetworkCounter::hitPhysicalOut(long long bytes) {
153 static const int64_t MAX = 1ULL << 60;
154
155 // don't care about the race as its just a counter
156 const bool overflow = _physicalBytesOut.loadRelaxed() > MAX;
157
158 if (overflow) {
159 _physicalBytesOut.store(bytes);
160 } else {
161 _physicalBytesOut.fetchAndAdd(bytes);
162 }
163 }
164
hitLogicalIn(long long bytes)165 void NetworkCounter::hitLogicalIn(long long bytes) {
166 static const int64_t MAX = 1ULL << 60;
167
168 // don't care about the race as its just a counter
169 const bool overflow = _together.logicalBytesIn.loadRelaxed() > MAX;
170
171 if (overflow) {
172 _together.logicalBytesIn.store(bytes);
173 // The requests field only gets incremented here (and not in hitPhysical) because the
174 // hitLogical and hitPhysical are each called for each operation. Incrementing it in both
175 // functions would double-count the number of operations.
176 _together.requests.store(1);
177 } else {
178 _together.logicalBytesIn.fetchAndAdd(bytes);
179 _together.requests.fetchAndAdd(1);
180 }
181 }
182
hitLogicalOut(long long bytes)183 void NetworkCounter::hitLogicalOut(long long bytes) {
184 static const int64_t MAX = 1ULL << 60;
185
186 // don't care about the race as its just a counter
187 const bool overflow = _logicalBytesOut.loadRelaxed() > MAX;
188
189 if (overflow) {
190 _logicalBytesOut.store(bytes);
191 } else {
192 _logicalBytesOut.fetchAndAdd(bytes);
193 }
194 }
195
append(BSONObjBuilder & b)196 void NetworkCounter::append(BSONObjBuilder& b) {
197 b.append("bytesIn", static_cast<long long>(_together.logicalBytesIn.loadRelaxed()));
198 b.append("bytesOut", static_cast<long long>(_logicalBytesOut.loadRelaxed()));
199 b.append("physicalBytesIn", static_cast<long long>(_physicalBytesIn.loadRelaxed()));
200 b.append("physicalBytesOut", static_cast<long long>(_physicalBytesOut.loadRelaxed()));
201 b.append("numRequests", static_cast<long long>(_together.requests.loadRelaxed()));
202 }
203
204
205 OpCounters globalOpCounters;
206 OpCounters replOpCounters;
207 NetworkCounter networkCounter;
208 }
209