summaryrefslogtreecommitdiff
path: root/docs/server-parameters.md
blob: 758e1671cf433900fa0637cba068214d4ac2ed0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# Server Parameters
Mongo database and router servers (i.e., `mongod` and `mongos`) provide a number of configuration 
options through server parameters. These parameters allow users to configure the behavior of the 
server at startup or runtime. For instance, `logLevel` is a server parameter that configures the 
logging verbosity.

## How to define new parameters
Parameters are defined by the elements of the `server_parameters` section of an IDL file. The IDL 
machinery will parse these files and generate C++ code, and corresponding header files where 
appropriate. The generated code will self-register server parameters with the runtime.

Consider `logLevel` parameter from [`parameters.idl`][parameters.idl] for example:
```yaml
...
server_parameters:
  ...
  logLevel:
    description: "Specifies the verbosity of logging"
    set_at: ["startup", "runtime"]
    cpp_class:
      name: LogLevelServerParameter
      override_set: true
  ...
```

This defines a server parameter called `logLevel`, which is settable at startup or at runtime, and 
declares a C++ class for the parameter (i.e., `LogLevelServerParameter`). Refer to the 
[Server Parameters Syntax](#server-parameters-syntax) documentation for the complete IDL syntax.

## How to change a defined parameter
Users can set or modify a server parameter at startup and/or runtime, depending on the value 
specified for `set_at`. For instance, `logLevel` may be set at both startup and runtime, as 
indicated by `set_at` (see the above code snippet).

At startup, server parameters may be set using the `--setParameter` command line option. 
At runtime, the `setParameter` command may be used to modify server parameters. 
See the [`setParameter` documentation][set-parameter] for details.

## How to get the value provided for a parameter
Server developers may retrieve the value of a server parameter by:
* Accessing the C++ expression that corresponds to the parameter of interest. For example, reading 
from [`serverGlobalParams.quiet`][quiet-param] returns the current value for `quiet`.
* Registering a callback to be notified about changes to the server parameter (e.g., 
[`onUpdateFTDCFileSize`][ftdc-file-size-param] for `diagnosticDataCollectionFileSizeMB`).

Database users may use the [`getParameter`][get-parameter] command to query the current value for a 
server parameter.

## Server Parameters Syntax
The following shows the IDL syntax for declaring server parameters. Field types are denoted in each 
section. For details regarding `string or expression map`, see that section 
[below](#string-or-expression-map).

```yaml
server_parameters:
  "nameOfParameter": # string
    set_at: # string or list of strings
    description: # string
    cpp_vartype: # string
    cpp_varname: # string
    cpp_class: # string (name field) or map
      name: # string
      data: # string
      override_ctor: # bool
      override_set: # bool
      override_validate: # bool
    redact: # bool
    test_only: # bool
    default: # string or expression map
    deprecated_name: # string or list of strings
    on_update: # string
    condition:
      expr: # C++ bool expression, runtime evaled
      constexpr: # C++ bool expression, compile-time eval
      preprocessor: # C preprocessor condition
      min_fcv: # string
      feature_flag: # string
    validator: # Map containing one or more of the below
      lt: # string or expression map
      gt: # string or expression map
      lte: # string or expression map
      gte: # string or expression map
      callback: # string
```
Each entry in the `server_parameters` map represents one server parameter. The name of the parameter 
must be unique across the server instance. More information on the specific fields:

* `set_at` (required): Must contain the value `startup`, `runtime`, [`startup`, `runtime`], or 
`cluster`. If `runtime` is specified along with `cpp_varname`, then `decltype(cpp_varname)` must 
refer to a thread-safe storage type, specifically: `AtomicWord<T>`, `AtomicDouble`, `std::atomic<T>`, 
or `boost::synchronized<T>`. If `cluster` is specified along with `cpp_varname`, then 
`decltype(cpp_varname)` must refer to an IDL-defined type that has `ClusterServerParameter` attached 
as an inline chained struct.

* `description` (required): Free-form text field currently used only for commenting the generated C++ 
code. Future uses may preserve this value for a possible `{listSetParameters:1}` command or other 
programmatic and potentially user-facing purposes.

* `cpp_vartype`: Declares the full storage type. If `cpp_vartype` is not defined, it may be inferred 
from the C++ variable referenced by `cpp_varname`.

* `cpp_varname`: Declares the underlying variable or struct member to use when setting or reading the 
server parameter. If defined together with `cpp_vartype`, the storage will be declared as a global 
variable, and externed in the generated header file. If defined alone, a variable of this name will 
assume to have been declared and defined by the implementer, and its type will be automatically 
inferred at compile time. If `cpp_varname` is not defined, then `cpp_class` must be specified.

* `cpp_class`: Declares a custom `ServerParameter` class in the generated header using the provided 
string, or the name field in the associated map. The declared class will require an implementation 
of `setFromString()`, and optionally `set()`, `append()`, and a constructor.
See [Specialized Server Parameters](#specialized-server-parameters) below.

* `default`: String or expression map representation of the initial value.

* `redact`: Set to `true` to replace values of this setting with placeholders (e.g., for passwords).

* `test_only`: Set to `true` to disable this set parameter if `enableTestCommands` is not specified.

* `deprecated_name`: One or more names which can be used with the specified setting and underlying 
storage. Reading or writing a setting using this name will result in a warning in the server log.

* `on_update`: C++ callback invoked after all validation rules have completed successfully and the 
new value has been stored. Prototype: `Status(const cpp_vartype&);`

* `condition`: Up to five conditional rules for deciding whether or not to apply this server 
parameter. `preprocessor` will be evaluated first, followed by `constexpr`, then finally `expr`. If 
no provided setting evaluates to `false`, the server parameter will be registered. `feature_flag` and
`min_fcv` are evaluated after the parameter is registered, and instead affect whether the parameter
is enabled. `min_fcv` is a string of the form `X.Y`, representing the minimum FCV version for which
this parameter should be enabled. `feature_flag` is the name of a feature flag variable upon which
this server parameter depends -- if the feature flag is disabled, this parameter will be disabled.
`feature_flag` should be removed when all other instances of that feature flag are deleted, which
typically is done after the next LTS version of the server is branched. `min_fcv` should be removed
after it is no longer possible to downgrade to a FCV lower than that version - this occurs when the
next LTS version of the server is branched.

* `validator`: Zero or many validation rules to impose on the setting. All specified rules must pass 
to consider the new setting valid. `lt`, `gt`, `lte`, `gte` fields provide for simple numeric limits 
or expression maps which evaluate to numeric values. For all other validation cases, specify 
callback as a C++ function or static method. Note that validation rules (including callback) may run 
in any order. To perform an action after all validation rules have completed, `on_update` should be 
preferred instead. Callback prototype: `Status(const cpp_vartype&, const boost::optional<TenantId>&);`

Any symbols such as global variables or callbacks used by a server parameter must be imported using 
the usual IDL machinery via `globals.cpp_includes`. Similarly, all generated code will be nested 
inside the namespace defined by `globals.cpp_namespace`. Consider the following for example:
```yaml
global:
  cpp_namespace: "mongo"
  cpp_includes:
    - "mongo/db/free_mon/free_mon_mongod.h"

server_parameters:
  cloudFreeMonitoringEndpointURL:
    ...
    validator:
      callback: "onValidateFreeMonEndpointURL" # The callback is declared in "free_mon_mongod.h"
```

### Specialized Server Parameters
When `cpp_class` is specified on a server parameter, a child class of `ServerParameter` will be 
created in the `gen.h` file named for either the string value of `cpp_class`, or if it is expressed 
as a dictionary, then `cpp_class.name`. A `cpp_class` directive may also contain:
```yaml
server_parameters:
  someParameter:
    cpp_class:
      name: string # Name to assign to the class (e.g., SomeParameterImpl)
      data: string # cpp data type to add to the class as a property named "_data"
      override_ctor: bool # True to allow defining a custom constructor, default: false
      override_set: bool # True to allow defining a custom set() method, default: false
```

`override_ctor`: If `false`, the inherited constructor from the `ServerParameter` base class will be 
used. If `true`, then the implementer must provide a 
`{name}::{name}(StringData serverParameterName, ServerParameterType type)` constructor. In addition 
to any other work, this custom constructor must invoke its parent's constructor.

`override_set`: If `true`, the implementer must provide a `set` member function as:
```cpp
Status {name}::set(const BSONElement& val, const boost::optional<TenantId>& tenantId);
```
Otherwise the base class implementation `ServerParameter::set` is used. It
invokes `setFromString` using a string representation of `val`, if the `val` is
holding one of the supported types.

`override_validate`: If `true`, the implementer must provide a `validate` member function as:
```cpp
Status {name}::validate(const BSONElement& newValueElement, const boost::optional<TenantId>& tenantId);
```
Otherwise, the base class implementation `ServerParameter::validate` is used. This simply returns
`Status::OK()` without performing any kind of validation of the new BSON element.

If `param.redact` was specified as `true`, then a standard append method will be provided which 
injects a placeholder value. If `param.redact` was not specified as `true`, then an implementation 
must be provided with the following signature: 

```cpp
Status {name}::append(OperationContext*, BSONObjBuilder*, StringData, const boost::optional<TenantId>& tenantId);
```

Lastly, a `setFromString` method must always be provided with the following signature:
```cpp
Status {name}::setFromString(StringData value, const boost::optional<TenantId>& tenantId);
```

Note that by default, server parameters are not tenant aware and thus will always have `boost::none`
provided as `tenantId`, unless defined as cluster server parameters (discussed
[below](#cluster-server-parameters)).

Each server parameter encountered will produce a block of code to run at process startup similar to 
the following:
```cpp
/**
 *  Iteration count to use when creating new users with
 *  SCRAM-SHA-1 credentials
 */
MONGO_COMPILER_VARIABLE_UNUSED auto* scp_unique_ident = [] {
    using T = decltype(saslGlobalParams.scramSHA1IterationCount);
    constexpr auto setAt = ServerParameterType::kStartupAndRuntime;
    auto ret = new IDLServerParameterWithStorage<T>(
            "scramIterationCount",
            saslGlobalParams.scramSHA1IterationCount, setAt);
    ret->addBound<predicate::GTE>(5000);
    return ret;
}();
```

Any additional validator and callback would be set on `ret` as determined by the server parameter 
configuration block.

### Cluster Server Parameters
As indicated earlier, one of the options for the `set_at` field is `cluster`. If this value is 
selected, then the generated server parameter will be known as a cluster server parameter. These 
server parameters are persisted on a cluster-wide basis via the `setClusterParameter` and 
`getClusterParameter` commands. Cluster server parameters should be used instead of implementing 
custom commands to propagate an option cluster-wide, whenever possible.

`setClusterParameter` persists the new value of the indicated cluster server parameter onto a 
majority of nodes on non-sharded replica sets. On sharded clusters, it majority-writes the new value 
onto every shard and the config server. This ensures that every mongod in the cluster will be able 
to recover the most recently written value for all cluster server parameters on restart. 
Additionally, `setClusterParameter` blocks until the majority write has succeeded on every replica 
set in the cluster, which guarantees that the parameter value will not be rolled back after being 
set. Mongoses poll the config server for updated cluster server parameter values every `clusterServerParameterRefreshIntervalSecs`.

`getClusterParameter` returns the cached value of the requested cluster server parameter on the node
that it is run on. It can accept a single cluster server parameter name, a list of names, or `*` to 
return all cluster server parameter values on the node.

As indicated in the [Server Parameters Syntax](#server-parameters-syntax) section above, specifying
`cpp_vartype` for cluster server parameters must result in the usage of an IDL-defined type that has
`ClusterServerParameter` listed as a chained struct. It is also highly recommended to implement a 
validator callback function and register it to the cluster server parameter via the `validator` 
field. These validators are called before the new value of the cluster server parameter is written 
to disk during `setClusterParameter`. 
See [server_parameter_with_storage_test.idl][cluster-server-param-with-storage-test] and
[server_parameter_with_storage_test_structs.idl][cluster-server-param-with-storage-test-structs] for
examples.

Cluster server parameters can also be specified as specialized server parameters. The chart below
helps depict how base `ServerParameter` methods can be handled:

| `ServerParameter` method    | Override            | Default Behavior                            |
| --------------------------- | ------------------- | --------------------------------------------|
| constructor                 | `override_ctor`     | Instantiates only the name and type.        |                 
| `set()`                     | Required            | None, won't compile without implementation. |
| `setFromString()`           | Prohibited          | Returns `ErrorCodes::BadValue`.             |
| `append()`                  | Required            | None, won't compile without implementation. |
| `validate()`                | `override_validate` | Return `Status::OK()` without any checks.   |
| `reset()`                   | Required            | None, won't compile without implementation. |
| `getClusterParameterTime()` | Required            | Return `LogicalTime::kUninitialized`.       |

 
* Specifying `override_ctor` to true is optional. If the cluster server parameter needs to have any
storage initialized at the same time as parameter registration, then an overridden constructor could
be useful. Otherwise, the default likely suffices provided that all storage modified via `set()` is
instantiated in another way.
* It is highly recommended to specify `override_validate` to true and provide a custom implementation
of the `validate` method. This ensures that cluster parameters do not get set to nonsensical values.
* `set()` must be implemented in order to update in-memory parameter storage. It will be called from
an `OpObserver` after observing a change to the cluster parameter document on-disk.
* `append()` must be implemented in order to serialize the parameter into BSON for use in 
`getClusterParameter`.
* `setFromString()` must never be implemented as cluster server parameters are only set via BSON
during runtime.  
* `getClusterParameterTime` must be implemented and should return a `LogicalTime` corresponding to 
the current version of the cluster server parameter.
* `reset()` must be implemented and should update the cluster server parameter back to its default
value.  

All cluster server parameters are tenant-aware, meaning that on serverless clusters, each tenant has
an isolated set of parameters. The `setClusterParameter` and `getClusterParameter` commands will pass
the `tenantId` on the command request to the `ServerParameter`'s methods. On dedicated
(non-serverless) clusters, `boost::none` will be passed. IDL-defined cluster server parameters will
handle the passed-in `tenantId` automatically and store separate parameter values per-tenant.
Specialized server parameters will have to take care to correctly handle the passed-in `tenantId` and
to enforce tenant isolation.

Like normal server parameters, cluster server parameters can be defined to be dependent on a minimum
FCV version or a specific feature flag using the `condition: min_fcv/feature_flag:` syntax discussed
above. During FCV downgrade, the cluster parameter's stored on-disk value will be deleted if either:
(1) The downgraded FCV is lower than the cluster parameter's `min_fcv`, or (2) The cluster
parameter's `feature_flag` is disabled on the downgraded FCV. While a cluster server parameter is
disabled due to either of these conditions, `setClusterParameter` on it will always fail, and
`getClusterParameter` will fail on `mongod`, and return the default value on `mongos` -- this
difference in behavior is due to `mongos` being unaware of the current FCV.

See [server_parameter_specialized_test.idl][specialized-cluster-server-param-test-idl] and 
[server_parameter_specialized_test.h][specialized-cluster-server-param-test-data] for examples.

### String or Expression Map
The default and implicit fields above, as well as the `gt`, `lt`, `gte`, and `lte` validators accept 
either a simple scalar string which is treated as a literal value, or a yaml map containing an 
attribute called `expr`, which must be a string containing an arbitrary C++ expression to be used 
as-is. Optionally, an expression map may also include the `is_constexpr: false` attribute, which 
will suspend enforcement of the value being a `constexpr`.

For example, consider:
```yaml
server_parameters:
  connPoolMaxInUseConnsPerHost:
    ...
    cpp_varname: maxInUseConnsPerHost
    default:
      expr: std::numeric_limits<int>::max()
    ...
```

Here, the server parameter's default value is the evaluation of the C++ expression 
`std::numeric_limits<int>::max()`. Additionally, since default was not explicitly given the 
`is_constexpr: false` attribute, it will be round-tripped through the following lambda to guarantee 
that it does not rely on runtime information.
```cpp
[]{ constexpr auto value = <expr>; return value; }()
```

[parameters.idl]: ../src/mongo/db/commands/parameters.idl
[set-parameter]: https://docs.mongodb.com/manual/reference/parameters/#synopsis
[get-parameter]: https://docs.mongodb.com/manual/reference/command/getParameter/#getparameter
[quiet-param]: https://github.com/mongodb/mongo/search?q=serverGlobalParams+quiet+extension:idl&type=code
[ftdc-file-size-param]: ../src/mongo/db/ftdc/ftdc_server.idl
[cluster-server-param-with-storage-test]: ../src/mongo/idl/server_parameter_with_storage_test.idl
[cluster-server-param-with-storage-test-structs]: ../src/mongo/idl/server_parameter_with_storage_test_structs.idl
[specialized-cluster-server-param-test-idl]: ../src/mongo/idl/server_parameter_specialized_test.idl
[specialized-cluster-server-param-test-data]: ../src/mongo/idl/server_parameter_specialized_test.h