Logging - AWS SDK for C++

Logging

The AWS SDK for C++ includes configurable logging that generates a record of actions performed by the SDK during execution. To enable logging, set the LogLevel of SDKOptions to the appropriate verbosity for your application.

Aws::SDKOptions options; options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Info;

There are seven levels of verbosity to choose from. The default value is Off and no logs will be generated. Trace will generate the most level of detail, and Fatal will generate the least messages reporting only fatal error conditions.

Once logging is enabled in your application, the SDK will generate log files in your executable directory following the default naming pattern of aws_sdk_<date>.log. The log file generated by the prefix-naming option rolls over once per hour to allow for archiving or deleting log files.

The later versions of the SDK increasingly depend on the underlying AWS Common Runtime (CRT) libraries. These libraries provide common functionality and basic operations among SDKs. All log messages from the CRT libraries will be redirected to the SDK for C++ by default. The log level and logging system you specify for the SDK for C++ also applies to the CRT.

In the previous example, the CRT will inherit LogLevel::Info and also log messages at the Info level to the same file.

You can independently control the logging for the CRT libraries, either by redirecting its output to a separate log file, or by setting a different log level for messages from the CRT. Often it can be beneficial to reduce the verbosity of the CRT libraries so that they don’t overwhelm the logs. For example, the log level for only the CRT output can be set to Warn as follows:

options.loggingOptions.crt_logger_create_fn = [](){ return Aws::MakeShared<Aws::Utils::Logging::DefaultCRTLogSystem>("CRTLogSystem", Aws::Utils::Logging::LogLevel::Warn); };

By optionally using the method InitializeAWSLogging, you can control the verbosity level and the log output of the DefaultLogSystem. You can configure the log filename prefix, or redirect the output to a stream instead of a file.

Aws::Utils::Logging::InitializeAWSLogging( Aws::MakeShared<Aws::Utils::Logging::DefaultLogSystem>( "RunUnitTests", Aws::Utils::Logging::LogLevel::Trace, "aws_sdk_"));

Alternatively, instead of using the DefaultLogSystem, you can also use this method to provide your own logging implementation.

InitializeAWSLogging(Aws::MakeShared<CustomLoggingSystem>());

If you call method InitializeAWSLogging, free resources at the end of your program by calling ShutdownAWSLogging.

Aws::Utils::Logging::ShutdownAWSLogging();

Example integration test with logging

#include <aws/external/gtest.h> #include <aws/core/utils/memory/stl/AWSString.h> #include <aws/core/utils/logging/DefaultLogSystem.h> #include <aws/core/utils/logging/AWSLogging.h> #include <iostream> int main(int argc, char** argv) { Aws::Utils::Logging::InitializeAWSLogging( Aws::MakeShared<Aws::Utils::Logging::DefaultLogSystem>( "RunUnitTests", Aws::Utils::Logging::LogLevel::Trace, "aws_sdk_")); ::testing::InitGoogleTest(&argc, argv); int exitCode = RUN_ALL_TESTS(); Aws::Utils::Logging::ShutdownAWSLogging(); return exitCode; }

Example subclass of Aws::Utils::Logging::DefaultLogSystem for custom logging

The following code demonstrates how to subclass the Aws::Utils::Logging::DefaultLogSystem class, which is part of the AWS SDK for C++. This example overrides the ProcessFormattedStatement virtual function to customize logging.

Aws::Utils::Logging::DefaultLogSystem is one of several classes in the AWS SDK for C++ that subclass Aws::Utils::Logging::LogSystemInterface for custom logging.

class LogSystemOverride : public Aws::Utils::Logging::DefaultLogSystem { public: explicit LogSystemOverride(Aws::Utils::Logging::LogLevel logLevel, const Aws::String &logPrefix) : DefaultLogSystem(logLevel, logPrefix), mLogToStreamBuf(false) {} const Aws::Utils::Stream::SimpleStreamBuf &GetStreamBuf() const { return mStreamBuf; } void setLogToStreamBuf(bool logToStreamBuf) { mLogToStreamBuf = logToStreamBuf; } protected: void ProcessFormattedStatement(Aws::String &&statement) override { if (mLogToStreamBuf) { std::lock_guard<std::mutex> lock(mStreamMutex); mStreamBuf.sputn(statement.c_str(), statement.length()); } DefaultLogSystem::ProcessFormattedStatement(std::move(statement)); } private: Aws::Utils::Stream::SimpleStreamBuf mStreamBuf; // Use a mutex when writing to the buffer because // ProcessFormattedStatement can be called from multiple threads. std::mutex mStreamMutex; std::atomic<bool> mLogToStreamBuf; };
int main(int argc, char **argv) { Aws::SDKOptions options; options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace; auto logSystemOverride = Aws::MakeShared<LogSystemOverride>("AllocationTag", options.loggingOptions.logLevel, options.loggingOptions.defaultLogPrefix); options.loggingOptions.logger_create_fn = [logSystemOverride]() { return logSystemOverride; }; Aws::InitAPI(options); // Call Aws::InitAPI only once in an application. { Aws::Client::ClientConfiguration clientConfig; // Optional: Set to the AWS Region (overrides config file). // clientConfig.region = "us-east-1"; Aws::S3::S3Client s3Client(clientConfig); logSystemOverride->setLogToStreamBuf(true); auto outcome = s3Client.ListBuckets(); if (!outcome.IsSuccess()) { std::cerr << "ListBuckets error: " << outcome.GetError().GetExceptionName() << " " << outcome.GetError().GetMessage() << std::endl; } logSystemOverride->setLogToStreamBuf(false); std::cout << "Log for ListBuckets" << std::endl; std::cout << logSystemOverride->GetStreamBuf().str() << std::endl; } Aws::ShutdownAPI(options); return 0; }

See the complete example on GitHub.