Skip to content

Commit 53481bd

Browse files
fix: fix samples region tags and test flakiness (#680)
* chore: fix list logs snippet define timestamp filter in UTC time. change filter to last minute entries. enforce closing logging client at the end of the snippet. apply formatting. * chore: enforce closing logging client in samples force closing logging client at the end of the snippet * fix: fix region tag for LogEntryWriteHttpRequest change logging_write_request_entry to logging_write_log_entry_advanced * fix: add snippet for missing logging_write_log_entry * chore: move testListLogNamesSample to separate test * fix: fix samples testing add closing logging client at the end of the test unit add multiple attempts to clean log after each test print debug info in a case cleaning fails * fix: add test for WriteLogEntry remove unused textPayload from the snippet * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 9db233f commit 53481bd

File tree

8 files changed

+216
-68
lines changed

8 files changed

+216
-68
lines changed

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,27 @@ LogEntry firstEntry = LogEntry.newBuilder(StringPayload.of("message"))
166166
logging.write(Collections.singleton(firstEntry));
167167
```
168168

169+
The library supports writing log entries synchronously and asynchronously.
170+
In the synchronous mode each call to `write()` method results in a consequent call to Logging API to write a log entry.
171+
In the asynchronous mode the call(s) to Logging API takes place asynchronously and few calls to `write()` method may be batched together to compose a single call to Logging API.
172+
The default mode of writing is asynchronous.
173+
It can be configured in the `java.util.logging` handler [configuration file](https://cloud.google.com/logging/docs/setup/java#javautillogging_configuration):
174+
175+
```
176+
com.google.cloud.logging.LoggingHandler.synchronicity=SYNC
177+
```
178+
179+
or in the code after initiating an instance of `Logging` by calling:
180+
181+
```java
182+
logging.setWriteSynchronicity(Synchronicity.SYNC);
183+
```
184+
185+
NOTE:
186+
> Writing log entries asynchronously in some Google Cloud managed environments (e.g. Cloud Functions)
187+
> may lead to unexpected results such as absense of expected log entries or abnormal program execution.
188+
> To avoid these unexpected results, it is recommended to use synchronous mode.
189+
169190
#### Listing log entries
170191

171192
With Logging you can also list log entries that have been previously written. Add the following
@@ -236,6 +257,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-logging/tree/
236257
| Log Entry Write Http Request | [source code](https://github.com/googleapis/java-logging/blob/master/samples/snippets/src/main/java/com/example/logging/LogEntryWriteHttpRequest.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/LogEntryWriteHttpRequest.java) |
237258
| Quickstart Sample | [source code](https://github.com/googleapis/java-logging/blob/master/samples/snippets/src/main/java/com/example/logging/QuickstartSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/QuickstartSample.java) |
238259
| Tail Log Entries | [source code](https://github.com/googleapis/java-logging/blob/master/samples/snippets/src/main/java/com/example/logging/TailLogEntries.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/TailLogEntries.java) |
260+
| Write Log Entry | [source code](https://github.com/googleapis/java-logging/blob/master/samples/snippets/src/main/java/com/example/logging/WriteLogEntry.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/WriteLogEntry.java) |
239261
| Quickstart | [source code](https://github.com/googleapis/java-logging/blob/master/samples/snippets/src/main/java/com/example/logging/jul/Quickstart.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/jul/Quickstart.java) |
240262
| Example Enhancer | [source code](https://github.com/googleapis/java-logging/blob/master/samples/snippets/src/main/java/com/example/logging/jul/enhancers/ExampleEnhancer.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/jul/enhancers/ExampleEnhancer.java) |
241263

samples/snippets/src/main/java/com/example/logging/ListLogEntries.java

+26-24
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.text.DateFormat;
2626
import java.text.SimpleDateFormat;
2727
import java.util.Calendar;
28+
import java.util.TimeZone;
2829

2930
public class ListLogEntries {
3031

@@ -33,33 +34,34 @@ public static void main(String[] args) throws Exception {
3334
// or provide it as an argument.
3435
String logName = args.length > 0 ? args[0] : "test-log";
3536

36-
LoggingOptions options = LoggingOptions.getDefaultInstance();
37-
Logging logging = options.getService();
37+
try (Logging logging = LoggingOptions.getDefaultInstance().getService()) {
3838

39-
// When composing a filter, using indexed fields, such as timestamp, resource.type, logName and
40-
// others can help accelerate the results
41-
// Full list of indexed fields here:
42-
// https://cloud.google.com/logging/docs/view/advanced-queries#finding-quickly
43-
// This sample restrict the results to only last hour to minimize number of API calls
44-
Calendar calendar = Calendar.getInstance();
45-
calendar.add(Calendar.HOUR, -1);
46-
DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
47-
String logFilter =
48-
"logName=projects/"
49-
+ options.getProjectId()
50-
+ "/logs/"
51-
+ logName
52-
+ " AND timestamp>=\""
53-
+ rfc3339.format(calendar.getTime())
54-
+ "\"";
39+
// When composing a filter, using indexed fields, such as timestamp, resource.type, logName
40+
// and
41+
// others can help accelerate the results
42+
// Full list of indexed fields here:
43+
// https://cloud.google.com/logging/docs/view/advanced-queries#finding-quickly
44+
// This sample restrict the results to only last minute to minimize number of API calls
45+
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
46+
calendar.add(Calendar.MINUTE, -1);
47+
DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
48+
String logFilter =
49+
"logName=projects/"
50+
+ logging.getOptions().getProjectId()
51+
+ "/logs/"
52+
+ logName
53+
+ " AND timestamp>=\""
54+
+ rfc3339.format(calendar.getTime())
55+
+ "\"";
5556

56-
// List all log entries
57-
Page<LogEntry> entries = logging.listLogEntries(EntryListOption.filter(logFilter));
58-
while (entries != null) {
59-
for (LogEntry logEntry : entries.iterateAll()) {
60-
System.out.println(logEntry);
57+
// List all log entries
58+
Page<LogEntry> entries = logging.listLogEntries(EntryListOption.filter(logFilter));
59+
while (entries != null) {
60+
for (LogEntry logEntry : entries.iterateAll()) {
61+
System.out.println(logEntry);
62+
}
63+
entries = entries.getNextPage();
6164
}
62-
entries = entries.getNextPage();
6365
}
6466
}
6567
}

samples/snippets/src/main/java/com/example/logging/ListLogs.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ public class ListLogs {
2525

2626
public static void main(String... args) throws Exception {
2727

28-
LoggingOptions options = LoggingOptions.getDefaultInstance();
29-
Logging logging = options.getService();
28+
try (Logging logging = LoggingOptions.getDefaultInstance().getService()) {
3029

31-
// List all log names
32-
Page<String> logNames = logging.listLogs();
33-
while (logNames != null) {
34-
for (String logName : logNames.iterateAll()) {
35-
System.out.println(logName);
30+
// List all log names
31+
Page<String> logNames = logging.listLogs();
32+
while (logNames != null) {
33+
for (String logName : logNames.iterateAll()) {
34+
System.out.println(logName);
35+
}
36+
logNames = logNames.getNextPage();
3637
}
37-
logNames = logNames.getNextPage();
3838
}
3939
}
4040
}

samples/snippets/src/main/java/com/example/logging/LogEntryWriteHttpRequest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.example.logging;
1818

19-
// [START logging_write_request_entry]
19+
// [START logging_write_log_entry_advanced]
2020
import com.google.cloud.MonitoredResource;
2121
import com.google.cloud.logging.HttpRequest;
2222
import com.google.cloud.logging.LogEntry;
@@ -61,4 +61,4 @@ public static void createLogEntryRequest(String logName, String payLoad, HttpReq
6161
}
6262
}
6363
}
64-
// [END logging_write_request_entry]
64+
// [END logging_write_log_entry_advanced]

samples/snippets/src/main/java/com/example/logging/QuickstartSample.java

+15-18
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,24 @@ public class QuickstartSample {
3737

3838
/** Expects a new or existing Cloud log name as the first argument. */
3939
public static void main(String... args) throws Exception {
40-
41-
// Instantiates a client
42-
Logging logging = LoggingOptions.getDefaultInstance().getService();
43-
4440
// The name of the log to write to
4541
String logName = args[0]; // "my-log";
42+
String textPayload = "Hello, world!";
4643

47-
// The data to write to the log
48-
String text = "Hello, world!";
49-
50-
LogEntry entry =
51-
LogEntry.newBuilder(StringPayload.of(text))
52-
.setSeverity(Severity.ERROR)
53-
.setLogName(logName)
54-
.setResource(MonitoredResource.newBuilder("global").build())
55-
.build();
56-
57-
// Writes the log entry asynchronously
58-
logging.write(Collections.singleton(entry));
59-
60-
System.out.printf("Logged: %s%n", text);
44+
// Instantiates a client
45+
try (Logging logging = LoggingOptions.getDefaultInstance().getService()) {
46+
47+
LogEntry entry =
48+
LogEntry.newBuilder(StringPayload.of(textPayload))
49+
.setSeverity(Severity.ERROR)
50+
.setLogName(logName)
51+
.setResource(MonitoredResource.newBuilder("global").build())
52+
.build();
53+
54+
// Writes the log entry asynchronously
55+
logging.write(Collections.singleton(entry));
56+
}
57+
System.out.printf("Logged: %s%n", textPayload);
6158
}
6259
}
6360
// [END logging_quickstart]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2021 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+
* http://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+
package com.example.logging;
18+
19+
// [START logging_write_log_entry]
20+
import com.google.cloud.MonitoredResource;
21+
import com.google.cloud.logging.LogEntry;
22+
import com.google.cloud.logging.Logging;
23+
import com.google.cloud.logging.LoggingOptions;
24+
import com.google.cloud.logging.Payload.JsonPayload;
25+
import com.google.cloud.logging.Severity;
26+
import com.google.common.collect.ImmutableMap;
27+
import java.util.Collections;
28+
import java.util.Map;
29+
30+
public class WriteLogEntry {
31+
32+
public static void main(String[] args) throws Exception {
33+
// TODO(developer): Optionally provide the logname as an argument
34+
String logName = args.length > 0 ? args[0] : "test-log";
35+
36+
// Instantiates a client
37+
try (Logging logging = LoggingOptions.getDefaultInstance().getService()) {
38+
Map<String, String> payload =
39+
ImmutableMap.of(
40+
"name", "King Arthur", "quest", "Find the Holy Grail", "favorite_color", "Blue");
41+
LogEntry entry =
42+
LogEntry.newBuilder(JsonPayload.of(payload))
43+
.setSeverity(Severity.INFO)
44+
.setLogName(logName)
45+
.setResource(MonitoredResource.newBuilder("global").build())
46+
.build();
47+
48+
logging.write(Collections.singleton(entry));
49+
}
50+
System.out.printf("Wrote to %s\n", logName);
51+
}
52+
}
53+
// [END logging_write_log_entry]

samples/snippets/src/test/java/com/example/logging/LoggingIT.java

+36-16
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
import java.io.PrintStream;
3131
import java.util.Collections;
3232
import org.junit.After;
33+
import org.junit.AfterClass;
3334
import org.junit.Before;
35+
import org.junit.BeforeClass;
3436
import org.junit.Test;
3537
import org.junit.runner.RunWith;
3638
import org.junit.runners.JUnit4;
@@ -41,16 +43,38 @@
4143
public class LoggingIT {
4244

4345
private static final String TEST_LOG = formatForTest("test-log");
44-
private static final String GOOGLEAPIS_AUDIT_LOGNAME = "cloudaudit.googleapis.com%2Factivity";
4546
private static final String STRING_PAYLOAD = "Hello, world!";
4647
private static final String STRING_PAYLOAD2 = "Hello world again";
4748

4849
private ByteArrayOutputStream bout;
4950
private PrintStream out;
50-
private Logging logging = LoggingOptions.getDefaultInstance().getService();
51+
private static Logging logging;
52+
53+
private void deleteLog(String logName) throws InterruptedException {
54+
int deleteAttempts = 0;
55+
int allowedDeleteAttempts = 5;
56+
boolean deleted = false;
57+
while (!deleted && deleteAttempts < allowedDeleteAttempts) {
58+
deleted = logging.deleteLog(logName);
59+
deleteAttempts++;
60+
if (!deleted) {
61+
Thread.sleep(1000);
62+
}
63+
}
64+
if (!deleted) {
65+
System.err.println(
66+
"Failed to clean up log entries after 5 attempts. Following tests may be flaky...");
67+
}
68+
}
5169

52-
private void deleteLog(String logName) {
53-
logging.deleteLog(logName);
70+
@BeforeClass
71+
public static void startup() {
72+
logging = LoggingOptions.getDefaultInstance().getService();
73+
}
74+
75+
@AfterClass
76+
public static void shutDown() throws Exception {
77+
logging.close();
5478
}
5579

5680
@Before
@@ -61,13 +85,13 @@ public void setUp() {
6185
}
6286

6387
@After
64-
public void tearDown() {
88+
public void tearDown() throws Exception {
6589
// Clean up created logs
6690
deleteLog(TEST_LOG);
6791
System.setOut(null);
6892
}
6993

70-
@Test
94+
@Test(timeout = 60000)
7195
public void testQuickstartSample() throws Exception {
7296
QuickstartSample.main(TEST_LOG);
7397
String got = bout.toString();
@@ -116,7 +140,7 @@ public void testWriteLogHttpRequestSample() throws Exception {
116140
String[] args = new String[] {TEST_LOG};
117141
while (bout.toString().isEmpty()) {
118142
ListLogEntries.main(args);
119-
Thread.sleep(5000);
143+
Thread.sleep(1000);
120144
}
121145

122146
// check log entry contain request data
@@ -125,14 +149,10 @@ public void testWriteLogHttpRequestSample() throws Exception {
125149
}
126150

127151
@Test(timeout = 60000)
128-
public void testListLogNamesSample() throws Exception {
129-
ListLogs.main();
130-
// Check for mocked STDOUT having data
131-
while (bout.toString().isEmpty()) {
132-
Thread.sleep(5000);
133-
}
134-
135-
assertThat(bout.toString().contains(GOOGLEAPIS_AUDIT_LOGNAME)).isTrue();
152+
public void testWriteLogEntrySample() throws Exception {
153+
WriteLogEntry.main(new String[] {TEST_LOG});
154+
String got = bout.toString();
155+
assertThat(got).contains(String.format("Wrote to %s", TEST_LOG));
136156
}
137157

138158
@Test(timeout = 60000)
@@ -153,7 +173,7 @@ public void testTailLogEntriesSample() throws Exception {
153173
logging.write(Collections.singleton(logEntry));
154174
}
155175
} catch (Exception t) {
156-
System.out.println("Failed to write log entry:\n" + t);
176+
System.err.println("Failed to write log entry:\n" + t);
157177
}
158178
};
159179
Thread thread = new Thread(task);

0 commit comments

Comments
 (0)