com.amazon.redshift.logger.RedshiftLogger Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of redshift-jdbc42 Show documentation
Show all versions of redshift-jdbc42 Show documentation
Java JDBC 4.2 (JRE 8+) driver for Redshift database
The newest version!
package com.amazon.redshift.logger;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.DriverManager;
import java.text.FieldPosition;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.Locale;
import com.amazon.redshift.RedshiftProperty;
import com.amazon.redshift.util.RedshiftProperties;
/**
* Logger for each connection or at driver.
*
* @author iggarish
*
*/
public class RedshiftLogger {
// Any connection enable the logging
private static boolean isEnable = false;
private static RedshiftLogger driverLogger;
private volatile LogLevel level = LogLevel.OFF;
private String fileName;
private LogHandler handler;
private static AtomicInteger connectionId = new AtomicInteger();
public RedshiftLogger(String fileName,
String logLevel,
boolean driver,
String maxLogFileSize,
String maxLogFileCount) {
if (driver) {
this.fileName = fileName;
driverLogger = this;
}
else {
int connId = connectionId.incrementAndGet();
if (fileName != null) {
String fileExt = "";
if (fileName.contains("."))
{
fileExt = fileName
.substring(fileName.lastIndexOf("."), fileName.length());
fileName = fileName.substring(0, fileName.lastIndexOf("."));
}
this.fileName = fileName + "_connection_" + connId
+ fileExt ;
}
}
level = (logLevel != null )
? LogLevel.getLogLevel(logLevel)
: LogLevel.OFF;
if (level != LogLevel.OFF) {
try {
if (DriverManager.getLogWriter() != null) {
handler = new LogWriterHandler(DriverManager.getLogWriter());
}
else
if (this.fileName != null) {
handler = new LogFileHandler(this.fileName, driver, maxLogFileSize, maxLogFileCount);
}
else {
handler = new LogConsoleHandler();
}
}
catch(Exception ex) {
handler = new LogConsoleHandler();
}
isEnable = true;
}
}
/**
* Check for logging enable or not.
*
* @return true if any of the connection enable the logging, false otherwise.
*/
public static boolean isEnable() {
return isEnable;
}
public static RedshiftLogger getDriverLogger() {
return driverLogger;
}
/** True if logger associated with the connection enable the logging.
* Otherwise false.
*
* One logger associated with each connection.
* There is a separate logger at driver level.
*
* @return
*/
private boolean isEnabled() {
return (level != LogLevel.OFF);
}
public LogLevel getLogLevel() {
return level;
}
/**
* Determines if logging should occur based on the LogLevel.
*
* @param level
* The level of logging to attempt.
* @param log
* The ILogger to try to log to.
*
* @return True if logging is to be done according to LogLevel; false otherwise.
*/
public static boolean checkLogLevel(LogLevel level, RedshiftLogger log)
{
return (log.isEnabled()) &&
(level.ordinal() <= log.getLogLevel().ordinal());
}
/* public static boolean isLoggable(LogLevel level, RedshiftLogger log) {
return checkLogLevel(level, log);
} */
private static StackTraceElement getStackElementAbove(String functionName)
{
boolean returnNextFunction = false;
// Look for the function above the specified one.
for (StackTraceElement s : Thread.currentThread().getStackTrace())
{
if (returnNextFunction)
{
return s;
}
else if (s.getMethodName().equals(functionName))
{
returnNextFunction = true;
}
}
// Default to just returning 3 above, which should be the caller of the caller of this
// function.
return Thread.currentThread().getStackTrace()[3];
}
public static String maskSecureInfoInUrl(String url)
{
String[] tokens = {
RedshiftProperty.PWD.getName(),
RedshiftProperty.PASSWORD.getName(),
RedshiftProperty.IAM_ACCESS_KEY_ID.getName(),
RedshiftProperty.IAM_SECRET_ACCESS_KEY.getName(),
RedshiftProperty.IAM_SESSION_TOKEN.getName(),
RedshiftProperty.AUTH_PROFILE.getName(),
RedshiftProperty.SSL_KEY.getName(),
RedshiftProperty.SSL_PASSWORD.getName(),
RedshiftProperty.WEB_IDENTITY_TOKEN.getName(),
"Client_ID",
"Client_Secret",
"IdP_Tenant",
"Partner_SPID",
"Preferred_Role",
"Profile",
"roleArn",
};
String temp = maskSecureInfo(url, tokens, "[\\?;&]");
return temp;
}
public static String maskSecureInfo(String msg, String[] tokens, String tokenizer) {
if(msg == null) return msg;
StringBuilder newMsg = new StringBuilder();
String[] splitMsgs = msg.split(tokenizer);
boolean secureInfoFound = false;
for(String splitMsg : splitMsgs) {
String tokenFound = null;
String sTemp = splitMsg.toLowerCase();
for(String token : tokens) {
String temp = token.toLowerCase();
if(sTemp.contains(temp)) {
tokenFound = token;
secureInfoFound = true;
break;
}
}
if(tokenFound == null) {
newMsg.append(splitMsg).append(";");
}
else {
newMsg.append(tokenFound).append("=***;");
}
}
return (secureInfoFound) ? newMsg.toString() : msg;
}
public static Properties maskSecureInfoInProps(Properties info) {
if(info == null) return null;
String[] propNames = {
RedshiftProperty.PWD.getName(),
RedshiftProperty.PASSWORD.getName(),
RedshiftProperty.IAM_ACCESS_KEY_ID.getName(),
RedshiftProperty.IAM_SECRET_ACCESS_KEY.getName(),
RedshiftProperty.IAM_SESSION_TOKEN.getName(),
RedshiftProperty.AUTH_PROFILE.getName(),
RedshiftProperty.SSL_KEY.getName(),
RedshiftProperty.SSL_PASSWORD.getName(),
RedshiftProperty.WEB_IDENTITY_TOKEN.getName(),
"Client_ID",
"Client_Secret",
"IdP_Tenant",
"Partner_SPID",
"Preferred_Role",
"Profile",
"roleArn",
};
Properties loggedProperties = new RedshiftProperties();
loggedProperties.putAll(info);
removeUnrecognizedPropertiesFromLogging(loggedProperties);
for(String propName : propNames)
{
replaceIgnoreCase(loggedProperties, propName, "***");
}
return loggedProperties;
}
/**
* fetches set of properties defined in the RedshiftProperty enum class and properties defined in public docs
* compares against given properties and removes unrecognized properties from logs
*/
public static void removeUnrecognizedPropertiesFromLogging(Properties loggedProperties)
{
Set enumProperties = Arrays.stream(RedshiftProperty.values()).map(x -> x.getName().toLowerCase(Locale.US)).collect(Collectors.toSet());
Set publicProperties = RedshiftProperty.getPublicProperties().stream().map(x -> x.toLowerCase(Locale.US)).collect(Collectors.toSet());
Set allProperties = enumProperties.stream().collect(Collectors.toSet());
allProperties.addAll(publicProperties);
for (String givenProperty : loggedProperties.stringPropertyNames())
{
if (!allProperties.contains(givenProperty))
{
loggedProperties.remove(givenProperty);
}
}
}
public static String replaceIgnoreCase(Properties info, String key, String newVal) {
String value = info.getProperty(key);
if (null != value) {
info.replace(key, newVal);
return value;
}
// Not matching with the actual key then
Set> s = info.entrySet();
Iterator> it = s.iterator();
while (it.hasNext()) {
Entry