forked from haggman/HelloLoggingNodeJS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
187 lines (159 loc) · 5.1 KB
/
index.js
File metadata and controls
187 lines (159 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//This is a simple NodeJS app designed to explore various Google Cloud
//operations suite products
//Setup for tracing
const tracer = require('@google-cloud/trace-agent').start();
//Enable Debugger
require('@google-cloud/debug-agent').start(
{
allowExpressions: true, //So logpoint expressions will work
serviceContext: {
enableCanary: false,
service: 'hello-logging-js', //This is mostly for GKE.
version: '1.0' //set from env vars IRL
}});
// Enable Error Reporting
// Import the GCP ErrorReporting library
const {ErrorReporting} = require('@google-cloud/error-reporting');
const errors = new ErrorReporting({
reportMode: 'always', //as opposed to only while in production
serviceContext: {
service: 'hello-logging-js',
version: '1.0',
}
});
// Enable the Profiler
require('@google-cloud/profiler').start({
serviceContext: {
service: 'hello-logging-js',
version: '1.0',
},
});
//Setup a listener to catch all uncaught exceptions
process.on('uncaughtException', (e) => {
// Write the error to stderr.
console.error(e);
// Report that same error the Error Service
errors.report(e);
});
//Setup a Winston logger adding GCP support
//Not a best practice, but some coders still prefer
//using logging libraries
const winston = require('winston');
//Here's the GCP addon
const {LoggingWinston} = require('@google-cloud/logging-winston');
const loggingWinston = new LoggingWinston();
const logger = winston.createLogger({
level: 'info', //default logging level
transports: [
// Add GCP Logging
loggingWinston,
],
});
//Load the express server
const express = require('express');
const app = express();
app.disable('etag'); //so it will return 200 and 304 etc. codes.
//Setup some values used later in code
const { v1: uuidv1 } = require('uuid');
const containerID = uuidv1();
const funFactor = Math.floor(Math.random() * 5) + 1; //just for fun
// ******
// The web routes start here
// ******
//A classic Hello World, not using our logger
//but it is doing a classic console.log
app.get('/', (req, res) => {
console.log('/ version of Hello world received a request');
const target = process.env.TARGET || 'World';
res.send(`Hello ${target}!`);
});
//Another classic Hello World, this one using Winston to GCP
app.get('/log', (req, res) => {
logger.info("/log version of Hello World received a request")
const target = process.env.TARGET || 'World';
res.send(`Hello ${target}, from /log!`);
});
//Basic NodeJS app built with the express server
app.get('/score', (req, res) => {
//Random score, the contaierID is a UUID unique to each
//runtime container (testing was done in Cloud Run).
//funFactor is a random number 1-100
let score = Math.floor(Math.random() * 100) + 1;
console.log(`/score called, score:${score}, containerID:${containerID}, funFactor:${funFactor}`);
//Basic message back to browser
res.send(`Your score is a ${score}. Happy?`);
});
//Manually report an error
app.get('/error', (req, res) => {
try{
doesNotExist();
}
catch(e){
//This is a log, will not show in Error Reporter
console.error("Error processing /error " + e);
//Let's manually pass it to Error Reporter
errors.report("Error processing /error " + e);
}
res.send("Broken now, come back later.")
});
//Uncaught exception, auto reported
app.get('/uncaught', (req, res) => {
doesNotExist();
//won't ever get to:
res.send("Broken now, come back later.")
});
//Generates an uncaught exception every 1000 requests
app.get('/random-error', (req, res) => {
error_rate = parseInt(req.query.error_rate) || 1000
let errorNum = (Math.floor(Math.random() * error_rate) + 1);
if (errorNum==1) {
console.log("Called /random-error, and it's about to error");
doesNotExist();
}
console.log("Called /random-error, and it worked");
res.send("Worked this time.");
});
//Generates a slow request
//If you wanted more trace detail, you could use tracer and create some
//extra spans, like
//const customSpan1 = tracer.createChildSpan({name: 'slowPi'});
//customSpan1.endSpan();
app.get('/slow', (req, res) => {
let pi1=slowPi();
let pi2=slowPi2();
res.send(`Took it's time. pi to 1,000 places: ${pi1}, pi to 10,000 places: ${pi2}`);
});
function slowPi(){
let pi = piCalc(1000n);
console.log(`How's this pi? ${pi}`);
return pi;
}
function slowPi2(){
let pi = piCalc(10000n);
console.log(`Here's a bigger pi? ${pi}`)
return pi;
}
//Use one of the many techniques to calculate
//pi to "count" places. This is a variation of
//Ramanujan's formula.
function piCalc(count){
let i = 1n;
count = count + 20n
let x = 3n * (10n ** count);
let pi = x;
while (x > 0) {
x = x * i / ((i + 1n) * 4n);
pi += x / (i + 2n);
i += 2n;
}
pi = pi / (10n ** 20n);
console.log(pi);
return pi;
}
// Note that express error handling middleware should be attached after all
// the other routes and use() calls.
app.use(errors.express);
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log('Hello world listening on port', port);
});