# FTDC

## Table of Contents

- [High Level Overview](#high-level-overview)

## High Level Overview

FTDC stands for Full-Time Diagnostic Data Capture. FTDC is used to capture data about the mongod and
mongos processes and the system that a mongo process is running on.

From a top down view, An
[`FTDCController`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/controller.h)
object lives as a decoration on the service context. It is registered
[`here`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/ftdc_server.cpp#L55). The
`FTDCController` is initialized from the mongod and mongos main functions, which call
[`startMongoDFTDC`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/ftdc_mongod.h)
and
[`startMongoSFTDC`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/ftdc_mongos.h)
respectively. The FTDC controller owns a collection of collector objects that gather system and
process information for the controller. These sets of collector objects are stored in a
[`FTDCCollectorCollection`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/collector.h#L77-L116)
object, allowing all the data to be collected through one call to collect on the
`FTDCCollectorCollection`. There are two sets of `FTDCCollectorCollection` objects on the
controller:
[_periodicCollectors](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/controller.h#L200-L201)
that collects data at a specified time interval, and
[_rotateCollectors](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/controller.h#L207-L208)
that collects one set of data every time a file is created.

At specified time intervals, the FTDC Controller calls collect on the `_periodicCollectors`
collection. To collect the data, most collectors run existing commands via
[`CommandHelpers::runCommandDirectly`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/commands.h#L219-L224)
which is abstracted into `FTDCSimpleInternalCommandCollector`. Some process data is gathered via
custom implementations of `FTDCCollectorInterface`. After gathering the data, the FTDC Controller
[writes](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/controller.cpp#L251-L252)
the data out as described below using an
[`FTDCFileManager`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/file_manager.h).

Most collectors are of the class
[`FTDCSimpleInternalCommandCollector`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/ftdc_server.cpp#L173).
The
[`FTDCServerStatusCommandCollector`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/ftdc_server.cpp#L195).
has a very specific query that it needs to run to get the server information. For example, it does
not collect sharding information from `serverStatus` because sharding could trigger issues with
compression efficiency of FTDC. The system stats are collected by `LinuxSystemMetricsCollector` via
`/proc` on Linux and `WindowsSystemMetricsCollector` via Windows perf counters on Windows.

The
[`FTDCFileManager`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/file_manager.h)
is responsible for rotating files, managing disk space, and recovering files after a crash. When it
gets a hold of the data to be written to disk, it initially writes the data to an
[`FTDCCompressor`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/compressor.h)
object. The
[`FTDCCompressor`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/compressor.h)
compresses the data object and appends it to a chunk to be written out. If the chunk is full or the
BSON Schema has changed, the compressor indicates that the chunk needs to be written out to disk
immediately. Otherwise, the compressor indicates that it can store more data.

If the compressor can store more data there are two possibilities. If the data in the compressor has
reached a certain threshold, the
[`FTDCFileWriter`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/file_writer.h)
will decide to write out the unwritten section of data to an interim file. The goal of the interim
file is to flush data out in smaller intervals between archives to ensure the most up-to-date data
is recorded before a crash. The interim file also provides a chance for the regular files to have
maximum sized and compressed chunks. If not, nothing is written to outside of the compressor. If the
compressor indicates that the chunk needs to be written out immediately, data is flushed out of the
compressor into the archive file. The interim file is erased and written over, and the compressor
resets to take in new values.

The
[`FTDCFileManager`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/file_manager.h)
also decides when to rotate the archive files. When the file gets too large, the manager deletes the
reference to the old file and starts writing immediately to the new file by calling
[rotate](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/ftdc/file_manager.cpp#L304-L324).
