SpartacusIn21

专注:c++,python,d3d,设计模式,人工智能,并行计算

paho.mqtt.c打印日志

mqtt中自身就带有日志系统Log.h和Log.c,这些日志文件是在客户端调用MQTTClient_create函数是初始化的,MQTTClient_create源码如下:

int MQTTClient_create(MQTTClient* handle, const char* serverURI, const char* clientId,
		int persistence_type, void* persistence_context)
{
	int rc = 0;
	MQTTClients *m = NULL;

	FUNC_ENTRY;
	rc = Thread_lock_mutex(mqttclient_mutex);

	if (serverURI == NULL || clientId == NULL)
	{
		rc = MQTTCLIENT_NULL_PARAMETER;
		goto exit;
	}

	if (!UTF8_validateString(clientId))
	{
		rc = MQTTCLIENT_BAD_UTF8_STRING;
		goto exit;
	}

	if (!initialized)
	{
		#if defined(HEAP_H)
			Heap_initialize();
		#endif
		Log_initialize((Log_nameValue*)MQTTClient_getVersionInfo());
		bstate->clients = ListInitialize();
		Socket_outInitialize();
		Socket_setWriteCompleteCallback(MQTTClient_writeComplete);
		handles = ListInitialize();
#if defined(OPENSSL)
		SSLSocket_initialize();
#endif
		initialized = 1;
	}
	m = malloc(sizeof(MQTTClients));
	*handle = m;
	memset(m, '\0', sizeof(MQTTClients));
	if (strncmp(URI_TCP, serverURI, strlen(URI_TCP)) == 0)
		serverURI += strlen(URI_TCP);
#if defined(OPENSSL)
	else if (strncmp(URI_SSL, serverURI, strlen(URI_SSL)) == 0)
	{
		serverURI += strlen(URI_SSL);
		m->ssl = 1;
	}
#endif
	m->serverURI = MQTTStrdup(serverURI);
	ListAppend(handles, m, sizeof(MQTTClients));

	m->c = malloc(sizeof(Clients));
	memset(m->c, '\0', sizeof(Clients));
	m->c->context = m;
	m->c->outboundMsgs = ListInitialize();
	m->c->inboundMsgs = ListInitialize();
	m->c->messageQueue = ListInitialize();
	m->c->clientID = MQTTStrdup(clientId);
	m->connect_sem = Thread_create_sem();
	m->connack_sem = Thread_create_sem();
	m->suback_sem = Thread_create_sem();
	m->unsuback_sem = Thread_create_sem();

#if !defined(NO_PERSISTENCE)
	rc = MQTTPersistence_create(&(m->c->persistence), persistence_type, persistence_context);
	if (rc == 0)
	{
		rc = MQTTPersistence_initialize(m->c, m->serverURI);
		if (rc == 0)
			MQTTPersistence_restoreMessageQueue(m->c);
	}
#endif
	ListAppend(bstate->clients, m->c, sizeof(Clients) + 3*sizeof(List));

exit:
	Thread_unlock_mutex(mqttclient_mutex);
	FUNC_EXIT_RC(rc);
	return rc;
}

  可以看到MQTTClient_create中调用了Log_initialize来初始化日志系统,Log_initialize源码为:

