腾讯tlog黑盒实现(伪代码)

本文介绍了一个基于UDP的日志系统的设计与实现过程,包括客户端接口、日志类别管理及不同设备类型的日志记录方式。此外,还提供了一种XML配置文件解析工具,用于生成数据库操作所需的SQL语句及相关代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<p><strong><span style="font-family:Microsoft YaHei;">客户端接口部分,这个编译成库文件</span></strong></p>
// tlog_interface.h
namespace tlog
{
	class tlog_category_interface;
	class tlog_ctx_interface;
};

typedef tlog::tlog_ctx_interface* LPTLOGCTX;
typedef tlog::tlog_category_interface* LPLOGCATEGORYINST;

LPTLOGCTX tlog_init_from_file(const char*);
LPLOGCATEGORYINST tlog_get_category(LPTLOGCTX, const char*);

void tlog_info(LPLOGCATEGORYINST, size_t, size_t, const char*);

int tlog_fini_ctx(LPTLOGCTX*);

// tlog_base.h
namespace tlog{
class tlog_category_interface
{
	public:
		~tlog_category_interface(){}
		virtual void exec(const char*) = 0;
		virtual int release() = 0;
};

class tlog_ctx_interface
{
	public:
		~tlog_ctx_interface(){}
		virtual tlog_category_interface* get_category(const char*) = 0;
		virtual int release();
};

enum EN_DRVICE_TYPE
{
	en_device_file,
	en_device_net,
};

struct stDevice
{
	EN_DRVICE_TYPE _enType;
	stDevice(EN_DRVICE_TYPE enType)
		:_enType(enType)
	{}
	virtual EN_DRVICE_TYPE get_type() { return _enType; }
	
	virtual bool init(pugi::xml_node node) = 0;
	virtual int release() = 0;
	virtual void exec(const char* pszData) = 0;
};

struct stDeviceFile : public stDevice
{
	std::string _pattern; // 路径
	uint32_t _bufferSize; // 大小
	std::string _data;    // 内容
	std::ofstream _out;   // 句柄
	
	stDeviceFile()
		: stDevice(en_device_file)
	{}
	
	virtual bool init(pugi::xml_node node)
	{
		// 初始化数据成员
		// 打开要写的文件
	}
	virtual int release()
	{
		// 如果 _data 里面还有内容,写入到文件
		// 关闭文件
	}
	virtual void exec(const char* pStr)
	{
		_data.append(pStr);
		_data.append("\n");
		if (_data.size() >= _bufferSize)
		{
			_out << _data;
			_data.clear();
		}
	}
};
struct stDeviceNet : public stDevice
{
	char _protocol[32];
	char _ip[64];
	char _port[8];
	int _sock_c;
	
	stDeviceNet()
		: stDevice(en_device_net)
	{}
	
	virtual bool init(pugi::xml_node node)
	{
		// 初始化数据成员
		// 链接到UDPServer
	}
	virtual int release()
	{

	}
	virtual void exec(const char* pStr)
	{
		sockaddr_in ser;
		bzero(&ser, sizeof(ser));
		ser.sin_family = AF_INET;
		ser.sin_port = htons(atoi(_port));
		ser.sin_addr.s_addr = inet_addr(_ip);
		int nlen = sizeof(ser);
		
		sendto(_sock_c, pStr, strlen(pStr) + 1, 0, (sockaddr*)&ser, nlen);
	}
};

class tlog_category : public tlog_category_interface
{
private:
	std::string _name;
	std::vector<stDevice*> _vecDevice;
public:
	bool init(pugi::xml_node node)
	{
		// 解析配置,初始化数据成员
	}
	
	virtual int release()
	{
		// vec data release;
		// destroy vec;
	}
	
	virtual void exec(const char* pstr)
	{
		// for (auto& itr : _vec)
		// if (itr) itr->exec(pstr);
	}
};

class tlog_ctx : public tlog_ctx_interface
{
private:
	std::unordered_map<std::string, tlog_category*> _mapCate;
public:
	bool init(const char* pszPath)
	{
		// 初始化 _mapCate
	}
	
	virtual int release()
	{
		// _mapCate data release
		// destroy _mapCate
	}
	
	virtual tlog_category_interface* get_category(const char* name)
	{
		return _mapCate[name];
	}
};

};

// tlog_base.cpp

LPTLOGCTX tlog_init_from_file(const char* pszPath)
{
	tlog_ctx* pCtx = new tlog_ctx;
	pCtx->init(pszPath);
	return pCtx;
}

LPLOGCATEGORYINST tlog_get_category(LPTLOGCTX pstCtx, const char* pszName)
{
	if (pstCtx)
	{
		return pstCtx->get_category(pszName);
	}
	return NULL;
}

void tlog_info(LPLOGCATEGORYINST pCat, size_t id, size_t, cls, const char* pszFmt, ...)
{
	if (!pCat) return;
	va_list vArg;
	va_start(vArg, pszFmt);
	char buffer[MAX_SIZE] = {0};
	// char* pbuffer = buffer;
	// int len = _vsnprintf(pszFmt, vArg);
	// if (len < 0)
	// {
	// 	va_end(vArg);
	// 	return;
	// }
	// if (len >= MAX_SIZE)
	// 	pbuffer = (char*)malloc(len + 1);
	vsnprintf(buffer, MAX_SIZE, pszFmt, vArg);
	
	pCat->exec(buffer);
	
	va_end(vArg);
}

int tlog_fini_ctx(LPTLOGCTX* ppstCtx)
{
	if (ppstCtx && *ppstCtx)
	{
		(*ppstCtx)->release();
		*ppstCtx = NULL;
		return 0;
	}
	return -1;
}


解析xml工具代码:

// tlog_sql.h

struct stEntry
{
	std::string _name;
	std::string _oldname;
	std::string _type;
	uint32_t _size;
	std::string _desc;
	bool _index;
};

struct stStruct
{
	std::string _name;
	std::string _oldname;
	std::string _desc;
	std::unordered_map<std::string, stEntry> _mapEntry;
};

/*
解析xml到三个文件:.sql .h .cpp
.sql
	procedure 
		-- alter table name 
		IF EXIST (select * from information_schema.TABLES) WHERE table_name='...') THEN ALTER TABLE ... RENAME TO ... END IF;
		-- new table
		IF NOT EXIST (select * from information_schema.TABLES) WHERE table_name='...') THEN CREATE TABLE .... END IF;
		-- alter column name
		IF EXIST (select * from information_schema.COLUMNS) WHERE table_name='...' and column_name='...') THEN ALTER TABLE ... END IF;
		-- add column
		IF NOT EXIST (select * from information_schema.COLUMNS) WHERE table_name='...' and column_name='...') THEN ALTER TABLE ... END IF;
所有字段都这么组织一下sql语句,没有oldname的话就没有相关sql语句

.h interface
	class data_basic
	{
	public:
		virtual bool ss_split(const char* str) = 0;
		virtual const char* get_sql() = 0;
	};
	
	template<class data_basic>
	data_basic* getTlogData()
	{
		static data_base Inst;
		return &Inst;
	}
每一个struct都继承data_basic, name作为类名,entry内容作为数据成员
ss_split: 解析传入的 name|...|...|... 格式字符串到数据成员,组织DB INSERT语句
get_sql: 返回DB INSERT语句

.cpp 
	data_base* getTLogData(const char* name)
	{
		if (strcmp(name, "...") == 0)
			return getTLogData<...>();
		// .... else if () ....
		return NULL;
	}
... 是struct的名字,
*/

服务端代码没有给出,大概就是收到udp消息,用xml解析工具生成的 .h .cpp函数,插入到数据库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值