如何将命令输出日志重定向到跟踪系统

huangapple go评论88阅读模式
英文:

How to redirect logs from Command Output to tracing

问题

我正在将追踪作为Rust应用程序的日志工具。我希望所有日志都经过追踪。将来,它将处理将日志发送到监控工具。

应用程序本身调用多个进程。以前,它们将日志打印到标准输出,所有日志都可见。这些进程是使用Rust的Commandtokio::spawn运行的。

我想将Command的输出重定向到追踪,但不太确定如何做到这一点。

英文:

I'm adopting tracing as logging tool for rust app. I want to have all logs go through tracing. In the future, it will handle send logs to monitoring tool.

App by itself invoking multiple processes. Previously they were printing to Stdin and all logs were visible. Those processes ran with rust Command and tokio::spawn.

I would like to redirect the output from Command Output to the tracing, but not really confident how to do that.

答案1

得分: 1

根据我的理解,你之前使用过 println!,现在想要使用 tracing。

要启用 tracing,有两个部分:

  1. 在想要记录日志的地方,将 println! 替换为 info!warning! 或其他适当的日志级别,并在开头添加 use tracing::{info, warning}。这不会启用 tracing,因为如果没有订阅者对这些日志感兴趣,编译器会删除这些行。
  2. 因此,你必须在主进程启动的地方添加 tracing_subsriber。在 tokio::spawn 之前。
    简单方法
use tracing_subscriber;

tracing_subscriber::fmt::init();

更详细的方法

use tracing_subscriber::FmtSubscriber;
use tracing::{Level};

let subscriber = FmtSubscriber::builder()
    .with_max_level(Level::TRACE)
    // ... 这里你可以添加文件,如果需要的话,或者同时输出到 stdout 和文件。
    .finish();

查看 文档 获取配置信息。

你也可以创建 spans 以进行更详细的追踪,但这不明显是你所寻找的。

英文:

As I understand you used println! before and now you want to use tracing.

To activate tracing there are two parts:

  1. where you want to issue the log you replace println! with info! or warning! or other levels, whatever you feel suitable. And you do use tracing::{info, warning} in the beginning. That would not activate tracing as the compiler would just remove these lines if there is no subscriber who is interested in these logs.
  2. So you have to add tracing_subsriber somewhere where your main process start. Before tokio::spawn
    Simple way
use tracing_subscriber;

tracing_subscriber::fmt::init();

more detailed method

use tracing_subscriber::FmtSubscriber;
use tracing::{Level};

let subscriber = FmtSubscriber::builder()
    .with_max_level(Level::TRACE)
    // ... here you can add file if you want. Or both stdout and file.
    .finish();

See the docs for the configurations.

You can also create spans for more granular tracing but it is not evident that it is what you are looking for.

答案2

得分: 1

调用 std::Command::output 的结果是一个 Result<Output>,而 Output 结构具有公共的 stdout 和 stderr Vec<u8> 字段。

就像 Nikolay 所写的那样,您可以使用 tracing::info! 输出每个字段的值。

但如果现有的代码正在将输出写入应用程序本身的 stdout 和 stderr,也许正在使用 std::Command::spawn?您可以继续使用这个 spawn 方法,并从 child 获取 stdoutstderr,就像 std::process::Child 中所示,然后实际上创建新线程来从 stdout 和 stderr 中读取数据,然后将数据传递给 info! 这样的跟踪宏。

我怀疑 tracing 库可能没有一种通用的方法来执行这个操作,因为子进程的 stdout 和 stderr 可能以许多不同的方式进行格式化。

但如果您预期输出很短并且不需要解析,那么将 stdout 和 stderr 向量传递给 info! 应该可以解决问题,就像上面提到的那样。

英文:

The result of calling std::Command::output is a Result&lt;Output> and the Output struct has public stdout and stderr Vec&lt;u8&gt; fields.

So like Nikolay wrote, you can can tracing::info! to output each of the field values.

But if the existing code was writing to the stdout and stderr of the app itself, maybe std::Command::spawn was being used? You may want to continue using this spawn method and taking the stdout and stderr from the child as shown in std::process::Child and then actually spawning new threads to read from the stdout and stderr to pass the data to tracing macros like info!.

I doubt the tracing library would have a canned way of doing this because subprocess stdout and stderr could be formatted in so many ways.

But if you expect the output to be short and no parsing is necessary, then passing the stdout and stderr vecs to info! should do the trick as mentioned above.

huangapple
  • 本文由 发表于 2023年1月9日 18:46:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75056141.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定