aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/vespa/storage/persistence/filestorage/service_layer_host_info_reporter.cpp
blob: 4f0384dfcb02b6a7d2f012c5a597dd5d2f5bf3fc (plain) (blame)
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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "service_layer_host_info_reporter.h"
#include <vespa/persistence/spi/resource_usage.h>
#include <vespa/storage/common/nodestateupdater.h>
#include <cmath>
#include <sstream>

#include <vespa/log/log.h>
LOG_SETUP(".persistence.filestor.service_layer_host_info_reporter");

namespace storage {

using Object = vespalib::JsonStream::Object;
using End = vespalib::JsonStream::End;

namespace {

const vespalib::string memory_label("memory");
const vespalib::string disk_label("disk");
const vespalib::string attribute_address_space_label("attribute-address-space");

void write_usage(vespalib::JsonStream& output, const vespalib::string &label, double value)
{
    output << label << Object();
    output << "usage" << value;
    output << End();
}

void write_attribute_usage(vespalib::JsonStream& output, const vespalib::string &label, const spi::AttributeResourceUsage &usage)
{
    output << label << Object();
    output << "usage" << usage.get_usage();
    output << "name" << usage.get_name();
    output << End();
}

bool want_immediate_report(const spi::ResourceUsage& old_usage, const spi::ResourceUsage& new_usage, double noise_level)
{
    auto disk_usage_diff = fabs(new_usage.get_disk_usage() - old_usage.get_disk_usage());
    auto memory_usage_diff = fabs(new_usage.get_memory_usage() - old_usage.get_memory_usage());
    auto address_space_diff = fabs(new_usage.get_attribute_address_space_usage().get_usage() - old_usage.get_attribute_address_space_usage().get_usage());
    bool address_space_got_valid = !old_usage.get_attribute_address_space_usage().valid() &&
            new_usage.get_attribute_address_space_usage().valid();
    return ((disk_usage_diff > noise_level) ||
            (memory_usage_diff > noise_level) ||
            (address_space_diff > noise_level) ||
            address_space_got_valid);
}

}

ServiceLayerHostInfoReporter::ServiceLayerHostInfoReporter(NodeStateUpdater& node_state_updater,
                                                           double noise_level)
    : HostReporter(),
      spi::ResourceUsageListener(),
      _node_state_updater(node_state_updater),
      _lock(),
      _old_resource_usage(),
      _noise_level(noise_level)
{
}

ServiceLayerHostInfoReporter::~ServiceLayerHostInfoReporter()
{
    spi::ResourceUsageListener::reset(); // detach
}

void
ServiceLayerHostInfoReporter::set_noise_level(double level)
{
    _noise_level.store(level, std::memory_order_relaxed);
}

namespace {

vespalib::string
to_string(const spi::ResourceUsage& usage)
{
    std::ostringstream oss;
    oss << usage;
    return oss.str();
}

}

void
ServiceLayerHostInfoReporter::update_resource_usage(const spi::ResourceUsage& resource_usage)
{
    double noise_level = _noise_level.load(std::memory_order_relaxed);
    bool immediate_report = want_immediate_report(_old_resource_usage, resource_usage, noise_level);
    LOG(debug, "update_resource_usage(): immediate_report=%s, noise_level=%f, old_usage=%s, new_usage=%s",
        (immediate_report ? "true" : "false"), noise_level, to_string(_old_resource_usage).c_str(),
        to_string(resource_usage).c_str());
    if (immediate_report) {
        _old_resource_usage = resource_usage;
    }
    {
        std::lock_guard guard(_lock);
        spi::ResourceUsageListener::update_resource_usage(resource_usage);
    }
    if (immediate_report) {
        _node_state_updater.request_almost_immediate_node_state_replies();
    }
}

void
ServiceLayerHostInfoReporter::report(vespalib::JsonStream& output)
{
    output << "content-node" << Object();
    output << "resource-usage" << Object();
    {
        std::lock_guard guard(_lock);
        auto& usage = get_usage();
        LOG(debug, "report(): usage=%s", to_string(usage).c_str());
        write_usage(output, memory_label, usage.get_memory_usage());
        write_usage(output, disk_label, usage.get_disk_usage());
        write_attribute_usage(output, attribute_address_space_label, usage.get_attribute_address_space_usage());
    }
    output << End();
    output << End();
}

}