Skip to content

Commit e128d1f

Browse files
authored
Add a logging sample (#1078)
1 parent 78ea1fe commit e128d1f

File tree

5 files changed

+187
-0
lines changed

5 files changed

+187
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Firebase SDK for Cloud Functions Quickstart - Structured Logs
2+
3+
This quickstart demonstrates using the **`logger`** subpackage to write structured logs to Cloud Logging.
4+
5+
Learn more about logging in Cloud Functions for Firebase [in the docs](https://firebase.google.com/docs/functions/writing-and-viewing-logs).
6+
7+
## License
8+
9+
© Google, 2023. Licensed under an [Apache-2](../../../LICENSE) license.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"functions": [
3+
{
4+
"source": "functions",
5+
"codebase": "default",
6+
"ignore": [
7+
"node_modules",
8+
".git",
9+
"firebase-debug.log",
10+
"firebase-debug.*.log"
11+
],
12+
"predeploy": [
13+
"npm --prefix \"$RESOURCE_DIR\" run lint"
14+
]
15+
}
16+
]
17+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module.exports = {
2+
env: {
3+
es6: true,
4+
node: true,
5+
},
6+
parserOptions: {
7+
"ecmaVersion": 2018,
8+
},
9+
extends: [
10+
"eslint:recommended",
11+
"google",
12+
],
13+
rules: {
14+
"no-restricted-globals": ["error", "name", "length"],
15+
"prefer-arrow-callback": "error",
16+
"quotes": ["error", "double", {"allowTemplateLiterals": true}],
17+
},
18+
overrides: [
19+
{
20+
files: ["**/*.spec.*"],
21+
env: {
22+
mocha: true,
23+
},
24+
rules: {},
25+
},
26+
],
27+
globals: {},
28+
};
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
const {onRequest} = require("firebase-functions/v2/https");
18+
const {
19+
onRegressionAlertPublished,
20+
} = require("firebase-functions/v2/alerts/crashlytics");
21+
22+
// [START loggerImport]
23+
// All available logging functions
24+
const {
25+
log,
26+
info,
27+
debug,
28+
warn,
29+
error,
30+
write,
31+
} = require("firebase-functions/logger");
32+
// [END loggerImport]
33+
34+
const {initializeApp} = require("firebase-admin/app");
35+
const {getFirestore} = require("firebase-admin/firestore");
36+
// Initialize admin sdk for Firestore read in getInspirationalQuote
37+
initializeApp();
38+
39+
// [START helloLogs]
40+
exports.helloWorld = onRequest((request, response) => {
41+
// sends a log to Cloud Logging
42+
log("Hello logs!");
43+
44+
response.send("Hello from Firebase!");
45+
});
46+
// [END helloLogs]
47+
48+
// [START logsKitchenSink]
49+
exports.getInspirationalQuote = onRequest(async (request, response) => {
50+
const db = getFirestore();
51+
const today = new Date();
52+
const quoteOfTheMonthRef = db
53+
.collection("quotes")
54+
.doc(today.getFullYear())
55+
.collection("months")
56+
.doc(today.getMonth());
57+
58+
const DEFAULT_QUOTE =
59+
"You miss 100% of the shots you don't take. -Wayne Gretzky";
60+
let quote;
61+
try {
62+
const quoteOfTheMonthDocSnap = await quoteOfTheMonthRef.get();
63+
64+
// Attach relevant debugging information with debug()
65+
debug("Monthly quote fetch result", {
66+
docRef: quoteOfTheMonthRef.path,
67+
exists: quoteOfTheMonthDocSnap.exists,
68+
createTime: quoteOfTheMonthDocSnap.createTime,
69+
});
70+
71+
if (quoteOfTheMonthDocSnap.exists) {
72+
quote = quoteOfTheMonthDocSnap.data().text;
73+
} else {
74+
// Use warn() for lower-severity issues than error()
75+
warn("Quote not found for month, sending default instead", {
76+
docRef: quoteOfTheMonthRef.path,
77+
dateRequested: today.toLocaleDateString("en-US"),
78+
});
79+
80+
quote = DEFAULT_QUOTE;
81+
}
82+
} catch (e) {
83+
// Attach stack trace to errors
84+
error("Unable to read quote from Firestore, sending default instead",
85+
{message: e.stack});
86+
87+
quote = DEFAULT_QUOTE;
88+
}
89+
90+
// Attach relevant structured data to any log
91+
info("Sending a quote!", {quote: quote});
92+
response.json({inspirationalQuote: quote});
93+
});
94+
// [END logsKitchenSink]
95+
96+
// [START customLogWrite]
97+
exports.appHasARegression = onRegressionAlertPublished((event) => {
98+
write({
99+
// write() lets you set additional severity levels
100+
// beyond the built-in logger functions
101+
severity: "EMERGENCY",
102+
message: "Regression in production app",
103+
issue: event.data.payload.issue,
104+
lastOccurred: event.data.payload.resolveTime,
105+
});
106+
});
107+
// [END customLogWrite]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "functions",
3+
"description": "Cloud Functions for Firebase",
4+
"scripts": {
5+
"lint": "eslint .",
6+
"serve": "firebase emulators:start --only functions",
7+
"shell": "firebase functions:shell",
8+
"start": "npm run shell",
9+
"deploy": "firebase deploy --only functions",
10+
"logs": "firebase functions:log"
11+
},
12+
"engines": {
13+
"node": "16"
14+
},
15+
"main": "index.js",
16+
"dependencies": {
17+
"firebase-admin": "^11.5.0",
18+
"firebase-functions": "^4.2.0"
19+
},
20+
"devDependencies": {
21+
"eslint": "^8.15.0",
22+
"eslint-config-google": "^0.14.0",
23+
"firebase-functions-test": "^3.0.0"
24+
},
25+
"private": true
26+
}

0 commit comments

Comments
 (0)