Coverage Report

Created: 2026-06-17 02:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/service/http/action/warmup_stats_action.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "service/http/action/warmup_stats_action.h"
19
20
#include <chrono>
21
#include <list>
22
#include <set>
23
#include <string>
24
#include <thread>
25
26
#include "cloud/cloud_warmup_metrics.h"
27
#include "service/http/http_channel.h"
28
#include "service/http/http_headers.h"
29
#include "service/http/http_request.h"
30
#include "service/http/http_status.h"
31
#include "util/debug_points.h"
32
#include "util/easy_json.h"
33
34
namespace doris {
35
36
// Fill windowed num/size metrics into a JSON object
37
static void fill_windowed(EasyJson& parent, const std::string& key, MBvarWindowedAdder& num_adder,
38
0
                          MBvarWindowedAdder& size_adder, const std::string& dim_key) {
39
0
    EasyJson obj = parent.Set(key, EasyJson::kObject);
40
0
    EasyJson num = obj.Set("num", EasyJson::kObject);
41
0
    num["5m"] = num_adder.get_window_value(dim_key, 0);
42
0
    num["30m"] = num_adder.get_window_value(dim_key, 1);
43
0
    num["1h"] = num_adder.get_window_value(dim_key, 2);
44
0
    EasyJson size = obj.Set("size", EasyJson::kObject);
45
0
    size["5m"] = size_adder.get_window_value(dim_key, 0);
46
0
    size["30m"] = size_adder.get_window_value(dim_key, 1);
47
0
    size["1h"] = size_adder.get_window_value(dim_key, 2);
48
0
}
49
50
0
void WarmUpStatsAction::handle(HttpRequest* req) {
51
0
    DBUG_EXECUTE_IF("WarmUpStatsAction.handle.return_error", {
52
0
        HttpChannel::send_reply(req, HttpStatus::INTERNAL_SERVER_ERROR,
53
0
                                "injected warmup stats error");
54
0
        return;
55
0
    });
56
0
    DBUG_EXECUTE_IF("WarmUpStatsAction.handle.sleep", {
57
0
        auto sleep_ms = dp->param<int64_t>("sleep_ms", 6000);
58
0
        std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
59
0
    });
60
61
    // Collect all job_id dimension keys from all metrics
62
0
    std::set<std::string> all_keys;
63
0
    for (auto& k : g_warmup_ed_requested_segment_num.list_dimensions()) all_keys.insert(k);
64
0
    for (auto& k : g_warmup_ed_requested_index_num.list_dimensions()) all_keys.insert(k);
65
0
    for (auto& k : g_warmup_ed_finish_segment_num.list_dimensions()) all_keys.insert(k);
66
0
    for (auto& k : g_warmup_ed_finish_index_num.list_dimensions()) all_keys.insert(k);
67
0
    for (auto& k : g_warmup_ed_fail_segment_num.list_dimensions()) all_keys.insert(k);
68
0
    for (auto& k : g_warmup_ed_fail_index_num.list_dimensions()) all_keys.insert(k);
69
0
    for (auto& k : g_warmup_ed_downstream_progress_tracker.list_job_ids()) all_keys.insert(k);
70
71
0
    EasyJson result;
72
0
    result["code"] = 0;
73
0
    EasyJson jobs = result.Set("data", EasyJson::kArray);
74
75
0
    for (auto& job_id_str : all_keys) {
76
0
        EasyJson entry = jobs.PushBack(EasyJson::kObject);
77
0
        try {
78
0
            entry["job_id"] = static_cast<int64_t>(std::stoll(job_id_str));
79
0
        } catch (...) {
80
0
            entry["job_id"] = 0;
81
0
        }
82
83
        // requested
84
0
        EasyJson req_obj = entry.Set("requested", EasyJson::kObject);
85
0
        fill_windowed(req_obj, "seg", g_warmup_ed_requested_segment_num,
86
0
                      g_warmup_ed_requested_segment_size, job_id_str);
87
0
        fill_windowed(req_obj, "idx", g_warmup_ed_requested_index_num,
88
0
                      g_warmup_ed_requested_index_size, job_id_str);
89
90
        // finish
91
0
        EasyJson fin_obj = entry.Set("finish", EasyJson::kObject);
92
0
        fill_windowed(fin_obj, "seg", g_warmup_ed_finish_segment_num,
93
0
                      g_warmup_ed_finish_segment_size, job_id_str);
94
0
        fill_windowed(fin_obj, "idx", g_warmup_ed_finish_index_num, g_warmup_ed_finish_index_size,
95
0
                      job_id_str);
96
97
        // fail
98
0
        EasyJson fail_obj = entry.Set("fail", EasyJson::kObject);
99
0
        fill_windowed(fail_obj, "seg", g_warmup_ed_fail_segment_num, g_warmup_ed_fail_segment_size,
100
0
                      job_id_str);
101
0
        fill_windowed(fail_obj, "idx", g_warmup_ed_fail_index_num, g_warmup_ed_fail_index_size,
102
0
                      job_id_str);
103
104
        // Timestamps
105
0
        auto* trigger_ts =
106
0
                g_warmup_ed_last_trigger_ts.get_stats(std::list<std::string> {job_id_str});
107
0
        entry["last_trigger_ts"] = trigger_ts ? trigger_ts->get_value() : 0;
108
0
        auto* finish_ts = g_warmup_ed_last_finish_ts.get_stats(std::list<std::string> {job_id_str});
109
0
        entry["last_finish_ts"] = finish_ts ? finish_ts->get_value() : 0;
110
        // Target-side progress watermark for trigger-gap calculation. Pending work reports the
111
        // earliest unfinished upstream trigger time; fully caught-up work reports the latest
112
        // finished upstream trigger time.
113
0
        entry["progress_trigger_ts"] =
114
0
                g_warmup_ed_downstream_progress_tracker.get_progress_ts(job_id_str);
115
0
    }
116
117
0
    req->add_output_header(HttpHeaders::CONTENT_TYPE, "application/json");
118
0
    HttpChannel::send_reply(req, HttpStatus::OK, result.ToString());
119
0
}
120
121
} // namespace doris