int Log_initialize(Log_nameValue* info)
{
	int rc = -1;
	char* envval = NULL;

	if ((trace_queue = malloc(sizeof(traceEntry) * trace_settings.max_trace_entries)) == NULL)
		return rc;
	trace_queue_size = trace_settings.max_trace_entries;

	if ((envval = getenv("MQTT_C_CLIENT_TRACE")) != NULL && strlen(envval) > 0)
	{
		if (strcmp(envval, "ON") == 0 || (trace_destination = fopen(envval, "w")) == NULL)
			trace_destination = stdout;
		else
		{
			trace_destination_name = malloc(strlen(envval) + 1);
			strcpy(trace_destination_name, envval);
			trace_destination_backup_name = malloc(strlen(envval) + 3);
			sprintf(trace_destination_backup_name, "%s.0", trace_destination_name);
		}
	}
	if ((envval = getenv("MQTT_C_CLIENT_TRACE_MAX_LINES")) != NULL && strlen(envval) > 0)
	{
		max_lines_per_file = atoi(envval);
		if (max_lines_per_file <= 0)
			max_lines_per_file = 1000;
	}
	if ((envval = getenv("MQTT_C_CLIENT_TRACE_LEVEL")) != NULL && strlen(envval) > 0)
	{
		if (strcmp(envval, "MAXIMUM") == 0 || strcmp(envval, "TRACE_MAXIMUM") == 0)
			trace_settings.trace_level = TRACE_MAXIMUM;
		else if (strcmp(envval, "MEDIUM") == 0 || strcmp(envval, "TRACE_MEDIUM") == 0)
			trace_settings.trace_level = TRACE_MEDIUM;
		else if (strcmp(envval, "MINIMUM") == 0 || strcmp(envval, "TRACE_MEDIUM") == 0)
			trace_settings.trace_level = TRACE_MINIMUM;
		else if (strcmp(envval, "PROTOCOL") == 0  || strcmp(envval, "TRACE_PROTOCOL") == 0)
			trace_output_level = TRACE_PROTOCOL;
		else if (strcmp(envval, "ERROR") == 0  || strcmp(envval, "TRACE_ERROR") == 0)
			trace_output_level = LOG_ERROR;
	}
	Log_output(TRACE_MINIMUM, "=========================================================");
	Log_output(TRACE_MINIMUM, "                   Trace Output");
	if (info)
	{
		while (info->name)
		{
			snprintf(msg_buf, sizeof(msg_buf), "%s: %s", info->name, info->value);
			Log_output(TRACE_MINIMUM, msg_buf);
			info++;
		}
	}
#if !defined(WIN32) && !defined(WIN64)
	struct stat buf;
	if (stat("/proc/version", &buf) != -1)
	{
		FILE* vfile;
		
		if ((vfile = fopen("/proc/version", "r")) != NULL)
		{
			int len;
			
			strcpy(msg_buf, "/proc/version: ");
			len = strlen(msg_buf);
			if (fgets(&msg_buf[len], sizeof(msg_buf) - len, vfile))
				Log_output(TRACE_MINIMUM, msg_buf);
			fclose(vfile);
		}
	}
#endif
	Log_output(TRACE_MINIMUM, "=========================================================");
		
	return rc;
}

  在Log_initialize中可以看到,日志系统主要通过调用getenv获取环境变量"MQTT_C_CLIENT_TRACE"和"MQTT_C_CLIENT_TRACE_LEVEL"的值来配置日志操作的, 前者表示日志文件路径,后者表示日志文件等级。

  这里可以使用c函数_putenv_s(头文件#include <stdlib.h>)来设置当前进程的环境变量,这里举例如下,设置日志文件路径为"D:\\client.log",日志等级为"MAXIMUM",表示打印所有日志。

int result = _putenv_s("MQTT_C_CLIENT_TRACE", "D:\\client.log");
result = _putenv_s("MQTT_C_CLIENT_TRACE_LEVEL","MAXIMUM");

  除此之外,还有如下日志等级:

log等级说明
ERROR ERROR log输出较少,出现ERROR情况下打印log
PROTOCOL 只打印mosquitto协议相关的log
MINIMUM 输出全部log
MEDIUM 输出全部log
MAXIMUM 输出全部log,包括内存分配和释放

  后三种log输出内容基本一致。

  这样一来,就可以在连接mqtt的时候打印日志了,但是切记调用mqtt API函数的工程跟mqtt的工程运行库设置需要一样(同时为MDd/MD或MT/MTd),不然不能打印日志。

  打印的日志如下:

  

 

参考资料:

http://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/tracing.html

 

posted on 2017-09-20 20:25  SpartacusIn21  阅读(2539)  评论(0编辑  收藏  举报

导航