Skip to content

Commit b0b6f58

Browse files
Changed streamRecentLogs() to block and return log entries as a list. Changed Gradle cfLogs task and Maven cf:logs goal to tail streaming logs. Added Gradle cfRecentLogs task and Maven cf:recentLogs goal.
1 parent 1a45dcb commit b0b6f58

File tree

16 files changed

+419
-144
lines changed

16 files changed

+419
-144
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,12 @@
11
package org.cloudfoundry.client.lib;
22

3-
import java.util.Date;
3+
import org.cloudfoundry.client.lib.domain.ApplicationLog;
44

55
public interface ApplicationLogListener {
6-
void onMessage(ApplicationLog log);
7-
8-
void onComplete();
6+
void onMessage(ApplicationLog log);
97

10-
void onError(Throwable exception);
11-
12-
public static class ApplicationLog {
13-
private String appId;
14-
private String message;
15-
private Date timestamp;
16-
private MessageType messageType;
17-
private String sourceName;
18-
19-
public ApplicationLog(String appId, String message, Date timestamp, MessageType messageType, String sourceName) {
20-
this.appId = appId;
21-
this.message = message;
22-
this.timestamp = timestamp;
23-
this.messageType = messageType;
24-
this.sourceName = sourceName;
25-
}
8+
void onComplete();
269

27-
public String getAppId() {
28-
return appId;
29-
}
10+
void onError(Throwable exception);
3011

31-
public String getMessage() {
32-
return message;
33-
}
34-
35-
public Date getTimestamp() {
36-
return timestamp;
37-
}
38-
39-
public MessageType getMessageType() {
40-
return messageType;
41-
}
42-
43-
public String getSourceName() {
44-
return sourceName;
45-
}
46-
47-
@Override
48-
public String toString() {
49-
return String.format("%s [%s] %s (%s, %s)", appId, timestamp, message, messageType, sourceName);
50-
}
51-
}
52-
53-
public enum MessageType { STDOUT, STDERR }
5412
}

Diff for: cloudfoundry-client-lib/src/main/java/org/cloudfoundry/client/lib/CloudFoundryClient.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818

1919
import java.io.File;
2020
import java.io.IOException;
21-
import java.io.InputStream;
2221
import java.net.URL;
2322
import java.util.List;
2423
import java.util.Map;
2524
import java.util.UUID;
2625

2726
import org.cloudfoundry.client.lib.archive.ApplicationArchive;
27+
import org.cloudfoundry.client.lib.domain.ApplicationLog;
2828
import org.cloudfoundry.client.lib.domain.ApplicationStats;
2929
import org.cloudfoundry.client.lib.domain.CloudApplication;
3030
import org.cloudfoundry.client.lib.domain.CloudApplication.DebugMode;
@@ -318,7 +318,7 @@ public void updateApplicationEnv(String appName, List<String> env) {
318318
}
319319

