Skip to content

Commit 56e71a0

Browse files
feat: use structured logging on GCF with python 3.7 (#434)
1 parent d13eb61 commit 56e71a0

31 files changed

Lines changed: 615 additions & 298 deletions

packages/google-cloud-logging/google/cloud/logging_v2/client.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -355,13 +355,9 @@ def get_default_handler(self, **kw):
355355
return AppEngineHandler(self, **kw)
356356
elif monitored_resource.type == _GKE_RESOURCE_TYPE:
357357
return ContainerEngineHandler(**kw)
358-
elif (
359-
monitored_resource.type == _GCF_RESOURCE_TYPE
360-
and sys.version_info[0] == 3
361-
and sys.version_info[1] >= 8
362-
):
363-
# Cloud Functions with runtimes > 3.8 supports structured logs on standard out
364-
# 3.7 should use the standard CloudLoggingHandler, which sends logs over the network.
358+
elif monitored_resource.type == _GCF_RESOURCE_TYPE:
359+
# __stdout__ stream required to support structured logging on Python 3.7
360+
kw["stream"] = kw.get("stream", sys.__stdout__)
365361
return StructuredLogHandler(**kw, project_id=self.project)
366362
elif monitored_resource.type == _RUN_RESOURCE_TYPE:
367363
return StructuredLogHandler(**kw, project_id=self.project)

packages/google-cloud-logging/tests/environment/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,3 @@ Test files in `tests/<language>` can inherit from any file in `tests/common` log
7171
| Test Name | Optional Input | Description |
7272
| -------------- | ---------------- | -------------------------------- |
7373
| `simplelog` | `log_name`, `log_text` | Logs a simple text payload |
74-
| `requestlog` | `log_name`, `log_text` | Logs an http request object |
75-
| `stdoutlog` | `log_name`, `log_text` | Logs to standard out |

packages/google-cloud-logging/tests/environment/deployable/go/main.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"log"
2323
"net/http"
2424
"os"
25+
"strings"
2526
"time"
2627

2728
"cloud.google.com/go/compute/metadata"
@@ -207,7 +208,33 @@ func simplelog(args map[string]string) {
207208
logtext = val
208209
}
209210

210-
logger := client.Logger(logname).StandardLogger(logging.Info)
211+
logseverity := logging.Info
212+
if val, ok := args["severity"]; ok {
213+
switch strings.ToUpper(val) {
214+
case "DEFAULT":
215+
logseverity = logging.Default
216+
case "DEBUG":
217+
logseverity = logging.Debug
218+
case "INFO":
219+
logseverity = logging.Info
220+
case "NOTICE":
221+
logseverity = logging.Notice
222+
case "WARNING":
223+
logseverity = logging.Warning
224+
case "ERROR":
225+
logseverity = logging.Error
226+
case "CRITICAL":
227+
logseverity = logging.Critical
228+
case "ALERT":
229+
logseverity = logging.Alert
230+
case "EMERGENCY":
231+
logseverity = logging.Emergency
232+
default:
233+
break
234+
}
235+
}
236+
237+
logger := client.Logger(logname).StandardLogger(logseverity)
211238
logger.Println(logtext)
212239
}
213240

packages/google-cloud-logging/tests/environment/deployable/java/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
java-logging
22
_library
3+
workspace
34
lib.tar
45
*.sw*
56

packages/google-cloud-logging/tests/environment/deployable/java/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
# limitations under the License.
1414

1515
# compile local java-logging library
16-
FROM docker.io/maven AS lib-env
16+
FROM maven:3.8.1 AS lib-env
1717
WORKDIR /app
18-
COPY _library ./java-logging
18+
COPY _library ./
1919
RUN mvn verify --fail-never
2020
RUN mvn -Dmaven.test.skip=true package
2121

2222
# Compile the deployable code.
23-
FROM docker.io/maven AS build-env
23+
FROM maven:3.8.1 AS build-env
2424
WORKDIR /app
2525
COPY pom.xml /app/pom.xml
2626
# copy over compiled library

