aboutsummaryrefslogtreecommitdiffstats
path: root/yt/yt/core/misc/statistics.h
blob: 606992cfc4c24acafedb56cbac23de0a271837e7 (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
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
#pragma once

#include "public.h"

#include <yt/yt/core/yson/forwarding_consumer.h>
#include <yt/yt/core/yson/consumer.h>
#include <yt/yt/core/yson/building_consumer.h>

#include <yt/yt/core/ytree/tree_builder.h>
#include <yt/yt/core/ytree/convert.h>

#include <yt/yt/core/actions/callback.h>

#include <yt/yt/core/misc/property.h>

#include <util/generic/iterator_range.h>

namespace NYT {

////////////////////////////////////////////////////////////////////////////////

class TSummary
{
public:
    TSummary();

    TSummary(i64 sum, i64 count, i64 min, i64 max, std::optional<i64> last);

    void AddSample(i64 sample);

    void Merge(const TSummary& summary);

    void Reset();

    DEFINE_BYVAL_RO_PROPERTY(i64, Sum);
    DEFINE_BYVAL_RO_PROPERTY(i64, Count);
    DEFINE_BYVAL_RO_PROPERTY(i64, Min);
    DEFINE_BYVAL_RO_PROPERTY(i64, Max);
    DEFINE_BYVAL_RO_PROPERTY(std::optional<i64>, Last);

    void Persist(const TStreamPersistenceContext& context);

    bool operator == (const TSummary& other) const;

    friend class TStatisticsBuildingConsumer;
};

void Serialize(const TSummary& summary, NYson::IYsonConsumer* consumer);

////////////////////////////////////////////////////////////////////////////////

class TStatistics
{
public:
    using TSummaryMap = std::map<NStatisticPath::TStatisticPath, TSummary>;
    using TSummaryRange = TIteratorRange<TSummaryMap::const_iterator>;
    DEFINE_BYREF_RO_PROPERTY(TSummaryMap, Data);
    DEFINE_BYVAL_RW_PROPERTY(std::optional<TInstant>, Timestamp);

public:
    void AddSample(const NStatisticPath::TStatisticPath& path, i64 sample);

    void AddSample(const NStatisticPath::TStatisticPath& path, const NYTree::INodePtr& sample);

    template <class T>
    void AddSample(const NStatisticPath::TStatisticPath& path, const T& sample);

    void ReplacePathWithSample(const NStatisticPath::TStatisticPath& path, i64 sample);

    void ReplacePathWithSample(const NStatisticPath::TStatisticPath& path, const NYTree::INodePtr& sample);

    template <class T>
    void ReplacePathWithSample(const NStatisticPath::TStatisticPath& path, const T& sample);

    //! Merge statistics by merging summaries for each common statistics path.
    void Merge(const TStatistics& statistics);
    //! Merge statistics by taking summary from #statistics for each common statistics path.
    void MergeWithOverride(const TStatistics& statistics);

    //! Get range of all elements whose path starts with a given strict prefix path (possibly empty).
    /*!
     * Pre-requisites: `prefixPath` must not have terminating slash.
     * Examples: /a/b is a prefix path for /a/b/hij but not for /a/bcd/efg nor /a/b itself.
     */
    TSummaryRange GetRangeByPrefix(const NStatisticPath::TStatisticPath& prefixPath) const;

    //! Remove all the elements starting from prefixPath.
    //! The requirements for prefixPath are the same as in GetRangeByPrefix.
    void RemoveRangeByPrefix(const NStatisticPath::TStatisticPath& prefixPath);

    void Persist(const TStreamPersistenceContext& context);

private:
    template <class TCallback>
    void ProcessNodeWithCallback(const NStatisticPath::TStatisticPath& path, const NYTree::INodePtr& sample, TCallback callback);

    TSummary& GetSummary(const NStatisticPath::TStatisticPath& path);

    friend class TStatisticsBuildingConsumer;
};

i64 GetNumericValue(const TStatistics& statistics, const NStatisticPath::TStatisticPath& path);

std::optional<i64> FindNumericValue(const TStatistics& statistics, const NStatisticPath::TStatisticPath& path);
std::optional<TSummary> FindSummary(const TStatistics& statistics, const NStatisticPath::TStatisticPath& path);

////////////////////////////////////////////////////////////////////////////////

DEFINE_ENUM(EStatisticPathConflictType,
    (HasPrefix)
    (IsPrefix)
    (Exists)
    (None)
);

////////////////////////////////////////////////////////////////////////////////

void Serialize(const TStatistics& statistics, NYson::IYsonConsumer* consumer);

void CreateBuildingYsonConsumer(std::unique_ptr<NYson::IBuildingYsonConsumer<TStatistics>>* buildingConsumer, NYson::EYsonType ysonType);

////////////////////////////////////////////////////////////////////////////////

class TStatisticsConsumer
    : public NYson::TForwardingYsonConsumer
{
public:
    using TSampleHandler = TCallback<void(const NYTree::INodePtr& sample)>;
    explicit TStatisticsConsumer(TSampleHandler consumer);

private:
    const std::unique_ptr<NYTree::ITreeBuilder> TreeBuilder_;
    const TSampleHandler SampleHandler_;

    void OnMyListItem() override;
};

////////////////////////////////////////////////////////////////////////////////

template <class TTags>
class TTaggedStatistics
{
public:
    using TTaggedSummaries = THashMap<TTags, TSummary>;
    using TSummaryMap = std::map<NStatisticPath::TStatisticPath, TTaggedSummaries>;

    void AppendStatistics(const TStatistics& statistics, TTags tags);
    void AppendTaggedSummary(const NStatisticPath::TStatisticPath& path, const TTaggedSummaries& taggedSummaries);

    const TTaggedSummaries* FindTaggedSummaries(const NStatisticPath::TStatisticPath& path) const;
    const TSummaryMap& GetData() const;

    void Persist(const TStreamPersistenceContext& context);

private:
    TSummaryMap Data_;
};

////////////////////////////////////////////////////////////////////////////////

template <class TTags>
void Serialize(const TTaggedStatistics<TTags>& statistics, NYson::IYsonConsumer* consumer);

////////////////////////////////////////////////////////////////////////////////

template <class TValue>
void SerializeStatisticPathsMap(
    const std::map<NStatisticPath::TStatisticPath, TValue>& map,
    NYson::IYsonConsumer* consumer,
    const std::function<void(const TValue&, NYson::IYsonConsumer*)>& valueSerializer);

////////////////////////////////////////////////////////////////////////////////

} // namespace NYT

#define STATISTICS_INL_H_
#include "statistics-inl.h"
#undef STATISTICS_INL_H_