320320
/**
321-
* @deprecated use {@link #streamLogs(String, ApplicationLogListener)} or {@link #streamRecentLogs(String, ApplicationLogListener)}
321+
* @deprecated use {@link #streamLogs(String, ApplicationLogListener)} or {@link #getRecentLogs(String)}
322322
*/
323323
public Map<String, String> getLogs(String appName) {
324324
return cc.getLogs(appName);
@@ -328,10 +328,13 @@ public StreamingLogToken streamLogs(String appName, ApplicationLogListener liste
328328
return cc.streamLogs(appName, listener);
329329
}
330330

331-
public StreamingLogToken streamRecentLogs(String appName, ApplicationLogListener listener) {
332-
return cc.streamRecentLogs(appName, listener);
333-
}
334-
331+
public List<ApplicationLog> getRecentLogs(String appName) {
332+
return cc.getRecentLogs(appName);
333+
}
334+
335+
/**
336+
* @deprecated use {@link #streamLogs(String, ApplicationLogListener)} or {@link #getRecentLogs(String)}
337+
*/
335338
public Map<String, String> getCrashLogs(String appName) {
336339
return cc.getCrashLogs(appName);
337340
}

Diff for: cloudfoundry-client-lib/src/main/java/org/cloudfoundry/client/lib/CloudFoundryOperations.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.Map;
2424

2525
import org.cloudfoundry.client.lib.archive.ApplicationArchive;
26+
import org.cloudfoundry.client.lib.domain.ApplicationLog;
2627
import org.cloudfoundry.client.lib.domain.ApplicationStats;
2728
import org.cloudfoundry.client.lib.domain.CloudApplication;
2829
import org.cloudfoundry.client.lib.domain.CloudDomain;
@@ -354,7 +355,7 @@ public void createApplication(String appName, Staging staging, Integer disk, Int
354355
* @param appName name of the application
355356
* @return a Map containing the logs. The logs will be returned with the path to the log file used as the key and
356357
* the full content of the log file will be returned as a String value for the corresponding key.
357-
* @deprecated Use {@link #streamLogs(String, ApplicationLogListener)} or {@link #streamRecentLogs(String, ApplicationLogListener)}
358+
* @deprecated Use {@link #streamLogs(String, ApplicationLogListener)} or {@link #getRecentLogs(String)}
358359
*/
359360
Map<String, String> getLogs(String appName);
360361

@@ -373,14 +374,12 @@ public void createApplication(String appName, Staging staging, Integer disk, Int
373374
/**
374375
* Stream recent log entries.
375376
*
376-
* Stream logs that were recently produced for an app. Once recent log entries have been notified,
377-
* the listener will not be notified any more.
378-
*
379-
* @param appName the name of the application
380-
* @param listener listener object to be notified
381-
* @return token than can be used to cancel listening for logs
377+
* Stream logs that were recently produced for an app.
378+
*
379+
* @param appName the name of the application
380+
* @return the list of recent log entries
382381
*/
383-
StreamingLogToken streamRecentLogs(String appName, ApplicationLogListener listener);
382+
List<ApplicationLog> getRecentLogs(String appName);
384383

385384
/**
386385
* Get logs from most recent crash of the deployed application. The logs
@@ -390,6 +389,7 @@ public void createApplication(String appName, Staging staging, Integer disk, Int
390389
* @param appName name of the application
391390
* @return a Map containing the logs. The logs will be returned with the path to the log file used as the key and
392391
* the full content of the log file will be returned as a String value for the corresponding key.
392+
* @deprecated Use {@link #streamLogs(String, ApplicationLogListener)} or {@link #getRecentLogs(String)}
393393
*/
394394
Map<String, String> getCrashLogs(String appName);
395395

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.cloudfoundry.client.lib.domain;
2+
3+
4+
import java.util.Date;
5+
6+
public class ApplicationLog implements Comparable<ApplicationLog> {
7+
public enum MessageType {STDOUT, STDERR}
8+
9+
private String appId;
10+
private String message;
11+
private Date timestamp;
12+
private MessageType messageType;
13+
private String sourceName;
14+
private String sourceId;
15+
16+
public ApplicationLog(String appId, String message, Date timestamp, MessageType messageType, String sourceName, String sourceId) {
17+
this.appId = appId;
18+
this.message = message;
19+
this.timestamp = timestamp;
20+
this.messageType = messageType;
21+
this.sourceName = sourceName;
22+
this.sourceId = sourceId;
23+
}
24+
25+
public String getAppId() {
26+
return appId;
27+
}
28+
29+
public String getMessage() {
30+
return message;
31+
}
32+
33+
public Date getTimestamp() {
34+
return timestamp;
35+
}
36+
37+
public MessageType getMessageType() {
38+
return messageType;
39+
}
40+
41+
public String getSourceName() {
42+
return sourceName;
43+
}
44+
45+
public String getSourceId() {
46+
return sourceId;
47+
}
48+
49+
public int compareTo(ApplicationLog o) {
50+
return timestamp.compareTo(o.timestamp);
51+
}
52+
53+
@Override
54+
public String toString() {
55+
return String.format("%s [%s] %s (%s, %s)", appId, timestamp, message, messageType, sourceName);
56+
}
57+
}

Diff for: cloudfoundry-client-lib/src/main/java/org/cloudfoundry/client/lib/rest/CloudControllerClient.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.cloudfoundry.client.lib.StreamingLogToken;
3232
import org.cloudfoundry.client.lib.UploadStatusCallback;
3333
import org.cloudfoundry.client.lib.archive.ApplicationArchive;
34+
import org.cloudfoundry.client.lib.domain.ApplicationLog;
3435
import org.cloudfoundry.client.lib.domain.ApplicationStats;
3536
import org.cloudfoundry.client.lib.domain.CloudApplication;
3637
import org.cloudfoundry.client.lib.domain.CloudDomain;
@@ -146,9 +147,9 @@ void createApplication(String appName, Staging staging, Integer disk, Integer me
146147

147148
StreamingLogToken streamLogs(String appName, ApplicationLogListener listener);
148149

149-
StreamingLogToken streamRecentLogs(String appName, ApplicationLogListener listener);
150+
List<ApplicationLog> getRecentLogs(String appName);
150151

151-
Map<String, String> getCrashLogs(String appName);
152+
Map<String, String> getCrashLogs(String appName);
152153

153154
String getFile(String appName, int instanceIndex, String filePath, int startPosition, int endPosition);
154155

Diff for: cloudfoundry-client-lib/src/main/java/org/cloudfoundry/client/lib/rest/CloudControllerClientImpl.java

+67-32
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.cloudfoundry.client.lib.archive.ApplicationArchive;
5656
import org.cloudfoundry.client.lib.archive.DirectoryApplicationArchive;
5757
import org.cloudfoundry.client.lib.archive.ZipApplicationArchive;
58+
import org.cloudfoundry.client.lib.domain.ApplicationLog;
5859
import org.cloudfoundry.client.lib.domain.ApplicationStats;
5960
import org.cloudfoundry.client.lib.domain.CloudApplication;
6061
import org.cloudfoundry.client.lib.domain.CloudDomain;
@@ -222,15 +223,24 @@ public Map<String, String> getLogs(String appName) {
222223
String instance = String.valueOf(0);
223224
return doGetLogs(urlPath, appName, instance);
224225
}
225-
226-
public StreamingLogToken streamRecentLogs(String appName, ApplicationLogListener listener) {
227-
return streamLoggregatorLogs(appName, listener, true);
226+
227+
public List<ApplicationLog> getRecentLogs(String appName) {
228+
AccumulatingApplicationLogListener listener = new AccumulatingApplicationLogListener();
229+
streamLoggregatorLogs(appName, listener, true);
230+
synchronized (listener) {
231+
try {
232+
listener.wait();
233+
} catch (InterruptedException e) {
234+
// return any captured logs
235+
}
236+
}
237+
return listener.getLogs();
238+
}
239+
240+
public StreamingLogToken streamLogs(String appName, ApplicationLogListener listener) {
241+
return streamLoggregatorLogs(appName, listener, false);
228242
}
229243

230-
public StreamingLogToken streamLogs(String appName, ApplicationLogListener listener) {
231-
return streamLoggregatorLogs(appName, listener, false);
232-
}
233-
234244
public Map<String, String> getCrashLogs(String appName) {
235245
String urlPath = getFileUrlPath();
236246
CrashesInfo crashes = getCrashes(appName);
@@ -1613,31 +1623,56 @@ private UUID getAppId(String appName) {
16131623
return guid;
16141624
}
16151625

1616-
private StreamingLogToken streamLoggregatorLogs(String appName, ApplicationLogListener listener, boolean recent) {
1617-
ClientEndpointConfig.Configurator configurator = new ClientEndpointConfig.Configurator() {
1618-
public void beforeRequest(Map<String,List<String>> headers) {
1619-
if (token != null) {
1620-
headers.put(AUTHORIZATION_HEADER_KEY, Arrays.asList(getAuthorizationHeader()));
1621-
}
1622-
}
1623-
};
1624-
1625-
UUID appId = getAppId(appName);
1626-
CloudInfo cloudInfo = getInfo();
1627-
String mode = recent ? "dump" : "tail";
1628-
URI loggregatorUri = loggregatorUriTemplate.expand(cloudInfo.getLoggregatorEndpoint(), mode, appId);
1629-
try {
1630-
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
1631-
ClientEndpointConfig config = ClientEndpointConfig.Builder.create().configurator(configurator).build();
1632-
Session session = container.connectToServer(new LoggregatorEndpoint(listener), config, loggregatorUri);
1633-
return new StreamingLogTokenImpl(session);
1634-
} catch (DeploymentException e) {
1635-
throw new CloudOperationException(e);
1636-
} catch (IOException e) {
1637-
throw new CloudOperationException(e);
1638-
}
1639-
}
1640-
1626+
private StreamingLogToken streamLoggregatorLogs(String appName, ApplicationLogListener listener, boolean recent) {
1627+
ClientEndpointConfig.Configurator configurator = new ClientEndpointConfig.Configurator() {
1628+
public void beforeRequest(Map<String, List<String>> headers) {
1629+
if (token != null) {
1630+
headers.put(AUTHORIZATION_HEADER_KEY, Arrays.asList(getAuthorizationHeader()));
1631+
}
1632+
}
1633+
};
1634+
1635+
UUID appId = getAppId(appName);
1636+
CloudInfo cloudInfo = getInfo();
1637+
String mode = recent ? "dump" : "tail";
1638+
URI loggregatorUri = loggregatorUriTemplate.expand(cloudInfo.getLoggregatorEndpoint(), mode, appId);
1639+
try {
1640+
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
1641+
ClientEndpointConfig config = ClientEndpointConfig.Builder.create().configurator(configurator).build();
1642+
Session session = container.connectToServer(new LoggregatorEndpoint(listener), config, loggregatorUri);
1643+
return new StreamingLogTokenImpl(session);
1644+
} catch (DeploymentException e) {
1645+
throw new CloudOperationException(e);
1646+
} catch (IOException e) {
1647+
throw new CloudOperationException(e);
1648+
}
1649+
}
1650+
1651+
private class AccumulatingApplicationLogListener implements ApplicationLogListener {
1652+
private List<ApplicationLog> logs = new ArrayList<ApplicationLog>();
1653+
1654+
public void onMessage(ApplicationLog log) {
1655+
logs.add(log);
1656+
}
1657+
1658+
public void onError(Throwable exception) {
1659+
synchronized (this) {
1660+
this.notify();
1661+
}
1662+
}
1663+
1664+
public void onComplete() {
1665+
synchronized (this) {
1666+
this.notify();
1667+
}
1668+
}
1669+
1670+
public List<ApplicationLog> getLogs() {
1671+
Collections.sort(logs);
1672+
return logs;
1673+
}
1674+
}
1675+
16411676
private Map<String, Object> findApplicationResource(UUID appGuid, boolean fetchServiceInfo) {
16421677
Map<String, Object> urlVars = new HashMap<String, Object>();
16431678
String urlPath = "/v2/apps/{app}?inline-relations-depth=1";

0 commit comments

Comments
 (0)