zoukankan      html  css  js  c++  java
  • 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, '', 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, '', 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

  • 相关阅读:
    求24点
    关于参数和返回值的常量性
    点到平面的距离公式
    大端序与小端序
    Quake3中的绝对值函数
    整数超出范围时如何表示?
    关于数组的几道面试题
    在移位数组中查找数
    时间复杂度O(n),空间复杂度O(1)的排序
    C++之对象切割
  • 原文地址:https://www.cnblogs.com/chenyangchun/p/7563323.html
Copyright © 2011-2022 走看看