/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.vipr.client.system;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import com.emc.vipr.client.exceptions.ViPRException;
import com.emc.vipr.client.impl.DateUtils;
import com.emc.vipr.client.impl.RestClient;
import com.emc.vipr.client.impl.jaxb.ListProcessor;
import com.emc.vipr.client.system.impl.PathConstants;
import com.emc.vipr.client.util.AbstractItemProcessor;
import com.emc.vipr.client.util.ItemProcessor;
import com.emc.vipr.model.sys.logging.LogLevels;
import com.emc.vipr.model.sys.logging.LogLevels.LogLevel;
import com.emc.vipr.model.sys.logging.LogMessage;
import com.emc.vipr.model.sys.logging.SetLogLevelParam;
import com.sun.jersey.api.client.ClientResponse;
public class Logs {
public static final String DATE_FORMAT = "yyyy-MM-dd_HH:mm:ss";
public static final int LOG_LEVEL_FATAL = 0;
public static final int LOG_LEVEL_ERROR = 4;
public static final int LOG_LEVEL_WARN = 5;
public static final int LOG_LEVEL_INFO = 7;
public static final int LOG_LEVEL_DEBUG = 8;
public static final int LOG_LEVEL_TRACE = 9;
private static final String NODE_ID = "node_id";
private static final String NODE_NAME = "node_name";
private static final String LOG_NAME = "log_name";
private static final String SEVERITY = "severity";
private static final String START_TIME = "start";
private static final String END_TIME = "end";
private static final String REGEX = "msg_regex";
private static final String MAX_COUNT = "maxcount";
private RestClient client;
public Logs(RestClient client) {
this.client = client;
}
/**
* Gets the log levels for all nodes and all logs. This is a convenience method for <tt>getLogLevels(null, null)</tt>.
*
* @return the list of log levels.
*
* @see #getLogLevels(Collection, Collection, Collection)
*/
public List<LogLevel> getLogLevels() {
return getLogLevels(null, null, null);
}
/**
* Gets the log levels for the given nodes and logs.
*
* @param nodeIds
* the IDs of the nodes. If null or empty, all node log levels are retrieved
* @param logNames
* the name of the logs. If null or empty, all logs' levels are returned.
* @return the list of log levels.
* @deprecated Replaced by
* @see #getLogLevels(Collection, Collection, Collection)
*/
public List<LogLevel> getLogLevels(Collection<String> nodeIds, Collection<String> logNames) {
UriBuilder builder = client.uriBuilder(PathConstants.LOG_LEVELS_URL);
if ((nodeIds != null) && (!nodeIds.isEmpty())) {
builder.queryParam(NODE_ID, nodeIds.toArray());
}
if ((logNames != null) && (!logNames.isEmpty())) {
builder.queryParam(LOG_NAME, logNames.toArray());
}
LogLevels response = client.getURI(LogLevels.class, builder.build());
return response.getLogLevels();
}
/**
* Gets the log levels for the given nodes and logs.
*
* @param nodeIds
* the IDs of the nodes. If null or empty, all node log levels are retrieved
* @param nodeNames
* the names of the nodes. If null or empty, all node log levels are retrieved
* @param logNames
* the name of the logs. If null or empty, all logs' levels are returned.
* @return the list of log levels.
*/
public List<LogLevel> getLogLevels(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames) {
UriBuilder builder = client.uriBuilder(PathConstants.LOG_LEVELS_URL);
if ((nodeIds != null) && (!nodeIds.isEmpty())) {
builder.queryParam(NODE_ID, nodeIds.toArray());
}
if ((nodeNames != null) && (!nodeNames.isEmpty())) {
builder.queryParam(NODE_NAME, nodeNames.toArray());
}
if ((logNames != null) && (!logNames.isEmpty())) {
builder.queryParam(LOG_NAME, logNames.toArray());
}
LogLevels response = client.getURI(LogLevels.class, builder.build());
return response.getLogLevels();
}
/**
* Sets the log level for all nodes and logs. This is a convenience method for <tt>setLogLevels(severity, null, null)</tt>
*
* @param severity
* the log severity.
*
* @see #setLogLevels(int, Collection, Collection, Collection)
*/
public void setLogLevels(int severity) {
setLogLevels(severity, null, null, null);
}
/**
* Sets the log level for the given nodes and logs. This constructs a {@link SetLogLevelParam} and calls
* {@link #setLogLevels(SetLogLevelParam)}.
* <p>
* API Call: <tt>POST /logs/log-levels</tt>
*
* @param severity
* the log severity.
* @param nodeIds
* the IDs of the nodes. If null all nodes are changed.
* @param logNames
* the names of the logs. If null all logs are changed.
* @deprecated Replaced by
* @see #setLogLevels(int, Collection, Collection, Collection)
*/
@Deprecated
public void setLogLevels(int severity, Collection<String> nodeIds, Collection<String> logNames) {
SetLogLevelParam param = new SetLogLevelParam();
param.setSeverity(severity);
if ((nodeIds != null) && (!nodeIds.isEmpty())) {
param.setNodeIds(new ArrayList<String>(nodeIds));
}
if ((logNames != null) && (!logNames.isEmpty())) {
param.setLogNames(new ArrayList<String>(logNames));
}
setLogLevels(param);
}
/**
* Sets the log level for the given nodes and logs. This constructs a {@link SetLogLevelParam} and calls
* {@link #setLogLevels(SetLogLevelParam)}.
* <p>
* API Call: <tt>POST /logs/log-levels</tt>
*
* @param severity
* the log severity.
* @param nodeIds
* the IDs of the nodes. If null all nodes are changed.
* @param nodeNames
* the names of the nodes. If null all nodes are changed.
* @param logNames
* the names of the logs. If null all logs are changed.
*/
public void setLogLevels(int severity, Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames) {
SetLogLevelParam param = new SetLogLevelParam();
param.setSeverity(severity);
if ((nodeIds != null) && (!nodeIds.isEmpty())) {
param.setNodeIds(new ArrayList<String>(nodeIds));
}
if ((nodeNames != null) && (!nodeNames.isEmpty())) {
param.setNodeNames(new ArrayList<String>(nodeNames));
}
if ((logNames != null) && (!logNames.isEmpty())) {
param.setLogNames(new ArrayList<String>(logNames));
}
setLogLevels(param);
}
/**
* Sets the log levels.
* <p>
* API Call: <tt>POST /logs/log-levels</tt>
*
* @param param
* the log level configuration.
*/
public void setLogLevels(SetLogLevelParam param) {
client.post(String.class, param, PathConstants.LOG_LEVELS_URL);
}
/**
* @deprecated Replaced by
* @see #get(Collection, Collection, Collection, Integer, Date, Date, String, Integer)
*/
@Deprecated
public List<LogMessage> get(Collection<String> nodeIds, Collection<String> logNames, Integer severity, Date start,
Date end, String regex, Integer maxCount) {
return get(nodeIds, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
/**
* @deprecated Replaced by
* @see #get(Collection, Collection, Collection, Integer, String, String, String, Integer)
*/
@Deprecated
public List<LogMessage> get(Collection<String> nodeIds, Collection<String> logNames, Integer severity,
String start, String end, String regex, Integer maxCount) {
final List<LogMessage> results = new ArrayList<LogMessage>();
AbstractItemProcessor<LogMessage> processor = new AbstractItemProcessor<LogMessage>() {
@Override
public void processItem(LogMessage item) throws Exception {
results.add(item);
}
};
getAsItems(processor, nodeIds, logNames, severity, start, end, regex, maxCount);
return results;
}
/**
* @deprecated Replaced by
* @see #getAsItems(ItemProcessor, Collection, Collection, Collection, Integer, Date, Date, String, Integer)
*/
@Deprecated
public void getAsItems(ItemProcessor<LogMessage> processor, Collection<String> nodeIds,
Collection<String> logNames, Integer severity, Date start, Date end, String regex, Integer maxCount) {
getAsItems(processor, nodeIds, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
/**
* @deprecated Replaced by
* @see #getAsItems(ItemProcessor, Collection, Collection, Collection, Integer, String, String, String, Integer)
*/
@Deprecated
public void getAsItems(ItemProcessor<LogMessage> processor, Collection<String> nodeIds,
Collection<String> logNames, Integer severity, String start, String end, String regex, Integer maxCount) {
ListProcessor<LogMessage> listProcessor = new ListProcessor<LogMessage>(LogMessage.class, processor);
InputStream in = getAsStream(nodeIds, logNames, severity, start, end, regex, maxCount);
try {
listProcessor.process(in);
} catch (Exception e) {
throw new ViPRException(e);
} finally {
try {
in.close();
} catch (IOException e) {
// Silently ignore
}
}
}
public List<LogMessage> get(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames, Integer severity, Date start,
Date end, String regex, Integer maxCount) {
return get(nodeIds, nodeNames, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
public List<LogMessage> get(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames, Integer severity,
String start, String end, String regex, Integer maxCount) {
final List<LogMessage> results = new ArrayList<LogMessage>();
AbstractItemProcessor<LogMessage> processor = new AbstractItemProcessor<LogMessage>() {
@Override
public void processItem(LogMessage item) throws Exception {
results.add(item);
}
};
getAsItems(processor, nodeIds, nodeNames, logNames, severity, start, end, regex, maxCount);
return results;
}
public void getAsItems(ItemProcessor<LogMessage> processor, Collection<String> nodeIds, Collection<String> nodeNames,
Collection<String> logNames, Integer severity, Date start, Date end, String regex, Integer maxCount) {
getAsItems(processor, nodeIds, nodeNames, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
public void getAsItems(ItemProcessor<LogMessage> processor, Collection<String> nodeIds, Collection<String> nodeNames,
Collection<String> logNames, Integer severity, String start, String end, String regex, Integer maxCount) {
ListProcessor<LogMessage> listProcessor = new ListProcessor<LogMessage>(LogMessage.class, processor);
InputStream in = getAsStream(nodeIds, nodeNames, logNames, severity, start, end, regex, maxCount);
try {
listProcessor.process(in);
} catch (Exception e) {
throw new ViPRException(e);
} finally {
try {
in.close();
} catch (IOException e) {
// Silently ignore
}
}
}
/**
* Gets the system logs as a stream.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time, may be null. If specified, this will be formatted in the UTC timezone as <tt>yyyy-MM-dd_HH:mm:ss</tt>.
* @param end
* the end time, may be null. If specified, this will be formatted in the UTC timezone as <tt>yyyy-MM-dd_HH:mm:ss</tt>
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as XML.
* @deprecated Replaced by
* @see #getAsStream(Collection, Collection, Collection, Integer, Date, Date, String, Integer)
*/
@Deprecated
public InputStream getAsStream(Collection<String> nodeIds, Collection<String> logNames, Integer severity,
Date start, Date end, String regex, Integer maxCount) {
return getAsStream(nodeIds, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
/**
* Gets the system logs as an XML stream.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param end
* the end time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as XML.
* @deprecated Replaced by
* @see #getAsStream(Collection, Collection, Collection, Integer, String, String, String, Integer)
*/
@Deprecated
public InputStream getAsStream(Collection<String> nodeIds, Collection<String> logNames, Integer severity,
String start, String end, String regex, Integer maxCount) {
URI uri = getURI(nodeIds, null, logNames, severity, start, end, regex, maxCount);
ClientResponse response = client.getClient().resource(uri).accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
return response.getEntityInputStream();
}
/**
* Gets the system logs as a stream.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param nodeNames
* the names of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time, may be null. If specified, this will be formatted in the UTC timezone as <tt>yyyy-MM-dd_HH:mm:ss</tt>.
* @param end
* the end time, may be null. If specified, this will be formatted in the UTC timezone as <tt>yyyy-MM-dd_HH:mm:ss</tt>
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as XML.
*/
public InputStream getAsStream(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames, Integer severity,
Date start, Date end, String regex, Integer maxCount) {
return getAsStream(nodeIds, nodeNames, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
/**
* Gets the system logs as an XML stream.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param nodeNames
* the names of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param end
* the end time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as XML.
*/
public InputStream getAsStream(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames, Integer severity,
String start, String end, String regex, Integer maxCount) {
URI uri = getURI(nodeIds, nodeNames, logNames, severity, start, end, regex, maxCount);
ClientResponse response = client.getClient().resource(uri).accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
return response.getEntityInputStream();
}
/**
* Gets the system logs as a text stream.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param end
* the end time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as text.
* @deprecated Replaced by
* @see #getAsText(Collection, Collection, Collection, Integer, String, String, String, Integer)
*/
@Deprecated
public InputStream getAsText(Collection<String> nodeIds, Collection<String> logNames, Integer severity, Date start,
Date end, String regex, Integer maxCount) {
return getAsText(nodeIds, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
/**
* Gets the system logs as a text stream.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param nodeNames
* the names of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param end
* the end time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as text.
*/
public InputStream getAsText(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames, Integer severity, Date start,
Date end, String regex, Integer maxCount) {
return getAsText(nodeIds, nodeNames, logNames, severity, formatDate(start), formatDate(end), regex, maxCount);
}
/**
* Gets the system logs as a text stream.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param end
* the end time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as text.
* @deprecated Replaced by
* @see #getAsText(Collection, Collection, Collection, Integer, String, String, String, Integer)
*/
@Deprecated
public InputStream getAsText(Collection<String> nodeIds, Collection<String> logNames, Integer severity,
String start, String end, String regex, Integer maxCount) {
URI uri = getURI(nodeIds, null, logNames, severity, start, end, regex, maxCount);
ClientResponse response = client.getClient().resource(uri).accept(MediaType.TEXT_PLAIN).get(ClientResponse.class);
return response.getEntityInputStream();
}
/**
* Gets the system logs as a text stream by node.
* <p>
* API Call: <tt>GET /logs</tt>
*
* @param nodeIds
* the IDs of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param nodeNames
* the names of the nodes on which logs are retrieved, if null or empty logs are retrieved on all nodes.
* @param logNames
* the names of the logs to retrieve, if null or empty all logs are retrieved.
* @param severity
* the severity level, may be null
* @param start
* the start time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param end
* the end time (<tt>yyyy-MM-dd_HH:mm:ss</tt>), may be null.
* @param regex
* the regular expression that logs must match, may be null or empty.
* @param maxCount
* the maximum number of log messages to return, may be null. More may be returned if there are multiple logs
* at the same instant when max count is reached.
* @return a stream containing the logs as text.
*/
public InputStream getAsText(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames, Integer severity,
String start, String end, String regex, Integer maxCount) {
URI uri = getURI(nodeIds, nodeNames, logNames, severity, start, end, regex, maxCount);
ClientResponse response = client.getClient().resource(uri).accept(MediaType.TEXT_PLAIN).get(ClientResponse.class);
return response.getEntityInputStream();
}
private URI getURI(Collection<String> nodeIds, Collection<String> nodeNames, Collection<String> logNames, Integer severity, String startTime,
String endTime, String regex, Integer maxCount) {
UriBuilder builder = client.uriBuilder(PathConstants.LOGS_URL);
if ((nodeIds != null) && (!nodeIds.isEmpty())) {
builder.queryParam(NODE_ID, nodeIds.toArray());
}
if ((nodeNames != null) && (!nodeNames.isEmpty())) {
builder.queryParam(NODE_NAME, nodeNames.toArray());
}
if ((logNames != null) && (!logNames.isEmpty())) {
builder.queryParam(LOG_NAME, logNames.toArray());
}
if (severity != null) {
builder.queryParam(SEVERITY, severity);
}
if (startTime != null) {
builder.queryParam(START_TIME, startTime);
}
if (endTime != null) {
builder.queryParam(END_TIME, endTime);
}
if ((regex != null) && (regex.length() > 0)) {
builder.queryParam(REGEX, regex);
}
if (maxCount != null) {
builder.queryParam(MAX_COUNT, maxCount);
}
return builder.build();
}
private String formatDate(Date date) {
return date != null ? DateUtils.formatUTC(date, DATE_FORMAT) : null;
}
public LogsSearchBuilder search() {
return new LogsSearchBuilder(this);
}
}