【问题标题】:Log 'jsonPayload' in Firebase Cloud Functions在 Firebase Cloud Functions 中记录“jsonPayload”
【发布时间】:2018-03-09 02:45:51
【问题描述】:

TL;DR;

有谁知道是否可以在 Firebase/Google Cloud 函数中使用 console.log 使用 jsonPayload 属性将条目记录到堆栈驱动程序,以便我的日志可以搜索(目前我传递给 console.log 的任何内容都会被字符串化为textPayload)。


我有一个多模块项目,其中一些代码在 Firebase Cloud Functions 上运行,一些在其他环境中运行,例如 Google Compute Engine。稍微简化一下,我基本上有一个“核心”模块,然后我将“云功能”模块部署到 Cloud Functions,将“后端服务”部署到 GCE,这些都依赖于“核心”等。

我在整个“核心”模块中使用 bunyan 进行日志记录,当部署到 GCE 时,记录器是使用“@google-cloud/logging-bunyan”配置的,因此我的日志会转到 Stack Driver。

除此之外:在 Google Cloud Functions 中使用此配置会导致 Error: Endpoint read failed 出现问题,我认为这是由于函数不会变冷并试图重用死连接,但我不能 100% 确定真正的问题是什么原因是。

所以现在我尝试使用console.log(arg) 记录,其中arg 是一个对象,而不是字符串。我希望这个对象出现在堆栈驱动程序中的jsonPayload 下,但它正在被字符串化并放入textPayload 字段中。

【问题讨论】:

标签: firebase google-cloud-functions stackdriver


【解决方案1】:

我花了一段时间,但我终于在firebase functions samples repository 中遇到了this example。最后我决定了一些类似这样的东西:

const Logging = require('@google-cloud/logging');
const logging = new Logging();
const log = logging.log('my-func-logger');
const logMetadata = {
  resource: {
    type: 'cloud_function',
    labels: {
      function_name: process.env.FUNCTION_NAME ,
      project: process.env.GCLOUD_PROJECT,
      region: process.env.FUNCTION_REGION
    },
  },
};
const logData = { id: 1, score: 100 };
const entry = log.entry(logMetaData, logData);
log.write(entry)

您可以将字符串severity 属性值添加到logMetaData(例如“INFO”或“ERROR”)。 Here is the list 的可能值。


可用节点 10 环境变量的更新。这些似乎可以解决问题:

labels: {
  function_name: process.env.FUNCTION_TARGET,
  project: process.env.GCP_PROJECT,
  region: JSON.parse(process.env.FIREBASE_CONFIG).locationId
}

更新:对于 Node 10 运行时,他们希望您在部署期间使用 set env values explicitly。我想有一个宽限期,因为我部署的功能仍在工作。

【讨论】:

  • 这是我最终采取的路线,我也在使用 GKE,kubernetes 从标准输出收集日志作为 textPayload,希望我可以使用 console.log 而不必处理日志记录构架。但正如您也发现的那样,获取 jsonPayload 的唯一方法是使用日志库。
  • 很好的答案,谢谢。现在我剩下的就是把labels['execution_id'] 也放进去(如果你在Firebase 上使用console.log 会得到同样的结果)。
  • PS 它看起来像 @google-cloud/logging-winston(也许是 bunyan 替代品)会自动添加您的 logMetadata。尽管如此,execution_id 还是避开了我。我可能不得不自己跟踪github.com/googleapis/…
  • 您是否将 Logging 实例保留在全局上下文中?或者您是否为每个请求创建一个新请求?很好奇,当云功能在未使用时受到 CPU 限制时,您是否遇到过死连接问题。
  • 每个请求的新实例。我相信已经加载的云函数可以重用,因此需要确保每个调用都有自己的日志实例。
【解决方案2】:

我遇到了同样的问题,正如 cmets 在 @wtk 的回答中所说,我想添加复制我可以在下面的 sn-p 中找到的所有默认云函数日志记录行为,包括 execution_id。

至少对于使用Cloud FunctionsHTTP Trigger 选项,以下为我生成了正确的日志。我还没有测试过Firebase Cloud Functions

// global
const { Logging } = require("@google-cloud/logging");
const logging = new Logging();
const Log = logging.log("cloudfunctions.googleapis.com%2Fcloud-functions");
const LogMetadata = {
  severity: "INFO",
  type: "cloud_function",
  labels: {
    function_name: process.env.FUNCTION_NAME,
    project: process.env.GCLOUD_PROJECT,
    region: process.env.FUNCTION_REGION
  }
};

// per request
const data = { foo: "bar" };
const traceId = req.get("x-cloud-trace-context").split("/")[0];
const metadata = {
  ...LogMetadata,
  severity: 'INFO',
  trace: `projects/${process.env.GCLOUD_PROJECT}/traces/${traceId}`,
  labels: {
    execution_id: req.get("function-execution-id")
  }
};
Log.write(Log.entry(metadata, data));

【讨论】:

  • 这仍然对您有用吗?必须像那样携带trace id真是太烦人了
【解决方案3】:

@wtk 答案中的 github 链接应更新为:

https://github.com/firebase/functions-samples/blob/2f678fb933e416fed9be93e290ae79f5ea463a2b/stripe/functions/index.js#L103

因为它指的是问题被回答时的存储库,并且在其中具有以下功能:

// To keep on top of errors, we should raise a verbose error report with Stackdriver rather
// than simply relying on console.error. This will calculate users affected + send you email
// alerts, if you've opted into receiving them.
// [START reporterror]
function reportError(err, context = {}) {
    // This is the name of the StackDriver log stream that will receive the log
    // entry. This name can be any valid log stream name, but must contain "err"
    // in order for the error to be picked up by StackDriver Error Reporting.
    const logName = 'errors';
    const log = logging.log(logName);

    // https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/MonitoredResource
    const metadata = {
    resource: {
        type: 'cloud_function',
        labels: {function_name: process.env.FUNCTION_NAME},
    },
    };

    // https://cloud.google.com/error-reporting/reference/rest/v1beta1/ErrorEvent
    const errorEvent = {
    message: err.stack,
    serviceContext: {
        service: process.env.FUNCTION_NAME,
        resourceType: 'cloud_function',
    },
    context: context,
    };

    // Write the error log entry
    return new Promise((resolve, reject) => {
    log.write(log.entry(metadata, errorEvent), (error) => {
        if (error) {
        return reject(error);
        }
        resolve();
    });
    });
}
// [END reporterror]

【讨论】:

    猜你喜欢
    • 2021-03-02
    • 2018-01-02
    • 1970-01-01
    • 2018-06-11
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    相关资源
    最近更新 更多