16 #include <aws/core/Aws.h> 17 #include <aws/core/utils/Outcome.h> 18 #include <aws/core/utils/logging/LogMacros.h> 19 #include <aws/logs/CloudWatchLogsErrors.h> 20 #include <aws/logs/model/CreateLogGroupRequest.h> 21 #include <aws/logs/model/CreateLogStreamRequest.h> 22 #include <aws/logs/model/DescribeLogGroupsRequest.h> 23 #include <aws/logs/model/DescribeLogGroupsResult.h> 24 #include <aws/logs/model/DescribeLogStreamsRequest.h> 25 #include <aws/logs/model/DescribeLogStreamsResult.h> 26 #include <aws/logs/model/InputLogEvent.h> 27 #include <aws/logs/model/LogStream.h> 28 #include <aws/logs/model/PutLogEventsRequest.h> 35 std::chrono::milliseconds now() {
36 return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
41 namespace CloudWatchLogs {
54 this->
cw_client_ = std::make_shared<Aws::CloudWatchLogs::CloudWatchLogsClient>(client_config);
63 const Aws::CloudWatchLogs::Model::PutLogEventsRequest & request, Aws::String & next_token)
72 AWS_LOG_WARN(__func__,
"PutLogEvents occurring too quickly, rate limiting in effect. Delaying PutLogs call by %d ms", sleep_for.count());
73 std::this_thread::sleep_for(sleep_for);
76 auto response = this->
cw_client_->PutLogEvents(request);
78 if (!response.IsSuccess()) {
80 AWS_LOGSTREAM_ERROR(__func__,
"Send log request failed due to: " 81 << response.GetError().GetMessage() <<
", with error code: " 82 <<
static_cast<int>(response.GetError().GetErrorType()));
84 switch(response.GetError().GetErrorType()) {
86 case Aws::CloudWatchLogs::CloudWatchLogsErrors::NETWORK_CONNECTION:
89 case Aws::CloudWatchLogs::CloudWatchLogsErrors::INVALID_PARAMETER_COMBINATION:
90 case Aws::CloudWatchLogs::CloudWatchLogsErrors::INVALID_PARAMETER_VALUE:
91 case Aws::CloudWatchLogs::CloudWatchLogsErrors::MISSING_PARAMETER:
99 AWS_LOG_DEBUG(__func__,
"Setting the sequence token to use for the next send log request.");
100 next_token = response.GetResult().GetNextSequenceToken();
107 Aws::String & next_token,
const std::string & log_group,
const std::string & log_stream,
111 Aws::Vector<Aws::CloudWatchLogs::Model::InputLogEvent> events;
114 AWS_LOGSTREAM_WARN(__func__,
116 << log_group <<
" Log Stream: " <<
121 Aws::CloudWatchLogs::Model::PutLogEventsRequest request;
122 request.SetLogGroupName(log_group.c_str());
123 request.SetLogStreamName(log_stream.c_str());
125 if (next_token !=
"") {
126 request.SetSequenceToken(next_token);
129 for (
auto & log : logs) {
130 events.push_back(log);
132 request.SetLogEvents(events);
135 request.SetSequenceToken(next_token);
138 AWS_LOGSTREAM_ERROR(__func__,
"Failed to send to CloudWatch in Log Group: " 139 << log_group <<
" Log Stream: " << log_stream
140 <<
" with error code: " << status);
143 AWS_LOGSTREAM_DEBUG(__func__,
144 "A batch of logs was successfully sent to CloudWatch in Log Group: " 145 << log_group <<
" Log Stream: " << log_stream <<
".");
149 if (!events.empty()) {
150 request.SetLogEvents(events);
153 AWS_LOGSTREAM_ERROR(__func__,
"Failed to send to CloudWatch in Log Group: " 154 << log_group <<
" Log Stream: " << log_stream
155 <<
" with error code: " << status);
157 AWS_LOGSTREAM_DEBUG(__func__,
"All queued logs were successfully sent to CloudWatch in Log Group: " 158 << log_group <<
" Log Stream: " << log_stream <<
".");
166 const std::string & log_group)
170 Aws::CloudWatchLogs::Model::CreateLogGroupRequest log_group_request;
171 log_group_request.SetLogGroupName(log_group.c_str());
173 const auto & response = this->
cw_client_->CreateLogGroup(log_group_request);
174 if (!response.IsSuccess()) {
177 __func__,
"Failed to create Log Group :" 178 << log_group <<
" due to: " << response.GetError().GetMessage()
179 <<
", with error code: " <<
static_cast<int>(response.GetError().GetErrorType()));
181 if (response.GetError().GetErrorType() ==
182 Aws::CloudWatchLogs::CloudWatchLogsErrors::RESOURCE_ALREADY_EXISTS) {
185 }
else if(response.GetError().GetErrorType() == Aws::CloudWatchLogs::CloudWatchLogsErrors::NETWORK_CONNECTION) {
196 const std::string & log_group)
199 Aws::CloudWatchLogs::Model::DescribeLogGroupsRequest describe_log_group_request;
200 Aws::String next_token;
202 describe_log_group_request.SetLogGroupNamePrefix(log_group.c_str());
205 if (next_token.size() != 0) {
206 describe_log_group_request.SetNextToken(next_token);
209 const auto & response = this->
cw_client_->DescribeLogGroups(describe_log_group_request);
210 if (!response.IsSuccess()) {
212 if(response.GetError().GetErrorType() == Aws::CloudWatchLogs::CloudWatchLogsErrors::NETWORK_CONNECTION) {
218 AWS_LOGSTREAM_WARN(__func__,
"Request to check if log group named " 219 << log_group <<
" exists failed. Error message: " 220 << response.GetError().GetMessage() <<
", with error code: " 221 <<
static_cast<int>(response.GetError().GetErrorType()));
226 auto & log_group_list = response.GetResult().GetLogGroups();
227 next_token = response.GetResult().GetNextToken();
229 for (
const auto & curr_log_group : log_group_list) {
230 if (curr_log_group.GetLogGroupName().c_str() == log_group) {
231 AWS_LOGSTREAM_DEBUG(__func__,
"Found Log Group named: " << log_group <<
".");
237 AWS_LOGSTREAM_INFO(__func__,
"Failed to find Log Group named: " << log_group <<
".");
246 const std::string & log_group,
const std::string & log_stream)
250 Aws::CloudWatchLogs::Model::CreateLogStreamRequest log_stream_request;
251 log_stream_request.SetLogGroupName(log_group.c_str());
252 log_stream_request.SetLogStreamName(log_stream.c_str());
254 const auto & response = this->
cw_client_->CreateLogStream(log_stream_request);
255 if (!response.IsSuccess()) {
257 AWS_LOGSTREAM_ERROR(__func__,
"Failed to create Log Stream :" 258 << log_stream <<
" in Log Group :" << log_group <<
" due to: " 259 << response.GetError().GetMessage() <<
", with error code: " 260 <<
static_cast<int>(response.GetError().GetErrorType()));
261 if (response.GetError().GetErrorType() ==
262 Aws::CloudWatchLogs::CloudWatchLogsErrors::RESOURCE_ALREADY_EXISTS) {
264 }
else if(response.GetError().GetErrorType() == Aws::CloudWatchLogs::CloudWatchLogsErrors::NETWORK_CONNECTION) {
275 const std::string & log_group,
const std::string & log_stream,
276 Aws::CloudWatchLogs::Model::LogStream * log_stream_object)
279 Aws::CloudWatchLogs::Model::DescribeLogStreamsRequest describe_log_stream_request;
280 Aws::String next_token;
282 describe_log_stream_request.SetLogGroupName(log_group.c_str());
283 describe_log_stream_request.SetLogStreamNamePrefix(log_stream.c_str());
286 if (next_token.size() != 0) {
287 describe_log_stream_request.SetNextToken(next_token);
290 const auto & response = this->
cw_client_->DescribeLogStreams(describe_log_stream_request);
291 if (!response.IsSuccess()) {
293 if(response.GetError().GetErrorType() == Aws::CloudWatchLogs::CloudWatchLogsErrors::NETWORK_CONNECTION) {
301 __func__,
"Request to check if log stream named " 302 << log_stream <<
" exists in log group named: " << log_group
303 <<
". Error message: " << response.GetError().GetMessage()
304 <<
", with error code: " <<
static_cast<int>(response.GetError().GetErrorType()));
308 auto & log_stream_list = response.GetResult().GetLogStreams();
309 next_token = response.GetResult().GetNextToken();
311 for (
const auto & curr_log_stream : log_stream_list) {
312 if (curr_log_stream.GetLogStreamName().c_str() == log_stream) {
313 AWS_LOGSTREAM_DEBUG(__func__,
"Found Log Stream named: " << log_stream <<
" in Log Group :" 314 << log_group <<
".");
315 if (
nullptr != log_stream_object) {
316 *log_stream_object = curr_log_stream;
323 AWS_LOGSTREAM_INFO(__func__,
"Failed to find Log Stream named: " << log_stream
333 const std::string & log_group,
const std::string & log_stream, Aws::String & next_token)
336 Aws::CloudWatchLogs::Model::LogStream log_stream_object;
343 AWS_LOGSTREAM_ERROR(__func__,
"Failed to obtain sequence token due to Log Stream: " 344 << log_stream <<
" in Log Group :" << log_group
345 <<
" doesn't exist.");
347 next_token = log_stream_object.GetUploadSequenceToken();
std::chrono::milliseconds last_put_time_
virtual Aws::CloudWatchLogs::ROSCloudWatchLogsErrors SendLogsToCloudWatch(Aws::String &next_token, const std::string &log_group, const std::string &log_stream, LogCollection &logs)
Sends a list of logs to CloudWatch.
virtual Aws::CloudWatchLogs::ROSCloudWatchLogsErrors GetLogStreamToken(const std::string &log_group, const std::string &log_stream, Aws::String &next_token)
Gets the next sequence token to use for sending logs to cloudwatch.
std::shared_ptr< Aws::CloudWatchLogs::CloudWatchLogsClient > cw_client_
Aws::CloudWatchLogs::ROSCloudWatchLogsErrors SendLogsRequest(const Aws::CloudWatchLogs::Model::PutLogEventsRequest &request, Aws::String &next_token)
std::list< LogType > LogCollection
virtual Aws::CloudWatchLogs::ROSCloudWatchLogsErrors CheckLogStreamExists(const std::string &log_group, const std::string &log_stream, Aws::CloudWatchLogs::Model::LogStream *log_stream_object)
Check if a log stream in a log group exists.
virtual Aws::CloudWatchLogs::ROSCloudWatchLogsErrors CreateLogStream(const std::string &log_group, const std::string &log_stream)
Creates a log stream in the specified log group.
virtual Aws::CloudWatchLogs::ROSCloudWatchLogsErrors CheckLogGroupExists(const std::string &log_group)
Check if a log group exists.
Contains Error handling functionality for ROS AWS CloudWatch Logs libraries.
CloudWatchLogsFacade()=default
virtual Aws::CloudWatchLogs::ROSCloudWatchLogsErrors CreateLogGroup(const std::string &log_group)
Creates a log group.
const std::chrono::milliseconds kMinPutLogsPeriod
constexpr uint16_t kMaxLogsPerRequest
ROSCloudWatchLogsErrors
Defines error return codes for functions This enum defines standard error codes that will be returned...