Skip to content

Commit 101e56e

Browse files
authored
Logging refactor of JUL + monitored resource construction (googleapis#1847)
Adding support for auto-config of JUL with monitored resource construction on Flex, Standard, GCE and GKE.
1 parent b355f4d commit 101e56e

File tree

15 files changed

+1013
-737
lines changed

15 files changed

+1013
-737
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2017 Google Inc. All Rights Reserved.
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.google.cloud;
18+
19+
import static java.nio.charset.StandardCharsets.UTF_8;
20+
21+
import java.io.BufferedReader;
22+
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.io.InputStreamReader;
25+
import java.net.HttpURLConnection;
26+
import java.net.URL;
27+
28+
/**
29+
* Retrieves Google Cloud project-id and a limited set of instance attributes from Metadata server.
30+
* @see <a href="https://cloud.google.com/compute/docs/storing-retrieving-metadata">
31+
* https://cloud.google.com/compute/docs/storing-retrieving-metadata</a>
32+
*/
33+
public class MetadataConfig {
34+
35+
private static final String METADATA_URL = "http://metadata/computeMetadata/v1/";
36+
37+
private MetadataConfig() {
38+
}
39+
40+
public static String getProjectId() {
41+
return getAttribute("project/project-id");
42+
}
43+
44+
public static String getZone() {
45+
String zoneId = getAttribute("instance/zone");
46+
if (zoneId.contains("/")) {
47+
return zoneId.substring(zoneId.lastIndexOf('/') + 1);
48+
}
49+
return zoneId;
50+
}
51+
52+
public static String getInstanceId() {
53+
return getAttribute("instance/id");
54+
}
55+
56+
public static String getClusterName() {
57+
return getAttribute("instance/cluster-name");
58+
}
59+
60+
private static String getAttribute(String attributeName) {
61+
try {
62+
URL url = new URL(METADATA_URL + attributeName);
63+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
64+
connection.setRequestProperty("Metadata-Flavor", "Google");
65+
InputStream input = connection.getInputStream();
66+
if (connection.getResponseCode() == 200) {
67+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, UTF_8))) {
68+
return reader.readLine();
69+
}
70+
}
71+
} catch (IOException ignore) {
72+
// ignore
73+
}
74+
return null;
75+
}
76+
}

google-cloud-core/src/main/java/com/google/cloud/ServiceOptions.java

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ public static String getDefaultProjectId() {
309309
return projectId != null ? projectId : getGoogleCloudProjectId();
310310
}
311311

312-
protected static String getAppEngineAppId() {
312+
public static String getAppEngineAppId() {
313313
return System.getProperty("com.google.appengine.application.id");
314314
}
315315

@@ -370,23 +370,8 @@ protected static String getGoogleCloudProjectId() {
370370
// ignore
371371
}
372372
}
373-
try {
374-
URL url = new URL("http://metadata/computeMetadata/v1/project/project-id");
375-
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
376-
// TODO replace X-Google-Metadata-Request with:
377-
// connection.setRequestProperty("Metadata-Flavor", "Google");
378-
connection.setRequestProperty("X-Google-Metadata-Request", "True");
379-
InputStream input = connection.getInputStream();
380-
if (connection.getResponseCode() == 200) {
381-
try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, UTF_8))) {
382-
return reader.readLine();
383-
}
384-
}
385-
} catch (IOException ignore) {
386-
// ignore
387-
}
388-
// return null if can't determine
389-
return null;
373+
// return project id from metadata config
374+
return MetadataConfig.getProjectId();
390375
}
391376

392377
private static boolean isWindows() {

google-cloud-examples/src/main/java/com/google/cloud/examples/logging/snippets/LoggingSnippets.java

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.google.cloud.logging.SinkInfo;
4141
import com.google.cloud.logging.SinkInfo.Destination.DatasetDestination;
4242

43+
import com.google.cloud.logging.Synchronicity;
4344
import java.util.ArrayList;
4445
import java.util.HashMap;
4546
import java.util.List;
@@ -454,7 +455,10 @@ public boolean deleteMetricAsync(String metricName)
454455
}
455456

