C++ 堵塞的重点是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/52357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the point of clog?
提问by markets
I've been wondering, what is the point of clog? As near as I can tell, clog is the same as cerr but with buffering so it is more efficient. Usually stderr is the same as stdout, so clog is the same as cout. This seems pretty lame to me, so I figure I must be misunderstanding it. If I have log messages going out to the same place I have error messages going out to (perhaps something in /var/log/messages), then I probably am not writing too much out (so there isn't much lost by using non-buffered cerr). In my experience, I want my log messages up to date (not buffered) so I can help find a crash (so I don't want to be using the buffered clog). Apparently I should always be using cerr.
我一直在想,堵塞有什么意义?据我所知,clog 与 cerr 相同,但具有缓冲功能,因此效率更高。通常stderr与stdout相同,所以clog与cout相同。这对我来说似乎很蹩脚,所以我想我一定是误解了它。如果我将日志消息发送到我有错误消息发送到的同一个地方(可能是 /var/log/messages 中的某些内容),那么我可能不会写太多(因此使用 non 不会丢失太多) - 缓冲的 cerr)。根据我的经验,我希望我的日志消息是最新的(没有缓冲),这样我就可以帮助找到崩溃(所以我不想使用缓冲的阻塞)。显然我应该总是使用 cerr。
I'd like to be able to redirect clog inside my program. It would be useful to redirect cerr so that when I call a library routine I can control where cerr and clog go to. Can some compilers support this? I just checked DJGPP and stdout is defined as the address of a FILE struct, so it is illegal to do something like "stdout = freopen(...)".
我希望能够在我的程序中重定向阻塞。重定向 cerr 会很有用,这样当我调用库例程时,我可以控制 cerr 和 clog 的去向。一些编译器可以支持这个吗?我刚刚检查了 DJGPP 并且 stdout 被定义为 FILE 结构的地址,因此执行诸如“stdout = freopen(...)”之类的操作是非法的。
- Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?
- Is the only difference between clog and cerr the buffering?
- How should I implement (or find) a more robust logging facility (links please)?
- 是否可以重定向 clog、cerr、cout、stdin、stdout 和/或 stderr?
- clog 和 cerr 之间的唯一区别是缓冲吗?
- 我应该如何实现(或找到)更强大的日志记录工具(请提供链接)?
采纳答案by Konrad Rudolph
Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?
是否可以重定向 clog、cerr、cout、stdin、stdout 和/或 stderr?
Yes. You want the rdbuf
function.
是的。你想要这个rdbuf
功能。
ofstream ofs("logfile");
cout.rdbuf(ofs.rdbuf());
cout << "Goes to file." << endl;
Is the only difference between clog and cerr the buffering?
clog 和 cerr 之间的唯一区别是缓冲吗?
As far as I know, yes.
据我所知,是的。
回答by Ben Collins
If you're in a posix shell environment (I'm really thinking of bash), you can redirect any file descriptor to any other file descriptor, so to redirect, you can just:
如果您在 posix shell 环境中(我真的在考虑 bash),您可以将任何文件描述符重定向到任何其他文件描述符,因此要重定向,您只需:
$ myprogram 2>&5
to redirect stderr to the file represented by fd=5.
将 stderr 重定向到 fd=5 表示的文件。
Edit: on second thought, I like @Konrad Rudolph's answer about redirection better. rdbuf() is a more coherent and portable way to do it.
编辑:再想一想,我更喜欢@Konrad Rudolph 关于重定向的回答。rdbuf() 是一种更加连贯和便携的方式来做到这一点。
As for logging, well...I start with the Boost library for all things C++ that isn't in the std library. Behold: Boost Logging v2
至于日志记录,嗯……我从 Boost 库开始,用于所有不在 std 库中的 C++ 内容。看:Boost Logging v2
Edit: Boost Logging is notpart of the Boost Libraries; it has been reviewed, but not accepted.
编辑:Boost Logging不是Boost 库的一部分;它已被,但未被接受。
Edit: 2 years later, back in May 2010, Boost did accept a logging library, now called Boost.Log.
编辑:2 年后,回到 2010 年 5 月,Boost 确实接受了一个日志库,现在称为Boost.Log。
Of course, there are alternatives:
当然,还有其他选择:
- Log4Cpp(a log4j-style API for C++)
- Log4Cxx(Apache-sponsored log4j-style API)
- Pantheios(defunct? last time I tried I couldn't get it to build on a recent compiler)
- Google's GLog(hat-tip @SuperElectric)
- Log4Cpp(用于 C++ 的 log4j 风格的 API)
- Log4Cxx(Apache 赞助的 log4j 风格的 API)
- Pantheios(已不复存在?上次我尝试时无法在最近的编译器上构建它)
- Google 的 GLog(帽子提示 @SuperElectric)
There's also the Windows Event logger.
还有 Windows 事件记录器。
And a couple of articles that may be of use:
还有一些可能有用的文章:
回答by Alexis Wilke
Redirections
重定向
Konrad Rudolph answer is good in regard to how to redirect the std::clog
(std::wclog
).
康拉德·鲁道夫 (Konrad Rudolph) 在如何重定向std::clog
( std::wclog
)方面的回答很好。
Other answers tell you about various possibilities such as using a command line redirect such as 2>output.log
. With Unix you can also create a file and add another output to your commands with something like 3>output.log
. In your program you then have to use fd
number 3 to print the logs. You can continue to print to stdout
and stderr
normally. The Visual Studio IDE has a similar feature with their CDebug
command, which sends its output to the IDE output window.
其他答案会告诉您各种可能性,例如使用命令行重定向,例如2>output.log
. 使用 Unix,您还可以创建一个文件并将另一个输出添加到您的命令中,例如3>output.log
. 在您的程序中,您必须使用fd
数字 3 来打印日志。您可以继续打印到stdout
和stderr
正常。Visual Studio IDE 具有与其CDebug
命令类似的功能,将其输出发送到 IDE 输出窗口。
stderr
is the same asstdout
?
stderr
是一样的stdout
吗?
This is generally true, but under Unix you can setup the stderr
to /dev/console
which means that it goes to another tty
(a.k.a. terminal). It's rarely used these days. I had it that way on IRIX. I would open a separate X-Window and see errors in it.
这通常是正确的,但在 Unix 下,您可以设置stderr
to/dev/console
这意味着它转到另一个tty
(又名终端)。这些天很少使用它。我在 IRIX 上就是这样的。我会打开一个单独的 X 窗口并查看其中的错误。
syslog
系统日志
One thing not mentioned, under Unix, you also have syslog()
.
有一件事没有提到,在 Unix 下,你也有syslog()
.
The newest versions under Linux (and probably Mac OS/X) does a lot more than it used to. Especially, it can use the identity and some other parameters to redirect the logs to a specific file (i.e. mail.log
). The syslog mechanism can be used between computers, so logs from computer A can be sent to computer B. And of course you can filter logs in various ways, especially by severity.
Linux(可能还有 Mac OS/X)下的最新版本比以前做的要多得多。特别是,它可以使用身份和其他一些参数将日志重定向到特定文件(即mail.log
)。syslog 机制可以在计算机之间使用,因此可以将来自计算机 A 的日志发送到计算机 B。当然,您可以通过多种方式过滤日志,尤其是按严重性。
The syslog()
is also very simple to use:
使用起来syslog()
也非常简单:
syslog(LOG_ERR, "message #%d", count++);
It offers 8 levels (or severity), a format a la printf()
, and a list of arguments for the format.
它提供 8 个级别(或严重性)、格式 a laprintf()
和格式参数列表。
Programmatically, you may tweak a few things if you first call the openlog()
function. You must call it before your first call to syslog()
.
以编程方式,如果您第一次调用该openlog()
函数,您可能会调整一些事情。您必须在第一次调用 之前调用它syslog()
。
As mentioned by unixman83, you may want to use a macro instead. That way you can include some parameters to your messages without having to repeat them over and over again. Maybe something like this (see Variadic Macro):
正如 unixman83 所提到的,您可能想改用宏。这样你就可以在你的消息中包含一些参数,而不必一遍又一遍地重复它们。也许是这样的(见Variadic Macro):
// (not tested... requires msg to be a string literal)
#define LOG(lvl, msg, ...) \
syslog(lvl, msg " (in " __FILE__ ":%d)", __VA_ARGS__, __LINE__)
You may also find __func__
useful.
你也可能觉得__func__
有用。
The redirection, filtering, etc. is done by creating configuration files. Here is an examplefrom my snapwebsites project:
重定向、过滤等是通过创建配置文件来完成的。这是我的 snapwebsites 项目中的一个示例:
mail.err /var/log/mail/mail.err
mail.* /var/log/mail/mail.log
& stop
I install the file under /etc/rsyslog.d/
and the syslog
server automatically handles that change and saves any mail related logs to those folders.
我将文件安装在下面/etc/rsyslog.d/
,syslog
服务器会自动处理该更改并将任何与邮件相关的日志保存到这些文件夹中。
Note: I also have to create the /va/log/mail
folder and the files inside the folder to make sure it all works right (because otherwise the mail daemon may not have enough permissions.)
注意:我还必须创建/va/log/mail
文件夹和文件夹内的文件,以确保一切正常(否则邮件守护程序可能没有足够的权限。)
snaplogger (a little plug)
snaplogger(一个小插头)
I've used log4cplus, which, since version 1.2.x, is quite good. I have three cons about it, though:
我使用过log4cplus,它从 1.2.x 版开始就非常好。不过,我有三个缺点:
- it requires me to completely clear everything if I want to call fork(); somehow it does not survive a fork() call properly... (at least in the version I had)
- the configuration files (.properties) are not easy to manage in my environment where I like the administrators to make changes without modifying the original
- it uses C++03 and we are now in 2019... I'd like to have at least C++11
- 如果我想调用 fork(),它需要我完全清除所有内容;不知何故,它无法在 fork() 正确调用中存活下来......(至少在我拥有的版本中)
- 配置文件 (.properties) 在我的环境中不容易管理,我喜欢管理员在不修改原始文件的情况下进行更改
- 它使用 C++03,我们现在在 2019 年......我希望至少有 C++11
Because of that, and especially because of point (1), I wrote my own version called snaplogger. This is not exactly a standalone project, though. I use many other projects from the snapcpp environment (it's much easier to just get snapcpp and run the bin/build-snap
script or just get the binaries from launchpad.)
正因为如此,尤其是因为第 (1) 点,我编写了自己的名为snaplogger的版本。不过,这并不完全是一个独立的项目。我使用了 snapcpp 环境中的许多其他项目(获取 snapcpp 并运行bin/build-snap
脚本或仅从launchpad 获取二进制文件要容易得多。)
The advantage of using a logger such as snaplogger or log4cplus is that you generally can define any number of destinations and many other parameters (such as the severity level as offered by syslog()
). The log4cplus is capable of sending its output to many different places: files, syslog, MS-Windows log system, console, a server, etc. Check out the appenders in those two projects to have an idea of the list of possibilities. The interesting factor here is that any log can be sent to all the destinations. This is useful to have a file named all.log where all your services send their logs. This allows to understand certain bugs which would not be as easy with separate log files when running many services in parallel.
使用 snaplogger 或 log4cplus 等记录器的优点是您通常可以定义任意数量的目的地和许多其他参数(例如由 提供的严重性级别syslog()
)。log4cplus 能够将其输出发送到许多不同的地方:文件、系统日志、MS-Windows 日志系统、控制台、服务器等。查看这两个项目中的附加程序以了解可能性列表。这里有趣的因素是任何日志都可以发送到所有目的地。这对于有一个名为 all.log 的文件很有用,您的所有服务都在其中发送它们的日志。这允许理解在并行运行许多服务时使用单独的日志文件不会那么容易的某些错误。
Here is a simple example in a snaplogger configuration file:
这是 snaplogger 配置文件中的一个简单示例:
[all]
type=file
lock=true
filename=/var/log/snapwebsites/all.log
[file]
lock=false
filename=/var/log/snapwebsites/firewall.log
Notice that for the all.log
file I require a lock so multiple writers do not mangle the logs between each others. It's not necessary for the [file]
section because I only have one process (no threads) for that one.
请注意,对于all.log
文件,我需要一个锁,以便多个作者不会破坏彼此之间的日志。这[file]
部分没有必要,因为我只有一个进程(没有线程)。
Both offer you a way to add your own appenders. So for example if you have a Qt application with an output window, you could write an appender to send the output of the SNAP_LOG_ERROR()
calls to that window.
两者都为您提供了一种添加自己的 appender 的方法。例如,如果您有一个带有输出窗口的 Qt 应用程序,您可以编写一个 appender 将SNAP_LOG_ERROR()
调用的输出发送到该窗口。
snaplogger
also offers you a way to extend the variable support in messages (also called the format.) For example, I can insert the date using the ${date}
variable. Then I can tweak it with a parameter. To only output the year, I use ${date:year}
. This variable parameter support is also extensible.
snaplogger
还为您提供了一种方法来扩展消息中的变量支持(也称为格式)。例如,我可以使用${date}
变量插入日期。然后我可以用一个参数来调整它。为了只输出年份,我使用${date:year}
. 这种可变参数支持也是可扩展的。
snaplogger
can filter the output by severity (like syslog), by a regex, and by component. We have a normal
and a secure
component, the default is normal
. I want logs sent to the secure
component to be written to secure files. This means in a sub-directory which is way more protected than the normal logs that most admins can review. When I run my HTTP services, some times I send information such as the last 3 digits of a credit card. I prefer to have those in a secure log. It could also be password related errors. Anything I deem to be a security risk in a log, really. Again, components are extensible so you can have your own.
snaplogger
可以按严重性(如系统日志)、正则表达式和组件过滤输出。我们有一个normal
和一个secure
组件,默认是normal
. 我希望将发送到secure
组件的日志写入安全文件。这意味着在一个子目录中,它比大多数管理员可以查看的普通日志受到更多的保护。当我运行 HTTP 服务时,有时我会发送信息,例如信用卡的最后 3 位数字。我更喜欢将它们保存在安全日志中。也可能是与密码相关的错误。我认为日志中存在安全风险的任何内容,真的。同样,组件是可扩展的,因此您可以拥有自己的组件。
回答by Chipster
Since there are several answers here about redirection, I will add this nice gemI stumbled across recently about redirection:
由于这里有几个关于重定向的答案,我将添加我最近偶然发现的关于重定向的这个不错的宝石:
#include <fstream>
#include <iostream>
class redirecter
{
public:
redirecter(std::ostream & dst, std::ostream & src)
: src(src), sbuf(src.rdbuf(dst.rdbuf())) {}
~redirecter() { src.rdbuf(sbuf); }
private:
std::ostream & src;
std::streambuf * const sbuf;
};
void hello_world()
{
std::cout << "Hello, world!\n";
}
int main()
{
std::ofstream log("hello-world.log");
redirecter redirect(log, std::cout);
hello_world();
return 0;
}
It's basically a redirection class that allows you to redirect any two streams, and restore it when you're finished.
它基本上是一个重定向类,允许您重定向任意两个流,并在完成后恢复它。
回答by unixman83
Basic Logger
基本记录器
#define myerr(e) {CriticalSectionLocker crit; std::cerr << e << std::endl;}
Used as myerr("ERR: " << message);
or myerr("WARN: " << message << code << etc);
用作myerr("ERR: " << message);
或myerr("WARN: " << message << code << etc);
Is very effective.
非常有效。
Then do:
然后做:
./programname.exe 2> ./stderr.log
perl parsestderr.pl stderr.log
or just parse stderr.log by hand
或者只是手动解析 stderr.log
I admit this is not for extremelyperformance critical code. But who writes that anyway.
我承认这不是针对性能极其关键的代码。但无论如何谁写的。