Skip to content

Commit 25673fd

Browse files
authored
feat: Add an ability to delete logs based on project, folder, organization or billing account resource names (#731)
* fets: Add an ability to delete logs based on project, folder, organization or billing account resource names * Add an ability to make async and non-async delete calls in tests * Add proper validations with meaningful error message and also fix test name typo * Address PR comments * Move NPE validations into deleteLogAsync from getLogName
1 parent 1996cb4 commit 25673fd

File tree

4 files changed

+143
-5
lines changed

4 files changed

+143
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- see http://www.mojohaus.org/clirr-maven-plugin/examples/ignored-differences.html -->
3+
<differences>
4+
<difference>
5+
<differenceType>7012</differenceType>
6+
<className>com/google/cloud/logging/Logging</className>
7+
<method>* deleteLog*(java.lang.String, com.google.cloud.logging.LogDestinationName)</method>
8+
</difference>
9+
</differences>

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

+57
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,63 @@ default ApiFuture<AsyncPage<String>> listLogsAsync(ListOption... options) {
597597
*/
598598
boolean deleteLog(String log);
599599

600+
/**
601+
* Deletes a log and all its log entries for given log destination (see 'logName' parameter in
602+
* https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry). The log will reappear if
603+
* new entries are written to it.
604+
*
605+
* <p>Example of deleting a log by folder destination.
606+
*
607+
* <pre>
608+
* {
609+
* &#64;code
610+
* String logName = "my_log_name";
611+
* String folder = "my_folder";
612+
* boolean deleted = logging.deleteLog(logName, LogDestinationName.folder(folder));
613+
* if (deleted) {
614+
* // the log was deleted
615+
* } else {
616+
* // the log was not found
617+
* }
618+
* }
619+
* </pre>
620+
*
621+
* @return {@code true} if the log was deleted, {@code false} if it was not found
622+
*/
623+
default boolean deleteLog(String log, LogDestinationName destination) {
624+
throw new UnsupportedOperationException(
625+
"method deleteLog() does not have default implementation");
626+
}
627+
628+
/**
629+
* Sends a request for deleting a log and all its log entries for given log destination (see
630+
* 'logName' parameter in https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry).
631+
* This method returns a {@code ApiFuture} object to consume the result. {@link ApiFuture#get()}
632+
* returns {@code true} if the log was deleted, {@code false} if it was not found.
633+
*
634+
* <p>Example of asynchronously deleting a log by folder destination.
635+
*
636+
* <pre>
637+
* {
638+
* &#64;code
639+
* String logName = "my_log_name";
640+
* String folder = "my_folder";
641+
* ApiFuture<Boolean> future = logging.deleteLogAsync(logName, LogDestinationName.folder(folder));
642+
* // ...
643+
* boolean deleted = future.get();
644+
* if (deleted) {
645+
* // the log was deleted
646+
* } else {
647+
* // the log was not found
648+
* }
649+
* }
650+
* </pre>
651+
*/
652+
default ApiFuture<Boolean> deleteLogAsync(String log, LogDestinationName destination) {
653+
throw new UnsupportedOperationException(
654+
"method deleteLogAsync() does not have default implementation");
655+
}
656+
600657
/**
601658
* Sends a request for deleting a log and all its log entries. This method returns a {@code
602659
* ApiFuture} object to consume the result. {@link ApiFuture#get()} returns {@code true} if the

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

+19-5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.google.cloud.logging.spi.v2.LoggingRpc;
4141
import com.google.common.annotations.VisibleForTesting;
4242
import com.google.common.base.Function;
43+
import com.google.common.base.Preconditions;
4344
import com.google.common.base.Throwables;
4445
import com.google.common.collect.ImmutableList;
4546
import com.google.common.collect.Iterables;
@@ -440,14 +441,27 @@ public ApiFuture<AsyncPage<String>> listLogsAsync(ListOption... options) {
440441
}
441442

442443
public boolean deleteLog(String log) {
443-
return get(deleteLogAsync(log));
444+
return get(deleteLogAsync(log, null));
445+
}
446+
447+
@Override
448+
public boolean deleteLog(String log, LogDestinationName destination) {
449+
return get(deleteLogAsync(log, destination));
444450
}
445451

446452
public ApiFuture<Boolean> deleteLogAsync(String log) {
447-
DeleteLogRequest request =
448-
DeleteLogRequest.newBuilder()
449-
.setLogName(LogName.ofProjectLogName(getOptions().getProjectId(), log).toString())
450-
.build();
453+
return deleteLogAsync(log, null);
454+
}
455+
456+
@Override
457+
public ApiFuture<Boolean> deleteLogAsync(String log, LogDestinationName destination) {
458+
Preconditions.checkNotNull(log, "log parameter cannot be null");
459+
String projectId = getOptions().getProjectId();
460+
if (destination == null) {
461+
Preconditions.checkNotNull(projectId, "projectId parameter cannot be null");
462+
}
463+
LogName name = getLogName(projectId, log, destination);
464+
DeleteLogRequest request = DeleteLogRequest.newBuilder().setLogName(name.toString()).build();
451465
return transform(rpc.delete(request), EMPTY_TO_BOOLEAN_FUNCTION);
452466
}
453467

google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingImplTest.java

+58
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,50 @@ public void testDeleteLogAsync() throws ExecutionException, InterruptedException
17771777
assertTrue(logging.deleteLogAsync(LOG_NAME).get());
17781778
}
17791779

1780+
@Test
1781+
public void testDeleteLogBillingDestination() throws ExecutionException, InterruptedException {
1782+
testDeleteByDestination(
1783+
LOG_NAME, LOG_NAME_BILLING_PATH, LogDestinationName.billingAccount(BILLING), false);
1784+
}
1785+
1786+
@Test
1787+
public void testDeleteLogBillingDestinationAsync()
1788+
throws ExecutionException, InterruptedException {
1789+
testDeleteByDestination(
1790+
LOG_NAME, LOG_NAME_BILLING_PATH, LogDestinationName.billingAccount(BILLING), true);
1791+
}
1792+
1793+
@Test
1794+
public void testDeleteLogFolderDestination() throws ExecutionException, InterruptedException {
1795+
testDeleteByDestination(
1796+
LOG_NAME, LOG_NAME_FOLDER_PATH, LogDestinationName.folder(FOLDER), false);
1797+
}
1798+
1799+
@Test
1800+
public void testDeleteLogFolderDestinationAsync()
1801+
throws ExecutionException, InterruptedException {
1802+
testDeleteByDestination(
1803+
LOG_NAME, LOG_NAME_FOLDER_PATH, LogDestinationName.folder(FOLDER), true);
1804+
}
1805+
1806+
@Test
1807+
public void testDeleteLogOrgDestination() throws ExecutionException, InterruptedException {
1808+
testDeleteByDestination(
1809+
LOG_NAME, LOG_NAME_ORGANIZATION_PATH, LogDestinationName.organization(ORGANIZATION), false);
1810+
}
1811+
1812+
@Test
1813+
public void testDeleteLogOrgDestinationAsync() throws ExecutionException, InterruptedException {
1814+
testDeleteByDestination(
1815+
LOG_NAME, LOG_NAME_ORGANIZATION_PATH, LogDestinationName.organization(ORGANIZATION), true);
1816+
}
1817+
1818+
@Test
1819+
public void testDeleteLogProjectDestination() throws ExecutionException, InterruptedException {
1820+
testDeleteByDestination(
1821+
LOG_NAME, LOG_NAME_PROJECT_PATH, LogDestinationName.project(PROJECT), false);
1822+
}
1823+
17801824
@Test
17811825
public void testDeleteLogAsync_Null() throws ExecutionException, InterruptedException {
17821826
DeleteLogRequest request =
@@ -2241,6 +2285,20 @@ public void run() {
22412285
assertSame(0, exceptions.get());
22422286
}
22432287

2288+
private void testDeleteByDestination(
2289+
String logId, String logName, LogDestinationName destination, boolean useAsyncDelete)
2290+
throws ExecutionException, InterruptedException {
2291+
DeleteLogRequest request = DeleteLogRequest.newBuilder().setLogName(logName).build();
2292+
ApiFuture<Empty> response = ApiFutures.immediateFuture(Empty.getDefaultInstance());
2293+
EasyMock.expect(loggingRpcMock.delete(request)).andReturn(response);
2294+
EasyMock.replay(rpcFactoryMock, loggingRpcMock);
2295+
logging = options.getService();
2296+
assertTrue(
2297+
useAsyncDelete
2298+
? logging.deleteLogAsync(logId, destination).get()
2299+
: logging.deleteLog(logId, destination));
2300+
}
2301+
22442302
private void testWriteLogEntriesWithDestination(
22452303
String projectId, String fullLogNamePath, LogDestinationName destination) {
22462304
Map<String, String> labels = ImmutableMap.of("key", "value");

0 commit comments

Comments
 (0)