summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2021-09-27 18:50:00 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-09-27 19:15:10 +0000
commitf39e5fd6735431e899f1fc1689184f63b4b461ae (patch)
treef7faf02fe44d11ede2b7e38749875376a2ee0a5f /src/mongo/db
parent4ea51acda7d7659cb75dfdc6ed463bc5104c8238 (diff)
downloadmongo-f39e5fd6735431e899f1fc1689184f63b4b461ae.tar.gz
SERVER-60087 Add stats under collStats for timeseries bucket compression
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/commands/write_commands.cpp34
-rw-r--r--src/mongo/db/stats/SConscript1
-rw-r--r--src/mongo/db/stats/storage_stats.cpp2
-rw-r--r--src/mongo/db/timeseries/SConscript10
-rw-r--r--src/mongo/db/timeseries/timeseries_stats.cpp65
-rw-r--r--src/mongo/db/timeseries/timeseries_stats.h66
7 files changed, 172 insertions, 7 deletions
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index fde798457c6..4d75bf91168 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -368,6 +368,7 @@ env.Library(
'$BUILD_DIR/mongo/db/timeseries/catalog_helper',
'$BUILD_DIR/mongo/db/timeseries/timeseries_conversion_util',
'$BUILD_DIR/mongo/db/timeseries/timeseries_options',
+ '$BUILD_DIR/mongo/db/timeseries/timeseries_stats',
'$BUILD_DIR/mongo/db/transaction',
'$BUILD_DIR/mongo/db/views/views_mongod',
'$BUILD_DIR/mongo/executor/async_request_executor',
diff --git a/src/mongo/db/commands/write_commands.cpp b/src/mongo/db/commands/write_commands.cpp
index 9452f0c74b3..61f6b31d0a0 100644
--- a/src/mongo/db/commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands.cpp
@@ -69,6 +69,7 @@
#include "mongo/db/timeseries/bucket_catalog.h"
#include "mongo/db/timeseries/bucket_compression.h"
#include "mongo/db/timeseries/timeseries_constants.h"
+#include "mongo/db/timeseries/timeseries_stats.h"
#include "mongo/db/transaction_participant.h"
#include "mongo/db/views/view_catalog.h"
#include "mongo/db/write_concern.h"
@@ -690,11 +691,16 @@ public:
return SingleWriteResult();
}
- auto bucketCompressionFunc =
- [&closedBucket](const BSONObj& bucketDoc) -> boost::optional<BSONObj> {
+ boost::optional<int> beforeSize;
+ boost::optional<int> afterSize;
+
+ auto bucketCompressionFunc = [&](const BSONObj& bucketDoc) -> boost::optional<BSONObj> {
+ beforeSize = bucketDoc.objsize();
+ // Reset every time we run to ensure we never use a stale value
+ afterSize = boost::none;
auto compressed = timeseries::compressBucket(bucketDoc, closedBucket.timeField);
// If compressed object size is larger than uncompressed, skip compression update.
- if (compressed && compressed->objsize() > bucketDoc.objsize()) {
+ if (compressed && compressed->objsize() >= *beforeSize) {
LOGV2_DEBUG(5857802,
1,
"Skipping time-series bucket compression, compressed object is "
@@ -703,13 +709,27 @@ public:
"compressedSize"_attr = compressed->objsize());
return boost::none;
}
+ afterSize = compressed->objsize();
return compressed;
};
- return _getTimeseriesSingleWriteResult(write_ops_exec::performUpdates(
- opCtx,
- _makeTimeseriesCompressionOp(opCtx, closedBucket.bucketId, bucketCompressionFunc),
- OperationSource::kStandard));
+ auto compressionOp =
+ _makeTimeseriesCompressionOp(opCtx, closedBucket.bucketId, bucketCompressionFunc);
+ auto result = _getTimeseriesSingleWriteResult(
+ write_ops_exec::performUpdates(opCtx, compressionOp, OperationSource::kStandard));
+
+ // Report stats, if we fail before running the transform function then just skip
+ // reporting.
+ if (result.isOK() && beforeSize) {
+ auto coll = CollectionCatalog::get(opCtx)->lookupCollectionByNamespaceForRead(
+ opCtx, compressionOp.getNamespace());
+ if (coll) {
+ const auto& stats = TimeseriesStats::get(coll.get());
+ stats.onBucketClosed(*beforeSize, afterSize);
+ }
+ }
+
+ return result;
}
void _commitTimeseriesBucket(OperationContext* opCtx,
diff --git a/src/mongo/db/stats/SConscript b/src/mongo/db/stats/SConscript
index d7a439cd38e..b27a81181ac 100644
--- a/src/mongo/db/stats/SConscript
+++ b/src/mongo/db/stats/SConscript
@@ -129,6 +129,7 @@ env.Library(
'$BUILD_DIR/mongo/db/index/index_access_method',
'$BUILD_DIR/mongo/db/pipeline/document_sources_idl',
'$BUILD_DIR/mongo/db/timeseries/bucket_catalog',
+ '$BUILD_DIR/mongo/db/timeseries/timeseries_stats',
'fill_locker_info',
'top',
],
diff --git a/src/mongo/db/stats/storage_stats.cpp b/src/mongo/db/stats/storage_stats.cpp
index 96067384f6a..a2253d49706 100644
--- a/src/mongo/db/stats/storage_stats.cpp
+++ b/src/mongo/db/stats/storage_stats.cpp
@@ -38,6 +38,7 @@
#include "mongo/db/index/index_access_method.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/timeseries/bucket_catalog.h"
+#include "mongo/db/timeseries/timeseries_stats.h"
#include "mongo/db/views/view_catalog.h"
#include "mongo/logv2/log.h"
@@ -99,6 +100,7 @@ Status appendCollectionStorageStats(OperationContext* opCtx,
bob.append("avgBucketSize", collection->averageObjectSize(opCtx));
}
BucketCatalog::get(opCtx).appendExecutionStats(collNss.getTimeseriesViewNamespace(), &bob);
+ TimeseriesStats::get(collection.get()).append(&bob);
} else {
result->appendNumber("count", numRecords);
if (numRecords) {
diff --git a/src/mongo/db/timeseries/SConscript b/src/mongo/db/timeseries/SConscript
index 2a5ac31b204..e8b0f135c81 100644
--- a/src/mongo/db/timeseries/SConscript
+++ b/src/mongo/db/timeseries/SConscript
@@ -47,6 +47,16 @@ env.Library(
)
env.Library(
+ target='timeseries_stats',
+ source=[
+ 'timeseries_stats.cpp',
+ ],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/base',
+ ],
+)
+
+env.Library(
target='catalog_helper',
source=[
'catalog_helper.cpp',
diff --git a/src/mongo/db/timeseries/timeseries_stats.cpp b/src/mongo/db/timeseries/timeseries_stats.cpp
new file mode 100644
index 00000000000..33cafb386ff
--- /dev/null
+++ b/src/mongo/db/timeseries/timeseries_stats.cpp
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/timeseries/timeseries_stats.h"
+
+#include "mongo/db/catalog/collection.h"
+
+namespace mongo {
+namespace {
+
+const auto getTimeseriesStatsDecoration =
+ SharedCollectionDecorations::declareDecoration<TimeseriesStats>();
+
+} // namespace
+
+const TimeseriesStats& TimeseriesStats::get(const Collection* coll) {
+ return getTimeseriesStatsDecoration(coll->getSharedDecorations());
+}
+
+void TimeseriesStats::onBucketClosed(int uncompressedSize,
+ boost::optional<int> compressedSize) const {
+ _uncompressedSize.fetchAndAddRelaxed(uncompressedSize);
+ if (compressedSize) {
+ _compressedSize.fetchAndAddRelaxed(*compressedSize);
+ _numCompressedBuckets.fetchAndAddRelaxed(1);
+ } else {
+ _compressedSize.fetchAndAddRelaxed(uncompressedSize);
+ _numUncompressedBuckets.fetchAndAddRelaxed(1);
+ }
+}
+
+void TimeseriesStats::append(BSONObjBuilder* builder) const {
+ builder->appendNumber("numBytesUncompressed", _uncompressedSize.load());
+ builder->appendNumber("numBytesCompressed", _compressedSize.load());
+ builder->appendNumber("numCompressedBuckets", _numCompressedBuckets.load());
+ builder->appendNumber("numUncompressedBuckets", _numUncompressedBuckets.load());
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/timeseries/timeseries_stats.h b/src/mongo/db/timeseries/timeseries_stats.h
new file mode 100644
index 00000000000..c7870f34d35
--- /dev/null
+++ b/src/mongo/db/timeseries/timeseries_stats.h
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+
+#include "mongo/db/catalog/collection.h"
+
+namespace mongo {
+/**
+ * Timeseries statistics at Collection-level. Decorates 'SharedCollectionDecorations' and is not
+ * versioned per Collection instance.
+ *
+ * Used for timeseries statistics the BucketCatalog is unable to keep track of.
+ */
+class TimeseriesStats {
+public:
+ static const TimeseriesStats& get(const Collection* coll);
+
+ /**
+ * Records stats for a closed time-series bucket. 'boost::none' for compressedSize means
+ * compression failed for any reason.
+ */
+ void onBucketClosed(int uncompressedSize, boost::optional<int> compressedSize) const;
+
+ /**
+ * Appends current stats to the given BSONObjBuilder.
+ */
+ void append(BSONObjBuilder* builder) const;
+
+private:
+ // We need to be able to record stats on a time-series bucket collection without requiring a
+ // non-const Collection (which requires MODE_X collection lock).
+ mutable AtomicWord<long long> _uncompressedSize;
+ mutable AtomicWord<long long> _compressedSize;
+ mutable AtomicWord<long long> _numCompressedBuckets;
+ mutable AtomicWord<long long> _numUncompressedBuckets;
+};
+} // namespace mongo