diff --git a/pulsar-client-cpp/examples/CMakeLists.txt b/pulsar-client-cpp/examples/CMakeLists.txt index ec4f8dec21e990..bd124649cac56d 100644 --- a/pulsar-client-cpp/examples/CMakeLists.txt +++ b/pulsar-client-cpp/examples/CMakeLists.txt @@ -37,6 +37,10 @@ set(SAMPLE_PRODUCER_SOURCES SampleProducer.cc ) +set(SAMPLE_FILE_LOGGER_SOURCES + SampleFileLogger.cc +) + set(SAMPLE_PRODUCER_C_SOURCES SampleProducerCApi.c ) @@ -57,6 +61,7 @@ add_executable(SampleAsyncProducer ${SAMPLE_ASYNC_PRODUCER_SOURCES}) add_executable(SampleConsumer ${SAMPLE_CONSUMER_SOURCES}) add_executable(SampleConsumerListener ${SAMPLE_CONSUMER_LISTENER_SOURCES}) add_executable(SampleProducer ${SAMPLE_PRODUCER_SOURCES}) +add_executable(SampleFileLogger ${SAMPLE_FILE_LOGGER_SOURCES}) add_executable(SampleProducerCApi ${SAMPLE_PRODUCER_C_SOURCES}) add_executable(SampleConsumerCApi ${SAMPLE_CONSUMER_C_SOURCES}) add_executable(SampleConsumerListenerCApi ${SAMPLE_CONSUMER_LISTENER_C_SOURCES}) @@ -66,6 +71,7 @@ target_link_libraries(SampleAsyncProducer ${CLIENT_LIBS} pulsarShared) target_link_libraries(SampleConsumer ${CLIENT_LIBS} pulsarShared) target_link_libraries(SampleConsumerListener ${CLIENT_LIBS} pulsarShared) target_link_libraries(SampleProducer ${CLIENT_LIBS} pulsarShared) +target_link_libraries(SampleFileLogger ${CLIENT_LIBS} pulsarShared) target_link_libraries(SampleProducerCApi ${CLIENT_LIBS} pulsarShared) target_link_libraries(SampleConsumerCApi ${CLIENT_LIBS} pulsarShared) target_link_libraries(SampleConsumerListenerCApi ${CLIENT_LIBS} pulsarShared) diff --git a/pulsar-client-cpp/examples/SampleAsyncProducer.cc b/pulsar-client-cpp/examples/SampleAsyncProducer.cc index ccc2c0fa7dc0d0..9701ccbe6422d8 100644 --- a/pulsar-client-cpp/examples/SampleAsyncProducer.cc +++ b/pulsar-client-cpp/examples/SampleAsyncProducer.cc @@ -35,7 +35,7 @@ int main() { Client client("pulsar://localhost:6650"); Producer producer; - Result result = client.createProducer("persistent://prop/r1/ns1/my-topic", producer); + Result result = client.createProducer("persistent://public/default/my-topic", producer); if (result != ResultOk) { LOG_ERROR("Error creating producer: " << result); return -1; diff --git a/pulsar-client-cpp/examples/SampleConsumer.cc b/pulsar-client-cpp/examples/SampleConsumer.cc index e61b793987fd6e..1dcc550f811546 100644 --- a/pulsar-client-cpp/examples/SampleConsumer.cc +++ b/pulsar-client-cpp/examples/SampleConsumer.cc @@ -30,7 +30,7 @@ int main() { Client client("pulsar://localhost:6650"); Consumer consumer; - Result result = client.subscribe("persistent://prop/r1/ns1/my-topic", "consumer-1", consumer); + Result result = client.subscribe("persistent://public/default/my-topic", "consumer-1", consumer); if (result != ResultOk) { LOG_ERROR("Failed to subscribe: " << result); return -1; diff --git a/pulsar-client-cpp/examples/SampleConsumerListener.cc b/pulsar-client-cpp/examples/SampleConsumerListener.cc index 5d60ccd12c26f7..9ce2291636ab1c 100644 --- a/pulsar-client-cpp/examples/SampleConsumerListener.cc +++ b/pulsar-client-cpp/examples/SampleConsumerListener.cc @@ -38,7 +38,7 @@ int main() { Consumer consumer; ConsumerConfiguration config; config.setMessageListener(listener); - Result result = client.subscribe("persistent://prop/r1/ns1/my-topic", "consumer-1", config, consumer); + Result result = client.subscribe("persistent://public/default/my-topic", "consumer-1", config, consumer); if (result != ResultOk) { LOG_ERROR("Failed to subscribe: " << result); return -1; diff --git a/pulsar-client-cpp/examples/SampleFileLogger.cc b/pulsar-client-cpp/examples/SampleFileLogger.cc new file mode 100644 index 00000000000000..fcc3d417b76caa --- /dev/null +++ b/pulsar-client-cpp/examples/SampleFileLogger.cc @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include + +using namespace pulsar; + +int main(int argc, char* argv[]) { + ClientConfiguration clientConf; + // The logs whose level is >= INFO will be written to pulsar-cpp-client.log + clientConf.setLogger(new FileLoggerFactory(Logger::Level::LEVEL_INFO, "pulsar-cpp-client.log")); + + Client client("pulsar://localhost:6650", clientConf); + Producer producer; + client.createProducer("my-topic", producer); // just to create some logs + client.close(); + return 0; +} diff --git a/pulsar-client-cpp/examples/SampleProducer.cc b/pulsar-client-cpp/examples/SampleProducer.cc index bc1ece26ea43dc..ff5048792d1145 100644 --- a/pulsar-client-cpp/examples/SampleProducer.cc +++ b/pulsar-client-cpp/examples/SampleProducer.cc @@ -30,7 +30,7 @@ int main() { Client client("pulsar://localhost:6650"); Producer producer; - Result result = client.createProducer("persistent://prop/r1/ns1/my-topic", producer); + Result result = client.createProducer("persistent://public/default/my-topic", producer); if (result != ResultOk) { LOG_ERROR("Error creating producer: " << result); return -1; diff --git a/pulsar-client-cpp/include/pulsar/Client.h b/pulsar-client-cpp/include/pulsar/Client.h index 881d4849253349..1bc26145380549 100644 --- a/pulsar-client-cpp/include/pulsar/Client.h +++ b/pulsar-client-cpp/include/pulsar/Client.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include namespace pulsar { diff --git a/pulsar-client-cpp/include/pulsar/SimpleLoggerFactory.h b/pulsar-client-cpp/include/pulsar/ConsoleLoggerFactory.h similarity index 80% rename from pulsar-client-cpp/include/pulsar/SimpleLoggerFactory.h rename to pulsar-client-cpp/include/pulsar/ConsoleLoggerFactory.h index 1ab11dd2497556..7f3f407d9cd006 100644 --- a/pulsar-client-cpp/include/pulsar/SimpleLoggerFactory.h +++ b/pulsar-client-cpp/include/pulsar/ConsoleLoggerFactory.h @@ -23,6 +23,8 @@ namespace pulsar { +class ConsoleLoggerFactoryImpl; + /** * The default LoggerFactory of Client if `USE_LOG4CXX` macro was not defined during compilation. * @@ -37,22 +39,23 @@ namespace pulsar { * level simply. * * ```c++ - * #include + * #include * * ClientConfiguration conf; - * conf.setLogger(new SimpleLoggerFactory(Logger::LEVEL_DEBUG)); + * conf.setLogger(new ConsoleLoggerFactory(Logger::LEVEL_DEBUG)); * Client client("pulsar://localhost:6650", conf); * ``` */ -class SimpleLoggerFactory : public LoggerFactory { +class PULSAR_PUBLIC ConsoleLoggerFactory : public LoggerFactory { public: - explicit SimpleLoggerFactory() = default; - explicit SimpleLoggerFactory(Logger::Level level) : level_(level) {} + explicit ConsoleLoggerFactory(Logger::Level level = Logger::LEVEL_INFO); + + ~ConsoleLoggerFactory(); Logger* getLogger(const std::string& fileName) override; private: - Logger::Level level_{Logger::LEVEL_INFO}; + std::unique_ptr impl_; }; } // namespace pulsar diff --git a/pulsar-client-cpp/include/pulsar/FileLoggerFactory.h b/pulsar-client-cpp/include/pulsar/FileLoggerFactory.h new file mode 100644 index 00000000000000..aa6282e0075923 --- /dev/null +++ b/pulsar-client-cpp/include/pulsar/FileLoggerFactory.h @@ -0,0 +1,65 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +#include + +namespace pulsar { + +class FileLoggerFactoryImpl; + +/** + * A logger factory that is appending logs to a single file. + * + * The log format is "yyyy-mm-dd hh:MM:ss.xxx : | ", like + * + * ``` + * 2021-03-24 17:35:46.571 INFO [0x10a951e00] ConnectionPool:85 | Created connection for ... + * ``` + * + * Example: + * + * ```c++ + * #include + * + * ClientConfiguration conf; + * conf.setLogger(new FileLoggerFactory(Logger::LEVEL_DEBUG, "pulsar-client-cpp.log")); + * Client client("pulsar://localhost:6650", conf); + * ``` + */ +class PULSAR_PUBLIC FileLoggerFactory : public pulsar::LoggerFactory { + public: + /** + * Create a FileLoggerFactory instance. + * + * @param level the log level + * @param logFilePath the log file's path + */ + FileLoggerFactory(Logger::Level level, const std::string& logFilePath); + + ~FileLoggerFactory(); + + pulsar::Logger* getLogger(const std::string& filename) override; + + private: + std::unique_ptr impl_; +}; + +} // namespace pulsar diff --git a/pulsar-client-cpp/lib/ClientImpl.cc b/pulsar-client-cpp/lib/ClientImpl.cc index 5edda08e50ff35..d9a2b570d8c48b 100644 --- a/pulsar-client-cpp/lib/ClientImpl.cc +++ b/pulsar-client-cpp/lib/ClientImpl.cc @@ -26,7 +26,7 @@ #include "PartitionedConsumerImpl.h" #include "MultiTopicsConsumerImpl.h" #include "PatternMultiTopicsConsumerImpl.h" -#include +#include #include #include #include @@ -101,11 +101,11 @@ ClientImpl::ClientImpl(const std::string& serviceUrl, const ClientConfiguration& loggerFactory = Log4CxxLoggerFactory::create(clientConfiguration_.getLogConfFilePath()); } else { // Use default simple console logger - loggerFactory.reset(new SimpleLoggerFactory); + loggerFactory.reset(new ConsoleLoggerFactory); } #else // Use default simple console logger - loggerFactory.reset(new SimpleLoggerFactory); + loggerFactory.reset(new ConsoleLoggerFactory); #endif } LogUtils::setLoggerFactory(std::move(loggerFactory)); diff --git a/pulsar-client-cpp/lib/ConsoleLoggerFactory.cc b/pulsar-client-cpp/lib/ConsoleLoggerFactory.cc new file mode 100644 index 00000000000000..397c7feed070f7 --- /dev/null +++ b/pulsar-client-cpp/lib/ConsoleLoggerFactory.cc @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "lib/ConsoleLoggerFactoryImpl.h" + +namespace pulsar { + +ConsoleLoggerFactory::ConsoleLoggerFactory(Logger::Level level) + : impl_(new ConsoleLoggerFactoryImpl(level)) {} + +ConsoleLoggerFactory::~ConsoleLoggerFactory() {} + +Logger* ConsoleLoggerFactory::getLogger(const std::string& fileName) { return impl_->getLogger(fileName); } + +} // namespace pulsar diff --git a/pulsar-client-cpp/lib/ConsoleLoggerFactoryImpl.h b/pulsar-client-cpp/lib/ConsoleLoggerFactoryImpl.h new file mode 100644 index 00000000000000..61c1d90d745e5c --- /dev/null +++ b/pulsar-client-cpp/lib/ConsoleLoggerFactoryImpl.h @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +#include +#include "lib/SimpleLogger.h" + +namespace pulsar { + +class ConsoleLoggerFactoryImpl { + public: + ConsoleLoggerFactoryImpl(Logger::Level level) : level_(level) {} + + Logger* getLogger(const std::string& fileName) { return new SimpleLogger(std::cout, fileName, level_); } + + private: + Logger::Level level_; +}; + +} // namespace pulsar diff --git a/pulsar-client-cpp/lib/FileLoggerFactory.cc b/pulsar-client-cpp/lib/FileLoggerFactory.cc new file mode 100644 index 00000000000000..a82613f00a0787 --- /dev/null +++ b/pulsar-client-cpp/lib/FileLoggerFactory.cc @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include +#include "lib/FileLoggerFactoryImpl.h" + +namespace pulsar { + +FileLoggerFactory::FileLoggerFactory(Logger::Level level, const std::string& logFilePath) + : impl_(new FileLoggerFactoryImpl(level, logFilePath)) {} + +FileLoggerFactory::~FileLoggerFactory() {} + +Logger* FileLoggerFactory::getLogger(const std::string& filename) { return impl_->getLogger(filename); } + +} // namespace pulsar diff --git a/pulsar-client-cpp/lib/FileLoggerFactoryImpl.h b/pulsar-client-cpp/lib/FileLoggerFactoryImpl.h new file mode 100644 index 00000000000000..75329c65fc88ec --- /dev/null +++ b/pulsar-client-cpp/lib/FileLoggerFactoryImpl.h @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#pragma once + +#include +#include +#include +#include + +#include "lib/SimpleLogger.h" + +namespace pulsar { + +class FileLoggerFactoryImpl { + public: + FileLoggerFactoryImpl(Logger::Level level, const std::string& logFilePath) + : level_(level), os_(logFilePath, std::ios_base::out | std::ios_base::app) {} + + ~FileLoggerFactoryImpl() { os_.close(); } + + Logger* getLogger(const std::string& filename) { return new SimpleLogger(os_, filename, level_); } + + private: + const Logger::Level level_; + std::ofstream os_; +}; + +} // namespace pulsar diff --git a/pulsar-client-cpp/lib/LogUtils.cc b/pulsar-client-cpp/lib/LogUtils.cc index 60e7d5169eb0cf..7967fbe75459a4 100644 --- a/pulsar-client-cpp/lib/LogUtils.cc +++ b/pulsar-client-cpp/lib/LogUtils.cc @@ -20,7 +20,7 @@ #include #include -#include +#include #include "Log4CxxLogger.h" @@ -50,7 +50,7 @@ void LogUtils::setLoggerFactory(std::unique_ptr loggerFactory) { LoggerFactory* LogUtils::getLoggerFactory() { if (s_loggerFactory.load() == nullptr) { - std::unique_ptr newFactory(new SimpleLoggerFactory()); + std::unique_ptr newFactory(new ConsoleLoggerFactory()); setLoggerFactory(std::move(newFactory)); } return s_loggerFactory.load(); diff --git a/pulsar-client-cpp/lib/SimpleLoggerFactory.cc b/pulsar-client-cpp/lib/SimpleLogger.h similarity index 89% rename from pulsar-client-cpp/lib/SimpleLoggerFactory.cc rename to pulsar-client-cpp/lib/SimpleLogger.h index 5fb5b678109251..b750336a37f68f 100644 --- a/pulsar-client-cpp/lib/SimpleLoggerFactory.cc +++ b/pulsar-client-cpp/lib/SimpleLogger.h @@ -17,7 +17,7 @@ * under the License. */ -#include +#pragma once #include #include @@ -48,7 +48,8 @@ inline std::ostream &operator<<(std::ostream &s, Logger::Level level) { class SimpleLogger : public Logger { public: - SimpleLogger(const std::string &filename, Level level) : filename_(filename), level_(level) {} + SimpleLogger(std::ostream &os, const std::string &filename, Level level) + : os_(os), filename_(filename), level_(level) {} bool isEnabled(Level level) { return level >= level_; } @@ -59,11 +60,12 @@ class SimpleLogger : public Logger { ss << " " << level << " [" << std::this_thread::get_id() << "] " << filename_ << ":" << line << " | " << message << "\n"; - std::cout << ss.str(); - std::cout.flush(); + os_ << ss.str(); + os_.flush(); } private: + std::ostream &os_; const std::string filename_; const Level level_; @@ -81,6 +83,4 @@ class SimpleLogger : public Logger { } }; -Logger *SimpleLoggerFactory::getLogger(const std::string &file) { return new SimpleLogger(file, level_); } - } // namespace pulsar diff --git a/pulsar-client-cpp/tests/CustomLoggerTest.cc b/pulsar-client-cpp/tests/CustomLoggerTest.cc index 8b4cd792faa051..f2a97d1978675a 100644 --- a/pulsar-client-cpp/tests/CustomLoggerTest.cc +++ b/pulsar-client-cpp/tests/CustomLoggerTest.cc @@ -17,7 +17,7 @@ * under the License. */ #include -#include +#include #include #include #include @@ -68,29 +68,29 @@ TEST(CustomLoggerTest, testCustomLogger) { ASSERT_EQ(logLines.size(), 2); } -TEST(CustomLoggerTest, testSimpleLoggerFactory) { - std::unique_ptr factory(new SimpleLoggerFactory); +TEST(CustomLoggerTest, testConsoleLoggerFactory) { + std::unique_ptr factory(new ConsoleLoggerFactory); std::unique_ptr logger(factory->getLogger(__FILE__)); ASSERT_FALSE(logger->isEnabled(Logger::LEVEL_DEBUG)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_INFO)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_WARN)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_ERROR)); - factory.reset(new SimpleLoggerFactory(Logger::LEVEL_DEBUG)); + factory.reset(new ConsoleLoggerFactory(Logger::LEVEL_DEBUG)); logger.reset(factory->getLogger(__FILE__)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_DEBUG)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_INFO)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_WARN)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_ERROR)); - factory.reset(new SimpleLoggerFactory(Logger::LEVEL_WARN)); + factory.reset(new ConsoleLoggerFactory(Logger::LEVEL_WARN)); logger.reset(factory->getLogger(__FILE__)); ASSERT_FALSE(logger->isEnabled(Logger::LEVEL_DEBUG)); ASSERT_FALSE(logger->isEnabled(Logger::LEVEL_INFO)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_WARN)); ASSERT_TRUE(logger->isEnabled(Logger::LEVEL_ERROR)); - factory.reset(new SimpleLoggerFactory(Logger::LEVEL_ERROR)); + factory.reset(new ConsoleLoggerFactory(Logger::LEVEL_ERROR)); logger.reset(factory->getLogger(__FILE__)); ASSERT_FALSE(logger->isEnabled(Logger::LEVEL_DEBUG)); ASSERT_FALSE(logger->isEnabled(Logger::LEVEL_INFO));