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

mendersoftware / mender / 978727395

24 Aug 2023 11:26AM UTC coverage: 79.085% (+0.2%) from 78.84%
978727395

push

gitlab-ci

lluiscampos
feat: Implement `http::DownloadResumer`

Implement class to download the Artifact, which will react to server
disconnections or other sorts of short read by scheduling new HTTP
requests with `Range` header.

See https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests for
an introduction to the feature, and read the specification for more
details.

The user calls _once_ `AsyncCall` with the header and body handlers, and
`DownloadResumer` will call back these handlers _once_ (each). The data
is passed to the user at operation completion.

The validation of the `Content-Range` header and the cases for the unit
tests are heavily inspired by the legacy client. See:
* https://github.com/mendersoftware/mender/blob/<a class=hub.com/mendersoftware/mender/commit/d9010526d35d3ac861ea1e4210d36c2fef748ef8">d9010526d/client/update_resumer.go#L113
* https://github.com/mendersoftware/mender/blob/d9010526d35d3ac861ea1e4210d36c2fef748ef8/client/update_resumer_test.go#L197

Ticket: MEN-6498
Changelog: None

Signed-off-by: Lluis Campos <lluis.campos@northern.tech>

231 of 231 new or added lines in 3 files covered. (100.0%)

5706 of 7215 relevant lines covered (79.09%)

278.95 hits per line

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

80.0
/common/log.hpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#ifndef MENDER_LOG_HPP
16
#define MENDER_LOG_HPP
17

18
#include <config.h>
19

20
#ifdef MENDER_LOG_BOOST
21
#include <boost/log/common.hpp>
22
#include <boost/log/sources/logger.hpp>
23
#endif
24

25
#include <string>
26
#include <cassert>
27

28
#include <common/error.hpp>
29
#include <common/expected.hpp>
30

31
namespace mender {
32
namespace common {
33
namespace log {
34

35
using namespace std;
36

37
namespace error = mender::common::error;
38
namespace expected = mender::common::expected;
39

40
enum LogErrorCode {
41
        NoError = 0,
42
        InvalidLogLevelError,
43
        LogFileError,
44
};
45

46
class LogErrorCategoryClass : public std::error_category {
47
public:
48
        const char *name() const noexcept override;
49
        string message(int code) const override;
50
};
51
extern const LogErrorCategoryClass LogErrorCategory;
52

53
error::Error MakeError(LogErrorCode code, const string &msg);
54

55
struct LogField {
56
        LogField(const string &key, const string &value) :
57
                key {key},
58
                value {value} {
59
        }
60

61
        string key;
62
        string value;
63
};
64

65

66
enum class LogLevel {
67
        Fatal = 0,
68
        Error = 1,
69
        Warning = 2,
70
        Info = 3,
71
        Debug = 4,
72
        Trace = 5,
73
};
74

75
using ExpectedLogLevel = expected::expected<LogLevel, error::Error>;
76

77
inline string ToStringLogLevel(LogLevel lvl) {
5,841✔
78
        switch (lvl) {
5,841✔
79
        case LogLevel::Fatal:
×
80
                return "fatal";
×
81
        case LogLevel::Error:
220✔
82
                return "error";
220✔
83
        case LogLevel::Warning:
7✔
84
                return "warning";
7✔
85
        case LogLevel::Info:
573✔
86
                return "info";
573✔
87
        case LogLevel::Debug:
1,130✔
88
                return "debug";
1,130✔
89
        case LogLevel::Trace:
3,911✔
90
                return "trace";
3,911✔
91
        }
92
        assert(false);
×
93
        return "unknown";
94
}
95

96
const LogLevel kDefaultLogLevel = LogLevel::Info;
97

98
ExpectedLogLevel StringToLogLevel(const string &level_str);
99

100
class Logger {
101
private:
102
#ifdef MENDER_LOG_BOOST
103
        boost::log::sources::severity_logger<LogLevel> logger;
104
#endif
105

106
        string name_ {};
107

108
        LogLevel level_;
109

110
        void AddField(const LogField &field);
111

112
        void Log_(LogLevel level, const string &message);
113

114
public:
115
        explicit Logger(const string &name);
116
        Logger(const string &name, LogLevel level);
117

118
        void SetLevel(LogLevel level);
119

120
        LogLevel Level();
121

122
        template <typename... Fields>
123
        Logger WithFields(const Fields &...fields) {
124
                auto l = Logger(this->name_);
125
                l.SetLevel(this->level_);
126
                for (const auto &f : {fields...}) {
127
                        l.AddField(f);
128
                }
129
                return l;
130
        }
131

132
        void Log(LogLevel level, const string &message) {
133
                if (level <= this->level_) {
134
                        Log_(level, message);
135
                }
136
        }
137

138
        void Fatal(const string &message) {
139
                Log(LogLevel::Fatal, message);
140
        }
141

142
        void Error(const string &message) {
143
                Log(LogLevel::Error, message);
144
        }
145

146
        void Warning(const string &message) {
147
                Log(LogLevel::Warning, message);
148
        }
149

150
        void Info(const string &message) {
151
                Log(LogLevel::Info, message);
152
        }
153

154
        void Debug(const string &message) {
155
                Log(LogLevel::Debug, message);
156
        }
157

158
        void Trace(const string &message) {
159
                Log(LogLevel::Trace, message);
160
        }
161
};
162

163

164
} // namespace log
165
} // namespace common
166
} // namespace mender
167

168

169
// Add a global logger to the namespace
170
namespace mender {
171
namespace common {
172
namespace log {
173

174
extern Logger global_logger_;
175

176
void SetLevel(LogLevel level);
177

178
error::Error SetupFileLogging(const string &log_file_path, bool exclusive = true);
179

180
LogLevel Level();
181

182
template <typename... Fields>
183
Logger WithFields(const Fields &...fields) {
184
        return global_logger_.WithFields(fields...);
185
}
186

187
void Log(LogLevel level, const string &message);
188
void Fatal(const string &message);
189
void Error(const string &message);
190
void Warning(const string &message);
191
void Info(const string &message);
192
void Debug(const string &message);
193
void Trace(const string &message);
194

195
} // namespace log
196
} // namespace common
197
} // namespace mender
198

199
#endif // MENDER_LOG_HPP
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

© 2025 Coveralls, Inc