456457
/**
457-
* Example of writing log entries and providing a default log name and monitored resource.
458+
* Example of writing log entries and providing a default log name and monitored
459+
* resource.
460+
* Logging writes are asynchronous by default.
461+
* {@link Logging#setWriteSynchronicity(Synchronicity)} can be used to update the synchronicity.
458462
*/
459463
// [TARGET write(Iterable, WriteOption...)]
460464
// [VARIABLE "my_log_name"]
@@ -465,31 +469,11 @@ public void write(String logName) {
465469
Map<String, Object> jsonMap = new HashMap<>();
466470
jsonMap.put("key", "value");
467471
entries.add(LogEntry.of(JsonPayload.of(jsonMap)));
468-
logging.write(entries,
469-
WriteOption.logName(logName),
470-
WriteOption.resource(MonitoredResource.newBuilder("global").build()));
471-
// [END write]
472-
}
473-
474-
/**
475-
* Example of asynchronously writing log entries and providing a default log name and monitored
476-
* resource.
477-
*/
478-
// [TARGET writeAsync(Iterable, WriteOption...)]
479-
// [VARIABLE "my_log_name"]
480-
public Future<Void> writeAsync(String logName) {
481-
// [START writeAsync]
482-
List<LogEntry> entries = new ArrayList<>();
483-
entries.add(LogEntry.of(StringPayload.of("Entry payload")));
484-
Map<String, Object> jsonMap = new HashMap<>();
485-
jsonMap.put("key", "value");
486-
entries.add(LogEntry.of(JsonPayload.of(jsonMap)));
487-
Future<Void> future = logging.writeAsync(
472+
logging.write(
488473
entries,
489474
WriteOption.logName(logName),
490475
WriteOption.resource(MonitoredResource.newBuilder("global").build()));
491-
// [END writeAsync]
492-
return future;
476+
// [END write]
493477
}
494478

495479
/**

google-cloud-examples/src/test/java/com/google/cloud/examples/logging/snippets/ITLoggingSnippets.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ public void testWriteAndListLogEntries() throws InterruptedException {
158158
public void testWriteAndListLogEntriesAsync() throws ExecutionException, InterruptedException {
159159
String logName = RemoteLoggingHelper.formatForTest("log_name");
160160
String filter = "logName=projects/" + logging.getOptions().getProjectId() + "/logs/" + logName;
161-
loggingSnippets.writeAsync(logName).get();
161+
loggingSnippets.write(logName);
162+
// flush all pending asynchronous writes
163+
logging.flush();
162164
Iterator<LogEntry> iterator = loggingSnippets.listLogEntriesAsync(filter).iterateAll().iterator();
163165
while (Iterators.size(iterator) < 2) {
164166
Thread.sleep(500);

google-cloud-logging/src/main/java/com/google/cloud/logging/GaeFlexLoggingEnhancer.java

Lines changed: 0 additions & 111 deletions
This file was deleted.

google-cloud-logging/src/main/java/com/google/cloud/logging/Logging.java

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,21 @@ public static EntryListOption filter(String filter) {
192192
}
193193
}
194194

195+
/* Sets synchronicity {@link Synchronicity} of logging writes, defaults to asynchronous. */
196+
void setWriteSynchronicity(Synchronicity synchronicity);
197+
198+
/* Retrieves current set synchronicity {@link Synchronicity} of logging writes. */
199+
Synchronicity getWriteSynchronicity();
200+
201+
/**
202+
* Sets flush severity for asynchronous logging writes. Default is ERROR.
203+
* Logs will be immediately written out for entries at or higher than flush severity.
204+
*/
205+
void setFlushSeverity(Severity flushSeverity);
206+
207+
/* Retrieves flush severity for asynchronous logging writes. */
208+
Severity getFlushSeverity();
209+
195210
/**
196211
* Creates a new sink.
197212
*
@@ -646,37 +661,23 @@ ApiFuture<AsyncPage<MonitoredResourceDescriptor>> listMonitoredResourceDescripto
646661
ApiFuture<Boolean> deleteMetricAsync(String metric);
647662

648663
/**
649-
* Writes log entries to Stackdriver Logging. Use {@link WriteOption#logName(String)} to provide a
650-
* log name for those entries that do not specify one. Use
651-
* {@link WriteOption#resource(MonitoredResource)} to provide a monitored resource for those
652-
* entries that do not specify one. Use {@link WriteOption#labels(Map)} to provide some labels
653-
* to be added to every entry in {@code logEntries}.
654-
*
655-
* <p>Example of writing log entries and providing a default log name and monitored resource.
656-
* <pre> {@code
657-
* String logName = "my_log_name";
658-
* List<LogEntry> entries = new ArrayList<>();
659-
* entries.add(LogEntry.of(StringPayload.of("Entry payload")));
660-
* Map<String, Object> jsonMap = new HashMap<>();
661-
* jsonMap.put("key", "value");
662-
* entries.add(LogEntry.of(JsonPayload.of(jsonMap)));
663-
* logging.write(entries,
664-
* WriteOption.logName(logName),
665-
* WriteOption.resource(MonitoredResource.newBuilder("global").build()));
666-
* }</pre>
667-
*
664+
* Flushes any pending asynchronous logging writes.
665+
* Logs are automatically flushed based on time and message count that be configured via
666+
* {@link com.google.api.gax.batching.BatchingSettings},
667+
* Logs are also flushed if at or above flush severity, see {@link #setFlushSeverity}.
668+
* Logging frameworks require support for an explicit flush.
669+
* See usage in the java.util.logging handler{@link LoggingHandler}.
668670
*/
669-
void write(Iterable<LogEntry> logEntries, WriteOption... options);
671+
void flush();
670672

671673
/**
672674
* Sends a request to log entries to Stackdriver Logging. Use {@link WriteOption#logName(String)}
673675
* to provide a log name for those entries that do not specify one. Use
674676
* {@link WriteOption#resource(MonitoredResource)} to provide a monitored resource for those
675677
* entries that do not specify one. Use {@link WriteOption#labels(Map)} to provide some labels
676-
* to be added to every entry in {@code logEntries}. The method returns a {@code ApiFuture} object
677-
* that can be used to wait for the write operation to be completed.
678+
* to be added to every entry in {@code logEntries}.
678679
*
679-
* <p>Example of asynchronously writing log entries and providing a default log name and monitored
680+
* <p>Example of writing log entries and providing a default log name and monitored
680681
* resource.
681682
* <pre> {@code
682683
* String logName = "my_log_name";
@@ -685,14 +686,14 @@ ApiFuture<AsyncPage<MonitoredResourceDescriptor>> listMonitoredResourceDescripto
685686
* Map<String, Object> jsonMap = new HashMap<>();
686687
* jsonMap.put("key", "value");
687688
* entries.add(LogEntry.of(JsonPayload.of(jsonMap)));
688-
* ApiFuture<Void> future = logging.writeAsync(
689+
* logging.write(
689690
* entries,
690691
* WriteOption.logName(logName),
691692
* WriteOption.resource(MonitoredResource.newBuilder("global").build()));
692693
* }</pre>
693694
*
694695
*/
695-
ApiFuture<Void> writeAsync(Iterable<LogEntry> logEntries, WriteOption... options);
696+
void write(Iterable<LogEntry> logEntries, WriteOption... options);
696697

697698
/**
698699
* Lists log entries. This method returns a {@link Page} object that can be used to consume

0 commit comments

Comments
 (0)