• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tstack / lnav / 17589970077-2502

09 Sep 2025 05:00PM UTC coverage: 65.196% (-5.0%) from 70.225%
17589970077-2502

push

github

tstack
[format] add fields for source file/line

Knowing the source file/line context in a log
message can help find log messages when using
log2src.

56 of 70 new or added lines in 2 files covered. (80.0%)

13954 existing lines in 210 files now uncovered.

45516 of 69814 relevant lines covered (65.2%)

404154.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

45.67
/src/spectro_impls.cc
1
/**
2
 * Copyright (c) 2022, Timothy Stack
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * * Redistributions of source code must retain the above copyright notice, this
10
 * list of conditions and the following disclaimer.
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 * this list of conditions and the following disclaimer in the documentation
13
 * and/or other materials provided with the distribution.
14
 * * Neither the name of Timothy Stack nor the names of its contributors
15
 * may be used to endorse or promote products derived from this software
16
 * without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29

30
#include <memory>
31
#include <optional>
32

33
#include "spectro_impls.hh"
34

35
#include "base/itertools.hh"
36
#include "lnav.hh"
37
#include "logfile_sub_source.hh"
38
#include "textview_curses.hh"
39

40
using namespace lnav::roles::literals;
41

42
class filtered_sub_source
43
    : public text_sub_source
44
    , public text_time_translator
45
    , public list_overlay_source {
46
public:
UNCOV
47
    bool empty() const override { return this->fss_delegate->empty(); }
×
48

UNCOV
49
    size_t text_line_count() override { return this->fss_lines.size(); }
×
50

51
    line_info text_value_for_line(textview_curses& tc,
×
52
                                  int line,
53
                                  std::string& value_out,
54
                                  line_flags_t flags) override
55
    {
UNCOV
56
        this->fss_lines | lnav::itertools::nth(line)
×
UNCOV
57
            | lnav::itertools::for_each([&](const auto row) {
×
58
                  this->fss_delegate->text_value_for_line(
×
UNCOV
59
                      tc, *row, value_out, flags);
×
UNCOV
60
              });
×
61

62
        return {};
×
63
    }
64

UNCOV
65
    size_t text_size_for_line(textview_curses& tc,
×
66
                              int line,
67
                              line_flags_t raw) override
68
    {
69
        return this->fss_lines | lnav::itertools::nth(line)
×
UNCOV
70
            | lnav::itertools::map([&](const auto row) {
×
UNCOV
71
                   return this->fss_delegate->text_size_for_line(tc, *row, raw);
×
72
               })
73
            | lnav::itertools::unwrap_or(size_t{0});
×
74
    }
75

76
    void text_attrs_for_line(textview_curses& tc,
×
77
                             int line,
78
                             string_attrs_t& value_out) override
79
    {
UNCOV
80
        this->fss_lines | lnav::itertools::nth(line)
×
81
            | lnav::itertools::for_each([&](const auto row) {
×
UNCOV
82
                  this->fss_delegate->text_attrs_for_line(tc, *row, value_out);
×
UNCOV
83
              });
×
84
    }
85

86
    std::optional<vis_line_t> row_for_time(struct timeval time_bucket) override
×
87
    {
88
        return this->fss_time_delegate->row_for_time(time_bucket);
×
89
    }
90

UNCOV
91
    std::optional<row_info> time_for_row(vis_line_t row) override
×
92
    {
UNCOV
93
        return this->fss_lines | lnav::itertools::nth(row)
×
UNCOV
94
            | lnav::itertools::flat_map([this](const auto row) {
×
UNCOV
95
                   return this->fss_time_delegate->time_for_row(*row);
×
96
               });
×
97
    }
98

UNCOV
99
    void list_value_for_overlay(const listview_curses& lv,
×
100
                                vis_line_t line,
101
                                std::vector<attr_line_t>& value_out) override
102
    {
UNCOV
103
        if (this->fss_overlay_delegate != nullptr) {
×
UNCOV
104
            this->fss_overlay_delegate->list_value_for_overlay(
×
105
                lv, line, value_out);
106
        }
107
    }
108

109
    text_sub_source* fss_delegate;
110
    text_time_translator* fss_time_delegate;
111
    list_overlay_source* fss_overlay_delegate{nullptr};
112
    std::vector<vis_line_t> fss_lines;
113
};
114

115
log_spectro_value_source::log_spectro_value_source(intern_string_t colname)
1✔
116
    : lsvs_colname(colname)
1✔
117
{
118
    this->update_stats();
1✔
119
}
1✔
120

121
void
122
log_spectro_value_source::update_stats()
33✔
123
{
124
    auto& lss = lnav_data.ld_log_source;
33✔
125

126
    this->lsvs_begin_time = std::chrono::microseconds::zero();
33✔
127
    this->lsvs_end_time = std::chrono::microseconds::zero();
33✔
128
    this->lsvs_stats.clear();
33✔
129
    for (auto& ls : lss) {
66✔
130
        auto* lf = ls->get_file_ptr();
33✔
131

132
        if (lf == nullptr) {
33✔
UNCOV
133
            continue;
×
134
        }
135

136
        auto format = lf->get_format();
33✔
137
        const auto* stats = format->stats_for_value(this->lsvs_colname);
33✔
138

139
        if (stats == nullptr) {
33✔
UNCOV
140
            continue;
×
141
        }
142

143
        auto ll = lf->begin();
33✔
144

145
        if (this->lsvs_begin_time == std::chrono::microseconds::zero()
33✔
146
            || ll->get_time<std::chrono::microseconds>()
33✔
UNCOV
147
                < this->lsvs_begin_time)
×
148
        {
149
            this->lsvs_begin_time = ll->get_time<std::chrono::microseconds>();
33✔
150
        }
151
        ll = lf->end();
33✔
152
        --ll;
33✔
153
        if (ll->get_time<std::chrono::microseconds>() > this->lsvs_end_time) {
33✔
154
            this->lsvs_end_time = ll->get_time<std::chrono::microseconds>();
33✔
155
        }
156

157
        this->lsvs_found = true;
33✔
158
        this->lsvs_stats.merge(*stats);
33✔
159
    }
33✔
160

161
    if (this->lsvs_begin_time > std::chrono::microseconds::zero()) {
33✔
162
        auto filtered_begin_time = lss.find_line(lss.at(0_vl))
163
                                       ->get_time<std::chrono::microseconds>();
33✔
164
        auto filtered_end_time
165
            = lss.find_line(lss.at(vis_line_t(lss.text_line_count() - 1)))
33✔
166
                  ->get_time<std::chrono::microseconds>();
33✔
167

168
        if (filtered_begin_time > this->lsvs_begin_time) {
33✔
UNCOV
169
            this->lsvs_begin_time = filtered_begin_time;
×
170
        }
171
        if (filtered_end_time < this->lsvs_end_time) {
33✔
UNCOV
172
            this->lsvs_end_time = filtered_end_time;
×
173
        }
174
    }
175
}
33✔
176

177
void
178
log_spectro_value_source::spectro_bounds(spectrogram_bounds& sb_out)
32✔
179
{
180
    auto& lss = lnav_data.ld_log_source;
32✔
181

182
    if (lss.text_line_count() == 0) {
32✔
UNCOV
183
        return;
×
184
    }
185

186
    this->update_stats();
32✔
187

188
    sb_out.sb_begin_time = this->lsvs_begin_time;
32✔
189
    sb_out.sb_end_time = this->lsvs_end_time;
32✔
190
    sb_out.sb_min_value_out = this->lsvs_stats.lvs_min_value;
32✔
191
    sb_out.sb_max_value_out = this->lsvs_stats.lvs_max_value;
32✔
192
    sb_out.sb_count = this->lsvs_stats.lvs_count;
32✔
193
}
194

195
void
196
log_spectro_value_source::spectro_row(spectrogram_request& sr,
2✔
197
                                      spectrogram_row& row_out)
198
{
199
    auto& lss = lnav_data.ld_log_source;
2✔
200
    auto begin_line
201
        = lss.find_from_time(timeval{to_time_t(sr.sr_begin_time), 0})
2✔
202
              .value_or(0_vl);
2✔
203
    auto end_line = lss.find_from_time(timeval{to_time_t(sr.sr_end_time), 0})
2✔
204
                        .value_or(vis_line_t(lss.text_line_count()));
2✔
205

206
    for (const auto& msg_info : lss.window_at(begin_line, end_line)) {
396✔
207
        const auto& ll = msg_info.get_logline();
197✔
208
        if (ll.get_time<std::chrono::microseconds>() >= sr.sr_end_time) {
197✔
209
            break;
×
210
        }
211

212
        const auto& values = msg_info.get_values();
197✔
213
        auto lv_iter = find_if(values.lvv_values.begin(),
197✔
214
                               values.lvv_values.end(),
215
                               logline_value_name_cmp(&this->lsvs_colname));
197✔
216

217
        if (lv_iter != values.lvv_values.end()) {
197✔
218
            switch (lv_iter->lv_meta.lvm_kind) {
197✔
UNCOV
219
                case value_kind_t::VALUE_FLOAT:
×
UNCOV
220
                    row_out.add_value(sr, lv_iter->lv_value.d, ll.is_marked());
×
UNCOV
221
                    break;
×
222
                case value_kind_t::VALUE_INTEGER: {
197✔
223
                    row_out.add_value(sr, lv_iter->lv_value.i, ll.is_marked());
197✔
224
                    break;
197✔
225
                }
226
                default:
×
227
                    break;
×
228
            }
229
        }
230
    }
2✔
231

232
    row_out.sr_details_source_provider = [this](const spectrogram_request& sr,
4✔
233
                                                double range_min,
234
                                                double range_max) {
235
        auto& lss = lnav_data.ld_log_source;
×
236
        auto retval = std::make_unique<filtered_sub_source>();
×
237
        auto begin_line
UNCOV
238
            = lss.find_from_time(timeval{to_time_t(sr.sr_begin_time), 0})
×
UNCOV
239
                  .value_or(0_vl);
×
240
        auto end_line
241
            = lss.find_from_time(timeval{to_time_t(sr.sr_end_time), 0})
×
UNCOV
242
                  .value_or(vis_line_t(lss.text_line_count()));
×
243

UNCOV
244
        retval->fss_delegate = &lss;
×
245
        retval->fss_time_delegate = &lss;
×
246
        retval->fss_overlay_delegate = nullptr;
×
247
        for (const auto& msg_info : lss.window_at(begin_line, end_line)) {
×
248
            const auto& ll = msg_info.get_logline();
×
249
            if (ll.get_time<std::chrono::microseconds>() >= sr.sr_end_time) {
×
UNCOV
250
                break;
×
251
            }
252

UNCOV
253
            const auto& values = msg_info.get_values();
×
254
            auto lv_iter = find_if(values.lvv_values.begin(),
×
255
                                   values.lvv_values.end(),
256
                                   logline_value_name_cmp(&this->lsvs_colname));
×
257

UNCOV
258
            if (lv_iter != values.lvv_values.end()) {
×
259
                switch (lv_iter->lv_meta.lvm_kind) {
×
260
                    case value_kind_t::VALUE_FLOAT:
×
UNCOV
261
                        if (range_min <= lv_iter->lv_value.d
×
262
                            && lv_iter->lv_value.d < range_max)
×
263
                        {
264
                            retval->fss_lines.emplace_back(
×
UNCOV
265
                                msg_info.get_vis_line());
×
266
                        }
UNCOV
267
                        break;
×
UNCOV
268
                    case value_kind_t::VALUE_INTEGER:
×
269
                        if (range_min <= lv_iter->lv_value.i
×
UNCOV
270
                            && lv_iter->lv_value.i < range_max)
×
271
                        {
UNCOV
272
                            retval->fss_lines.emplace_back(
×
UNCOV
273
                                msg_info.get_vis_line());
×
274
                        }
UNCOV
275
                        break;
×
UNCOV
276
                    default:
×
UNCOV
277
                        break;
×
278
                }
279
            }
280
        }
281

282
        return retval;
×
283
    };
2✔
284
}
2✔
285

286
void
287
log_spectro_value_source::spectro_mark(textview_curses& tc,
×
288
                                       std::chrono::microseconds begin_time,
289
                                       std::chrono::microseconds end_time,
290
                                       double range_min,
291
                                       double range_max)
292
{
293
    // XXX need to refactor this and the above method
UNCOV
294
    auto& log_tc = lnav_data.ld_views[LNV_LOG];
×
295
    auto& lss = lnav_data.ld_log_source;
×
296
    auto begin_line
UNCOV
297
        = lss.find_from_time(timeval{to_time_t(begin_time), 0}).value_or(0_vl);
×
UNCOV
298
    auto end_line = lss.find_from_time(timeval{to_time_t(end_time), 0})
×
299
                        .value_or(vis_line_t(lss.text_line_count()));
×
300
    logline_value_vector values;
×
301
    string_attrs_t sa;
×
302

303
    for (auto curr_line = begin_line; curr_line < end_line; ++curr_line) {
×
UNCOV
304
        auto cl = lss.at(curr_line);
×
305
        const auto lf = lss.find(cl);
×
UNCOV
306
        auto ll = lf->begin() + cl;
×
307
        const auto* format = lf->get_format_ptr();
×
308

309
        if (!ll->is_message()) {
×
310
            continue;
×
311
        }
312

313
        values.clear();
×
UNCOV
314
        lf->read_full_message(ll, values.lvv_sbr);
×
315
        values.lvv_sbr.erase_ansi();
×
UNCOV
316
        sa.clear();
×
UNCOV
317
        format->annotate(lf.get(), cl, sa, values, false);
×
318

319
        auto lv_iter = find_if(values.lvv_values.begin(),
×
320
                               values.lvv_values.end(),
321
                               logline_value_name_cmp(&this->lsvs_colname));
×
322

323
        if (lv_iter != values.lvv_values.end()) {
×
UNCOV
324
            switch (lv_iter->lv_meta.lvm_kind) {
×
UNCOV
325
                case value_kind_t::VALUE_FLOAT:
×
326
                    if (range_min <= lv_iter->lv_value.d
×
327
                        && lv_iter->lv_value.d <= range_max)
×
328
                    {
UNCOV
329
                        log_tc.toggle_user_mark(&textview_curses::BM_USER,
×
330
                                                curr_line);
331
                    }
UNCOV
332
                    break;
×
UNCOV
333
                case value_kind_t::VALUE_INTEGER:
×
UNCOV
334
                    if (range_min <= lv_iter->lv_value.i
×
UNCOV
335
                        && lv_iter->lv_value.i <= range_max)
×
336
                    {
UNCOV
337
                        log_tc.toggle_user_mark(&textview_curses::BM_USER,
×
338
                                                curr_line);
339
                    }
UNCOV
340
                    break;
×
UNCOV
341
                default:
×
UNCOV
342
                    break;
×
343
            }
344
        }
345
    }
346
}
347

348
db_spectro_value_source::db_spectro_value_source(std::string colname)
4✔
349
    : dsvs_colname(std::move(colname))
4✔
350
{
351
    this->update_stats();
4✔
352
}
4✔
353

354
void
355
db_spectro_value_source::update_stats()
4✔
356
{
357
    this->dsvs_begin_time = std::chrono::microseconds::zero();
4✔
358
    this->dsvs_end_time = std::chrono::microseconds::zero();
4✔
359
    this->dsvs_stats.clear();
4✔
360

361
    auto& dls = lnav_data.ld_db_row_source;
4✔
362

363
    this->dsvs_column_index = dls.column_name_to_index(this->dsvs_colname);
4✔
364

365
    if (!dls.has_log_time_column()) {
4✔
366
        if (dls.dls_time_column_invalidated_at) {
2✔
367
            static const auto order_by_help = attr_line_t()
1✔
368
                                                  .append("ORDER BY"_keyword)
1✔
369
                                                  .append(" ")
1✔
370
                                                  .append("log_time"_variable)
1✔
371
                                                  .append(" ")
1✔
372
                                                  .append("ASC"_keyword)
1✔
373
                                                  .move();
2✔
374

375
            this->dsvs_error_msg
376
                = lnav::console::user_message::error(
2✔
377
                      "Cannot generate spectrogram for database results")
378
                      .with_reason(
2✔
379
                          attr_line_t()
2✔
380
                              .append("The ")
1✔
381
                              .append_quoted("log_time"_variable)
1✔
382
                              .appendf(
2✔
383
                                  FMT_STRING(" column is not in ascending "
2✔
384
                                             "order between rows {} and {}"),
385
                                  dls.dls_time_column_invalidated_at.value()
1✔
386
                                      - 1,
1✔
387
                                  dls.dls_time_column_invalidated_at.value()))
388
                      .with_note(
2✔
389
                          attr_line_t("An ascending ")
2✔
390
                              .append_quoted("log_time"_variable)
1✔
391
                              .append(
1✔
392
                                  " column is needed to render a spectrogram"))
393
                      .with_help(attr_line_t("Add an ")
2✔
394
                                     .append_quoted(order_by_help)
2✔
395
                                     .append(" clause to your ")
1✔
396
                                     .append("SELECT"_keyword)
1✔
397
                                     .append(" statement"))
1✔
398
                      .move();
2✔
399
        } else {
400
            this->dsvs_error_msg
401
                = lnav::console::user_message::error(
2✔
402
                      "Cannot generate spectrogram for database results")
403
                      .with_reason(
2✔
404
                          attr_line_t()
2✔
405
                              .append("No ")
1✔
406
                              .append_quoted("log_time"_variable)
1✔
407
                              .append(" column found in the result set"))
1✔
408
                      .with_note(
2✔
409
                          attr_line_t("An ascending ")
2✔
410
                              .append_quoted("log_time"_variable)
1✔
411
                              .append(
1✔
412
                                  " column is needed to render a spectrogram"))
413
                      .with_help(
2✔
414
                          attr_line_t("Include a ")
2✔
415
                              .append_quoted("log_time"_variable)
1✔
416
                              .append(" column in your ")
1✔
417
                              .append(" statement. Use an ")
1✔
418
                              .append("AS"_keyword)
1✔
419
                              .append(
1✔
420
                                  " directive to alias a computed timestamp"))
421
                      .move();
2✔
422
        }
423
        return;
4✔
424
    }
425

426
    if (!this->dsvs_column_index) {
2✔
427
        this->dsvs_error_msg
428
            = lnav::console::user_message::error(
2✔
429
                  "Cannot generate spectrogram for database results")
430
                  .with_reason(attr_line_t("unknown column -- ")
2✔
431
                                   .append_quoted(lnav::roles::variable(
2✔
432
                                       this->dsvs_colname)))
1✔
433
                  .with_help("Expecting a numeric column to visualize")
2✔
434
                  .move();
1✔
435
        return;
1✔
436
    }
437

438
    if (!dls.dls_headers[this->dsvs_column_index.value()].is_graphable()) {
1✔
439
        this->dsvs_error_msg
440
            = lnav::console::user_message::error(
2✔
441
                  "Cannot generate spectrogram for database results")
442
                  .with_reason(attr_line_t()
2✔
443
                                   .append_quoted(lnav::roles::variable(
2✔
444
                                       this->dsvs_colname))
1✔
445
                                   .append(" is not a numeric column"))
1✔
446
                  .with_help("Only numeric columns can be visualized")
2✔
447
                  .move();
1✔
448
        return;
1✔
449
    }
450

UNCOV
451
    if (dls.dls_row_cursors.empty()) {
×
452
        this->dsvs_error_msg
453
            = lnav::console::user_message::error(
×
454
                  "Cannot generate spectrogram for database results")
455
                  .with_reason("Result set is empty")
×
456
                  .move();
×
457
        return;
×
458
    }
459

460
    this->dsvs_begin_time = to_us(dls.dls_time_column.front());
×
UNCOV
461
    this->dsvs_end_time = to_us(dls.dls_time_column.back());
×
462

463
    auto find_res
UNCOV
464
        = dls.dls_headers | lnav::itertools::find_if([this](const auto& elem) {
×
UNCOV
465
              return elem.hm_name == this->dsvs_colname;
×
UNCOV
466
          });
×
467
    if (find_res) {
×
UNCOV
468
        auto hm = find_res.value();
×
469
        auto& bs = hm->hm_chart.get_stats_for(this->dsvs_colname);
×
UNCOV
470
        this->dsvs_stats.lvs_min_value = bs.bs_min_value;
×
471
        this->dsvs_stats.lvs_max_value = bs.bs_max_value;
×
472
    }
473

UNCOV
474
    this->dsvs_stats.lvs_count = dls.dls_row_cursors.size();
×
475
}
476

477
void
478
db_spectro_value_source::spectro_bounds(spectrogram_bounds& sb_out)
×
479
{
480
    auto& dls = lnav_data.ld_db_row_source;
×
481

UNCOV
482
    if (dls.text_line_count() == 0) {
×
UNCOV
483
        return;
×
484
    }
485

UNCOV
486
    this->update_stats();
×
487

488
    sb_out.sb_begin_time = this->dsvs_begin_time;
×
489
    sb_out.sb_end_time = this->dsvs_end_time;
×
490
    sb_out.sb_min_value_out = this->dsvs_stats.lvs_min_value;
×
491
    sb_out.sb_max_value_out = this->dsvs_stats.lvs_max_value;
×
UNCOV
492
    sb_out.sb_count = this->dsvs_stats.lvs_count;
×
493
}
494

495
void
UNCOV
496
db_spectro_value_source::spectro_row(spectrogram_request& sr,
×
497
                                     spectrogram_row& row_out)
498
{
UNCOV
499
    auto& dls = lnav_data.ld_db_row_source;
×
500
    auto begin_row
UNCOV
501
        = dls.row_for_time({to_time_t(sr.sr_begin_time), 0}).value_or(0_vl);
×
502
    auto end_row = dls.row_for_time({to_time_t(sr.sr_end_time), 0})
×
UNCOV
503
                       .value_or(vis_line_t(dls.dls_row_cursors.size()));
×
504

505
    for (auto lpc = begin_row; lpc < end_row; ++lpc) {
×
506
        auto get_res
UNCOV
507
            = dls.get_cell_as_double(lpc, this->dsvs_column_index.value());
×
508

509
        if (get_res) {
×
510
            row_out.add_value(sr, get_res.value(), false);
×
511
        }
512
    }
513

UNCOV
514
    row_out.sr_details_source_provider = [this](const spectrogram_request& sr,
×
515
                                                double range_min,
516
                                                double range_max) {
517
        auto& dls = lnav_data.ld_db_row_source;
×
518
        auto retval = std::make_unique<filtered_sub_source>();
×
519

UNCOV
520
        retval->fss_delegate = &dls;
×
521
        retval->fss_time_delegate = &dls;
×
522
        retval->fss_overlay_delegate = &lnav_data.ld_db_overlay;
×
523
        auto begin_row
UNCOV
524
            = dls.row_for_time({to_time_t(sr.sr_begin_time), 0}).value_or(0_vl);
×
525
        auto end_row = dls.row_for_time({to_time_t(sr.sr_end_time), 0})
×
UNCOV
526
                           .value_or(vis_line_t(dls.dls_row_cursors.size()));
×
527

UNCOV
528
        for (auto lpc = begin_row; lpc < end_row; ++lpc) {
×
529
            auto get_res
UNCOV
530
                = dls.get_cell_as_double(lpc, this->dsvs_column_index.value());
×
UNCOV
531
            if (!get_res) {
×
UNCOV
532
                continue;
×
533
            }
UNCOV
534
            auto value = get_res.value();
×
UNCOV
535
            if ((range_min == value)
×
UNCOV
536
                || (range_min < value && value < range_max))
×
537
            {
UNCOV
538
                retval->fss_lines.emplace_back(lpc);
×
539
            }
540
        }
541

UNCOV
542
        return retval;
×
543
    };
544
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc