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 ...
随机推荐
- TCP/IP读书笔记(4) IPv4和IPv6 路由选择
TCP/IP读书笔记(4) IPv4和IPv6 路由选择 网络层是位于链路层之上,TCP/IP模型中网络层的核心协议是IP协议(Internet protocol). 目前主流的IP协议是IPv4(I ...
- ajax的缺点
平时我们大多注意的都是ajax给我们所带来的好处诸如用户体验的提升.对ajax所带来的缺陷有所忽视. 下面所阐述的ajax的缺陷都是它先天所产生的. 1.ajax干掉了back按钮,即对浏览器后退机制 ...
- PHPmysqli的 其他函数 从数据库中读出数据并且打印出来
<?php // 认识其他mysqli其他函数 header( 'Content-Type:text/html;charset=utf-8 '); require 'prepareSrarmen ...
- 【mysql】mysql主从复制
mysql主从复制配置 主服务器:192.168.0.100 从服务器 192.168.0.101 主服务器配置 my.ini(window下 linux 下是my.cnf) #开启二进制日志 log ...
- jQuery中的val()
jQuery中的val() 1.实例源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &qu ...
- java.text.ParseException: Unparseable date: "2015-06-09 hh:56:19"
1.错误描述 [DEBUG:]2015-06-09 16:56:19,520 [-------------------transcation start!--------------] java.te ...
- Caused by: java.sql.SQLException: Operand should contain 1 column(s)
1.错误描述 [ERROR:]2015-05-05 15:48:55,847 [异常拦截] org.hibernate.exception.DataException: error executing ...
- C# 高效字符串连接 StringBuilder介绍
在介绍StringBuilder之前,必须要先了解string的特性. string在.NET中属于基本数据类型,也是基本数据类型中唯一的引用类型.字符串可以声明为常量,但它却放在了堆中. 一:不可改 ...
- POJO
简单的Java对象(Plain Ordinary Java Objects)实际就是普通JavaBeans,使用POJO名称是为了避免和EJB混淆起来, 而且简称比较直接. 其中有一些属性及其gett ...
- 爬数据,能让你少写1000行代码的捷径! | Python 正则表达式
▌春暖花开,又到了出门游玩拍拍拍吃吃吃的好季节了! 说到拍照摄影,你会构图吗?就是在照片有限的空间内处理人.景.物的关系,并将三者安排在画面中最佳的位置,以形成画面特定结构的方法. 学院君就是一个「拍 ...