packages/google-cloud-logging/tests/environment/deployable/java/src/main/java/envtest/deployable/DeployableApplication.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public static void main(String[] args) throws IOException, RuntimeException {
154154
// ****************** GAE, GKE, GCE ******************
155155
// Enable app subscriber for all environments except GCR
156156
Boolean enableSubscriber = Boolean.parseBoolean(System.getenv().getOrDefault("ENABLE_SUBSCRIBER", "false"));
157-
System.out.format("ENV: ENABLE_SUBSCRIBER=true\n");
157+
System.out.format("ENV: ENABLE_SUBSCRIBER=%b\n", enableSubscriber);
158158
if (enableSubscriber) {
159159
// start a pub/sub server and listen for messages
160160
startPubsubSubscription();

packages/google-cloud-logging/tests/environment/deployable/java/src/main/java/envtest/deployable/Snippets.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,51 @@
2222
import com.google.cloud.logging.LoggingOptions;
2323
import com.google.cloud.logging.Payload.StringPayload;
2424
import com.google.cloud.logging.Severity;
25+
import com.google.cloud.logging.MonitoredResourceUtil;
2526
import com.google.logging.type.LogSeverity;
27+
import com.google.cloud.logging.Synchronicity;
2628

2729
public class Snippets {
2830

31+
private Severity getSeverity(String severityString){
32+
Severity severity;
33+
if (severityString.equals("DEBUG")){
34+
severity = Severity.DEBUG;
35+
} else if(severityString.equals("INFO")){
36+
severity = Severity.INFO;
37+
} else if (severityString.equals("NOTICE")){
38+
severity = Severity.NOTICE;
39+
} else if(severityString.equals("WARNING")){
40+
severity = Severity.WARNING;
41+
} else if(severityString.equals("ERROR")){
42+
severity = Severity.ERROR;
43+
} else if(severityString.equals("CRITICAL")){
44+
severity = Severity.CRITICAL;
45+
} else if(severityString.equals("ALERT")){
46+
severity = Severity.ALERT;
47+
} else if(severityString.equals("EMERGENCY")){
48+
severity = Severity.EMERGENCY;
49+
} else {
50+
severity = Severity.DEFAULT;
51+
}
52+
return severity;
53+
}
54+
2955
public void simplelog(Map<String,String> args){
3056
System.out.println("Called Simplelog!");
3157
// pull out arguments
3258
String logText = args.getOrDefault("log_text", "simplelog");
3359
String logName = args.getOrDefault("log_name", "test");
3460
String severityString = args.getOrDefault("severity", "DEFAULT");
3561

62+
// Set severity
63+
Severity severity = getSeverity(severityString);
64+
3665
// Instantiates a client
3766
Logging logging = LoggingOptions.getDefaultInstance().getService();
3867
LogEntry entry =
3968
LogEntry.newBuilder(StringPayload.of(logText))
40-
.setSeverity(Severity.ERROR)
69+
.setSeverity(severity)
4170
.setLogName(logName)
4271
.setResource(MonitoredResource.newBuilder("global").build())
4372
.build();

packages/google-cloud-logging/tests/environment/deployable/java/src/main/java/envtest/deployable/web/DeployableHttpController.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.springframework.web.bind.annotation.RestController;
1919
import org.springframework.web.bind.annotation.GetMapping;
20+
import org.springframework.web.bind.annotation.PostMapping;
2021

2122
import com.google.cloud.MonitoredResource;
2223
import com.google.cloud.logging.LogEntry;
@@ -45,6 +46,17 @@
4546
import java.lang.Thread;
4647
import java.lang.InterruptedException;
4748

49+
import java.util.Base64;
50+
import org.apache.commons.lang3.StringUtils;
51+
import org.springframework.http.HttpStatus;
52+
import org.springframework.http.ResponseEntity;
53+
import org.springframework.web.bind.annotation.RequestBody;
54+
import org.springframework.web.bind.annotation.RequestMapping;
55+
import org.springframework.web.bind.annotation.RequestMethod;
56+
import org.springframework.web.bind.annotation.RestController;
57+
import java.util.Map;
58+
import org.eclipse.jetty.util.B64Code;
59+
import envtest.deployable.DeployableApplication;
4860
/**
4961
* Defines a controller to handle HTTP requests.
5062
*/
@@ -58,4 +70,22 @@ public String helloWorld() {
5870

5971
return message;
6072
}
73+
74+
/**
75+
* This function will be triggered by incomming pub/sub messages from envctl.
76+
* It will then find and execute the requested test snippet, based on the
77+
* contents of the pub/sub payload
78+
*/
79+
@RequestMapping(value = "/", method = RequestMethod.POST)
80+
public ResponseEntity pubsub_receive(@RequestBody Map<String, Object> payload) {
81+
Map<String, Object> pubsubMessage = (Map<String, Object>) payload.get("message");
82+
Map<String, String> args = Collections.emptyMap();
83+
if (pubsubMessage.containsKey("attributes")) {
84+
args = (Map<String, String>) pubsubMessage.get("attributes");
85+
}
86+
String encodedName = (String) pubsubMessage.get("data");
87+
String fnName = B64Code.decode(encodedName, "UTF-8");
88+
DeployableApplication.triggerSnippet(fnName, args);
89+
return new ResponseEntity<>(fnName, HttpStatus.OK);
90+
}
6191
}

packages/google-cloud-logging/tests/environment/deployable/nodejs/app.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ if (process.env.RUNSERVER) {
7575
// Start app server
7676
const PORT = process.env.PORT || 8080;
7777
app.listen(PORT, () =>
78-
console.log(`nodejs-pubsub-tutorial listening on port ${PORT}`)
78+
console.log(`listening on port ${PORT}`)
7979
);
8080
}
8181

@@ -121,12 +121,6 @@ function triggerTest(message) {
121121
? Buffer.from(message.data, 'base64').toString()
122122
: console.error("WARNING: no log function was invoked");
123123

124-
console.log('Fn invoked with attributes, if any: ');
125-
console.log(message.attributes);
126-
127-
if (message.attributes) {
128-
tests[testName](message.attributes['log_name'], message.attributes['log_text']);
129-
} else {
130-
tests[testName]();
131-
}
124+
args = message.attributes ? message.attributes : {};
125+
tests[testName](args);
132126
}

packages/google-cloud-logging/tests/environment/deployable/nodejs/tests.js

Lines changed: 11 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -14,74 +14,29 @@
1414

1515
const {Logging} = require('@google-cloud/logging');
1616
const logging = new Logging();
17-
const defaultRequest = {
18-
method: 'POST',
19-
httpVersion: 'HTTP/1.1',
20-
url: 'https://google.com',
21-
headers: {'x-cloud-trace-context': '1/1;o=1'},
22-
rawHeaders: ['X-Cloud-Trace-Context'],
23-
statusCode: 200,
24-
}
2517

2618
/**
2719
* The following are test functions that can be triggered in each service.
2820
* envctl nodejs <env> trigger simplelog log_name=foo,log_text=bar
2921
*/
30-
var simplelog = function(logname = "my-log", logtext = "hello world" ) {
22+
var simplelog = function(args) {
23+
// set default values
24+
const logname = "logname" in args ? args["logname"] : "my-log";
25+
const logtext = "log_text" in args ? args["log_text"] : "simplelog";
26+
const severity = "severity" in args ? args["severity"] : "ERROR";
27+
3128
const log = logging.log(logname);
3229

33-
const text_entry = log.entry(logtext);
30+
const metadata = {
31+
severity: severity,
32+
};
3433

35-
log.write(text_entry).then(r => console.log(r));
36-
}
37-
38-
/**
39-
* envctl nodejs <env> trigger requestlog log_name=foo,log_text=bar
40-
*/
41-
var requestlog = function(logname = 'my-log', logtext = 'hello world', request) {
42-
if (!request) request = defaultRequest;
43-
const log = logging.log(logname);
44-
const entry = log.entry({httpRequest: request}, logtext);
45-
log.write(entry).then(r => console.log(r));
46-
}
34+
const text_entry = log.entry(metadata, logtext);
4735

48-
/**
49-
* envctl nodejs <env> trigger stdoutlog log_name=foo,log_text=bar
50-
*/
51-
var stdoutlog = function(logname = 'my-log', logtext = 'hello world', request) {
52-
if (!request) request = defaultRequest;
53-
logging.setProjectId().then( res => {
54-
logging.setDetectedResource().then( res => {
55-
const log = logging.logSync(logname);
56-
const meta = {
57-
// Fields all agents lift:
58-
severity: 'WARNING',
59-
httpRequest: request,
60-
labels: {foo: 'bar'},
61-
// Fields not lifted by all agents, e.g. GCF:
62-
insertId: '42',
63-
timestamp: new Date(2021,1,1,1,1,1,1),
64-
resource: {
65-
type: 'global',
66-
labels: {
67-
region: 'my-backyard',
68-
zone: 'twilight',
69-
}
70-
},
71-
// Note: explicit trace declarations override httpRequest header context
72-
trace: 'projects/my-projectid/traces/0679686673a',
73-
spanId: '000000000000004a',
74-
traceSampled: false,
75-
}
76-
const entry = log.entry(meta, logtext);
77-
log.write(entry);
78-
});
79-
});
36+
log.write(text_entry);
8037
}
8138

8239
module.exports={
8340
'simplelog': simplelog,
84-
'stdoutlog': stdoutlog,
85-
'requestlog': requestlog,
8641
}
8742

0 commit comments

Comments
 (0)