spdlog单例模式封装

#pragma once
#include "Util.h"

#ifdef _WIN32
#define __FILENAME__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1):__FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1):__FILE__)
#endif

//定义一个在日志后添加 文件名 函数名 行号 的宏定义
#ifndef suffix
#define suffix(msg)  std::string(msg).append("  <")\
        .append(__FILENAME__).append("> <").append(__func__)\
        .append("> <").append(std::to_string(__LINE__))\
        .append(">").c_str()
//#define suffix(msg)  std::string().append(" File:")\
//        .append(__FILENAME__).append("\", Func:\"").append(__func__)\
//        .append("()\", Line:\"").append(std::to_string(__LINE__)).append("\"").append(msg).c_str()
#endif

//在  spdlog.h   之前定义,才有效
#ifndef SPDLOG_TRACE_ON
#define SPDLOG_TRACE_ON
#endif

#ifndef SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG_ON
#endif

#include <spdlog\spdlog.h>
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include <spdlog\sinks\daily_file_sink.h>

class Logger
{

public:
	static Logger& GetInstance() {
		static Logger m_instance;
		return m_instance;
	}

	auto GetLogger() { return nml_logger; }

private:
	Logger() {
		util::MakeSureDirExist("logs");

		//设置为异步日志
		//spdlog::set_async_mode(32768);  // 必须为 2 的幂
		std::vector<spdlog::sink_ptr> sinkList;
//#ifdef _CONSOLE
#ifdef _DEBUG
		auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
		consoleSink->set_level(spdlog::level::debug);
		//consoleSink->set_pattern("[multi_sink_example] [%^%l%$] %v");
		consoleSink->set_pattern("[%m-%d %H:%M:%S.%e][%^%L%$]  %v");
		sinkList.push_back(consoleSink);
#endif
		auto basicSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/basicSink.txt");
		basicSink->set_level(spdlog::level::debug);
		basicSink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%5l%$]  %v");
		sinkList.push_back(basicSink);
		nml_logger = std::make_shared<spdlog::logger>("both", begin(sinkList), end(sinkList));
		//register it if you need to access it globally
		spdlog::register_logger(nml_logger);

		// 设置日志记录级别
#ifdef _DEBUG
		nml_logger->set_level(spdlog::level::trace);
#else
		nml_logger->set_level(spdlog::level::err);
#endif
		//设置 logger 格式[%^%L%$]
		//nml_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%5l]  %v");
		//nml_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%5l%$]  %v");
		//设置当出发 err 或更严重的错误时立刻刷新日志到  disk 
		nml_logger->flush_on(spdlog::level::err);

		spdlog::flush_every(std::chrono::seconds(3));
	}

	~Logger() {
		spdlog::drop_all();
	}

	Logger(const Logger&) = delete;
	Logger& operator=(const Logger&) = delete;

private:
	std::shared_ptr<spdlog::logger> nml_logger;
};

//Logger& operator<<(Logger& log, const char* s);
//Logger& operator<<(Logger& log, const std::string& s);

//#define DEBUG Logger::GetInstance() 
#define LTrace(msg,...) Logger::GetInstance().GetLogger()->trace(suffix(msg),__VA_ARGS__)
//#define LDebug(msg,...) Logger::GetInstance().GetLogger()->debug(suffix(msg),__VA_ARGS__)
#define LDebug(...) Logger::GetInstance().GetLogger()->debug(__VA_ARGS__)
#define LInfo(...) Logger::GetInstance().GetLogger()->info(__VA_ARGS__)
#define LWarn(...) Logger::GetInstance().GetLogger()->warn(__VA_ARGS__)
#define LError(...) Logger::GetInstance().GetLogger()->error(__VA_ARGS__)
#define LCritical(...) Logger::GetInstance().GetLogger()->critical(__VA_ARGS__)

#define criticalif(b, ...)                        \
    do {                                       \
        if ((b)) {                             \
           Logger::GetInstance().GetLogger()->critical(__VA_ARGS__); \
        }                                      \
    } while (0)

#ifdef WIN32  
#define errcode WSAGetLastError()
#endif
bool util::MakeSureDirExist(const char *dir, size_t len)
{
	assert(dir != NULL);
	if (len < 1 || len > 1024)
		return false;
	char *head, *p;
	char tmpDir[1024] = { 0 };
	//strcpy_s(tmpDir, 1024, dir);	//拷贝1024字节发现,len之后的字符全部变为-2
	strcpy_s(tmpDir, len + 1, dir);
	head = tmpDir;
	if (*head == '\\' || *head == '/')
		++head;
	p = head;
	if (*(tmpDir + len - 1) != '\\' && *(tmpDir + len - 1) != '/')
		*(tmpDir + len) = '\\';

	while (*p)
	{
		if (*p == '\\' || *p == '/')
		{
			*p = '\0';
			if (_access(head, 0))// 头文件io.h
			{
				if (_mkdir(head))
				{
#ifdef _DEBUG
					fprintf(stderr, "Failed to create directory %s\n", head);
					return false;
#endif
				}
			}
			*p = '\\';
		}
		++p;
	}
	return true;
}

main.cpp

#include "log.h"

int main()
{
    //example:
    LDebug("hello world");
    LDebug("EventBase addr: {}, m_tasks size: {}", (int32_t)this, m_tasks.size());
    LDebug("~Channel(), fd:{}", m_fd);

    system("pause");
    return 0;
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
单例模式是一种常用的设计模式,它可以保证一个类只有一个实例,并提供一个全局访问点。在封装mysql数据库连接类dbconn时,可以使用单例模式来确保只有一个数据库连接实例存在,避免多次连接数据库造成资源浪费和性能下降的问题。 具体实现可以在dbconn类中定义一个静态成员变量instance,用于保存唯一的数据库连接实例。在构造函数中,可以通过调用mysql_real_connect函数来建立数据库连接,并将连接句柄保存在成员变量中。在析构函数中,可以调用mysql_close函数来关闭数据库连接。 为了保证线程安全,可以使用双重检查锁定机制来实现单例模式。即在getInstance函数中,先检查instance是否为空,如果为空,则加锁创建一个新的实例,否则直接返回已有的实例。 下面是一个简单的示例代码: ``` class dbconn { private: static dbconn* instance; MYSQL* conn; dbconn() { conn = mysql_real_connect(...); // 建立数据库连接 } ~dbconn() { mysql_close(conn); // 关闭数据库连接 } public: static dbconn* getInstance() { if (instance == nullptr) { std::lock_guard<std::mutex> lock(mutex); if (instance == nullptr) { instance = new dbconn(); } } return instance; } }; dbconn* dbconn::instance = nullptr; ``` 使用时可以通过dbconn::getInstance()来获取数据库连接实例,然后调用相应的mysql函数来执行数据库操作。例如: ``` dbconn* conn = dbconn::getInstance(); mysql_query(conn->conn, "SELECT * FROM table"); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值