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
paho.mqtt.c打印日志的更多相关文章
- Xcode8中处理打印日志的配置
Xcode8中处理打印日志的配置
- Mybatis框架基于映射文件和配置文件的方式,实现增删改查,可以打印日志信息
首先在lib下导入: 与打印日志信息有关的架包 log4j-1.2.16.jar mybatis架包:mybatis-3.1.1.jar 连接数据库的架包:mysql-connector-java-5 ...
- Log打印日志遇到的问题
Log日志打印出现空指针问题 AndroidRuntime(372): Caused by: java.lang.NullPointerException: println needs a messa ...
- 重写NSLog,Debug模式下打印日志和当前行数
在pch文件中加入以下命令,NSLog在真机测试中就不会打印了 //重写NSLog,Debug模式下打印日志和当前行数 #if DEBUG #define NSLog(FORMAT, ...) fpr ...
- android112 c代码打印日志,c反编译调用java
activity: package com.itheima.ccalljava; import android.os.Bundle; import android.app.Activity; impo ...
- ruby脚本打印日志到rspec的报告文件中
在通过ruby+webdriver+rspec做自动化测试的时候,为了便于观察用例执行情况,我基本上都会用 rspec XX.rb --format doc -o result.log 如果遇到失败的 ...
- Log4j配置的经典总结,打印日志文件,日志存库
一.介绍 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制 日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Sy ...
- rsyslog 不打印日志到/var/log/messages
*.info;mail.none;authpriv.none;cron.none;local3.none /var/log/messages 表示 所有来源的info级别都记录到/var/log/me ...
- 以打印日志为荣之logging模块详细使用
啄木鸟社区里的Pythonic八荣八耻有一条: 以打印日志为荣 , 以单步跟踪为耻; 很多程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误.警告等信息输出,python ...
随机推荐
- Luogu P1747 好奇怪的游戏
题目背景 <爱与愁的故事第三弹·shopping>娱乐章. 调调口味来道水题. 题目描述 爱与愁大神坐在公交车上无聊,于是玩起了手机.一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名被 ...
- ACL访问控制列表
acl是基于文件系统的,所以支不支持acl在于使用什么文件系统. FAT32文件系统不支持权限,也不区分大小写 如果一个分区不是安装系统时分的分区,是一个新的分区的话,默认是不支持acl CentOS ...
- centos7安装zabbix3.2.4
系统:CentOS Linux release 7.2.1511 (Core) zabbix:3.2.4 一.yum -y install httpd mysql mysql-server mysql ...
- shell脚本基础 循环机构
循环结构 for循环格式一格式:for 变量 in 值1 值2 ........(值不一定是数字,可以是命令或者其他的)do 命令done [root@ceshiji ~]# vim a.sh #!/ ...
- 【前端】Vue和Vux开发WebApp日志四、增加命令行参数
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/vue_vux_4.html 项目github地址:https://github.com/shamoyuu/vue- ...
- MS SQL xp_instance_regwrite设置注册表疑惑
以前写过一篇博文"MS SQL 日志记录管理",里面介绍了如何设置SQL Server的错误日志的最大归档数量,如果在SSMS的UI界面设置,可以从"Manageme ...
- Davinci DM6446开发攻略——linux-2.6.18移植
TI DAVINCI 使用最新的内核是montavista linux-2.6.18,之前说过,国内很多公司,包括开发板的软件包,一直在使用montavista linux-2.6.10,这个版本准 ...
- python︱Anaconda安装、简介(安装报错问题解决、Jupyter Notebook)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 安装完anaconda,就相当于安装了Pyth ...
- Jenkins Android 自动打包配置
一.Jenkins自动打包配置 目标:1. 自动打包:2. 自动上传:3. 友好下载 1. Jenkins简介 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作. 减少重复劳 ...
- 一句Python,一句R︱pandas模块——高级版data.frame
先学了R,最近刚刚上手python,所以想着将python和R结合起来互相对比来更好理解python.最好就是一句python,对应写一句R. pandas可谓如雷贯耳,数据处理神器. 以下符号: = ...