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 #pragma once
32 
33 #include <boost/filesystem/path.hpp>
34 #include <vector>
35 
36 #include "mongo/base/status.h"
37 #include "mongo/base/status_with.h"
38 #include "mongo/db/ftdc/decompressor.h"
39 #include "mongo/db/jsobj.h"
40 
41 namespace mongo {
42 
43 /**
44  * Utilities for inflating and deflating BSON documents and metric arrays
45  */
46 namespace FTDCBSONUtil {
47 
48 /**
49 * Type of FTDC document.
50 *
51 * NOTE: Persisted to disk via BSON Objects.
52 */
53 enum class FTDCType : std::int32_t {
54     /**
55     * A metadata document is composed of a header + an array of bson documents
56     *
57     * See createBSONMetadataChunkDocument
58     */
59     kMetadata = 0,
60 
61     /**
62     * A metrics chunk is composed of a header + a compressed metric chunk.
63     *
64     * See createBSONMetricChunkDocument
65     */
66     kMetricChunk = 1,
67 };
68 
69 
70 /**
71  * Extract an array of numbers from a pair of documents. Verifies the pair of documents have same
72  * structure.
73  *
74  * Types considered numbers for the purpose of metrics:
75  *  - double - encoded as an integer, loses fractional components via truncation
76  *  - 32-bit integer
77  *  - 64-integer
78  *  - bool
79  *  - date
80  *  - timestamp
81  *    Note: Timestamp is encoded as two integers, the timestamp value followed by the increment.
82  *
83  * Two documents are considered the same if satisfy the following criteria:
84  *
85  * Criteria: During a Depth First traversal of the document:
86  *  1. Each element has the same name regardless of its type.
87  *  2. The same number of elements exist in each document.
88  *  3. The types of each element are the same.
89  *     Note: Double, Int, and Long are treated as equivalent for this purpose.
90  *
91  * @param referenceDoc A reference document to use the as the definition of the correct schema.
92  * @param doc A second document to compare against the reference document and extract metrics
93  * from
94  * @param metrics A vector of metrics that were extracted from the doc
95  *
96  * \return false if the documents differ in terms of metrics
97  */
98 StatusWith<bool> extractMetricsFromDocument(const BSONObj& referenceDoc,
99                                             const BSONObj& doc,
100                                             std::vector<std::uint64_t>* metrics);
101 
102 /**
103  * Construct a document from a reference document and array of metrics.
104  *
105  * @param referenceDoc A reference document to use the as the definition of the correct schema.
106  * @param builder A BSON builder to construct a single document into. Each document will be a
107  *copy
108  * of the reference document with the numerical fields replaced with values from metrics array.
109  * @param metrics A vector of metrics for all documents
110  * @param pos A position into the array of metrics to start iterating from.
111  *
112  * \return Status if the decompression of the buffer was successful or failed. Decompression may
113  * fail if the buffer is not valid.
114  */
115 Status constructDocumentFromMetrics(const BSONObj& referenceDoc,
116                                     BSONObjBuilder& builder,
117                                     const std::vector<std::uint64_t>& metrics,
118                                     size_t* pos);
119 
120 /**
121  * Construct a document from a reference document and array of metrics. See documentation above.
122  */
123 StatusWith<BSONObj> constructDocumentFromMetrics(const BSONObj& ref,
124                                                  const std::vector<std::uint64_t>& metrics);
125 
126 /**
127  * Create BSON metadata document for storage. The passed in document is embedded as the doc
128  * field in the example above. For the _id field, the specified date is used.
129  *
130  * Example:
131  * {
132  *  "_id" : Date_t
133  *  "type" : 0
134  *  "doc" : { ... }
135  * }
136  */
137 BSONObj createBSONMetadataDocument(const BSONObj& metadata, Date_t date);
138 
139 /**
140  * Create a BSON metric chunk document for storage. The passed in document is embedded as the
141  * data field in the example above. For the _id field, the date is specified by the caller
142  * since the metric chunk usually composed of multiple samples gathered over a period of time.
143  *
144  * Example:
145  * {
146  *  "_id" : Date_t
147  *  "type" : 1
148  *  "data" : BinData(...)
149  * }
150  */
151 BSONObj createBSONMetricChunkDocument(ConstDataRange buf, Date_t now);
152 
153 /**
154  * Get the _id field of a BSON document
155  */
156 StatusWith<Date_t> getBSONDocumentId(const BSONObj& obj);
157 
158 /**
159  * Get the type of a BSON document
160  */
161 StatusWith<FTDCType> getBSONDocumentType(const BSONObj& obj);
162 
163 /**
164  * Extract the metadata field from a BSON document
165  */
166 StatusWith<BSONObj> getBSONDocumentFromMetadataDoc(const BSONObj& obj);
167 
168 /**
169  * Get the set of metric documents from the compressed chunk of a metric document
170  */
171 StatusWith<std::vector<BSONObj>> getMetricsFromMetricDoc(const BSONObj& obj,
172                                                          FTDCDecompressor* decompressor);
173 
174 /**
175  * Is this a type that FTDC find's interesting? I.e. is this a numeric or container type?
176  */
177 bool isFTDCType(BSONType type);
178 }  // namespace FTDCBSONUtil
179 
180 
181 /**
182  * Miscellaneous utilties for FTDC.
183  */
184 namespace FTDCUtil {
185 /**
186  * Construct the full path to the interim file
187  */
188 boost::filesystem::path getInterimFile(const boost::filesystem::path& file);
189 
190 /**
191  * Construct the full path to the interim temp file before it is renamed.
192  */
193 boost::filesystem::path getInterimTempFile(const boost::filesystem::path& file);
194 
195 /**
196  * Round the specified time_point to the next multiple of period after the specified time_point
197  */
198 Date_t roundTime(Date_t now, Milliseconds period);
199 
200 /**
201  * Get the storage path for MongoS from the log file path.
202  */
203 boost::filesystem::path getMongoSPath(const boost::filesystem::path& logFile);
204 
205 }  // namespace FTDCUtil
206 
207 }  // namespace mongo
208