2014年11月25日 星期二

處理Splunk 與 WebLogic Log 時間不一致問題

最近使用Splunk導入WebLogic時發現時間不夠一致,甚至假設我自己撰寫程式來印出Log時,在Log檔裡顯示的時間是正確的,但在Splunk中卻被視為同一時間,由於我的Splunk Search非常依賴時間來做查詢條件,因此為了解決這種問題,我決定為WLS Log的時間新增一個欄位(Field)叫作 log_time。
另外WLS Log在我的Log File中原本時間顯示為中文,但是進入Splunk時,卻變成了亂碼,這個問題我試過不少方法也暫時無法解決(我是透過Forwarder,Splunk & WLS不同台機器)。
於是我試圖先讓WLS Log時間變成單純的數字日期,而不在出現中文。




步驟依序如上面圖示,至WebLogic AdminConsole中點選 伺服器-->欲修改的Log伺服器所在位置-->點選日誌記錄-->進階,在「日期格式樣式」把原本有中文 時分秒的設定 改成
 yyyy/M/d HH'-'mm'-'ss'-' z
重新啟動 Server,再至Log檔觀察,就可以發現時間格式改變了。
實際至Splunk 觀察也是一樣,另外我已經定義好 log_time 欄位的 pattern了如圖
如上圖所示,藍色是Splunk定義的時間,而紅色部分是Log的真實時間,以及我定義log_time欄位的時間,而為了使用我定義的時間來做查詢,在程式呼叫curl指令時需要將時間作轉換,注意"2014-11/26" 與 "10-37-33"之間是有空白的。
程式如下

Calendar calendar1 = Calendar.getInstance();
System.out.println("calendar1 : " + calendar1.getTime());
calendar1.add(Calendar.MINUTE, -5);
System.out.println("calendar2 : " + calendar1.getTime());
Date date = calendar1.getTime();
SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH-mm-ss");
String date1 = DATE_FORMAT.format(date);
System.out.println("Date1 : " + date1);
String[] tokens = date1.split(" ");
    for (String token:tokens) {
  System.out.println(token);
}
String finalDate = tokens[0]+"\\%20"+tokens[1];
System.out.println("finalDate: " + finalDate);
String log_time = "2014/11/25\\%2014-21-02";

注意我在程式碼第三行,已將實際時間減5分鐘,因為我的目的是查詢現在時間與前5分鐘之間的Log(假設Splunk時間若正確等同於Splunk執行earliest="-5m"),而最後得到的樣式就會像程式最後一行一樣  "2014/11/25\\%2014-21-02";
細心的你會發現我們中間的空白是使用\\%20取代,這是在Windows執行Java的作法

之後就是Splunk厲害的地方,他可以使用String表示時間後,依然可以比較時間,如下圖

因此我們可以放心的使用log_time當作時間基準查詢了,另外介紹Windows2003時間同步
我將Splunk Server與 WLS Server同步至我的DC Server
w32tm /config /manualpeerlist:dc.test.com.tw /syncfromflags:MANUAL
w32tm /config /update
w32tm /resync

讓時間更一致,WLS Log實在不夠精準,看來目前使用自定義的欄位查詢最精準。

**********************更好的方式  最新更新*******************************
修改WLS Date Format Pattern,修改成  yy/M/d HH':'mm':'ss  like as  14/12/12 16:52:09
重新啟動 WLS Server,則Splunk就可以認出正確的時間格式,並將其傳入 _time default index中,已 _time 的時間正確的話 ,就可以 如常的 使用 Splunk Time Modifier 
ex: earliest="-5m" or latest








Java Call Splunk Restful Service with curl On Linux

之前文章已經實現了使用Java搭配Curl and openssl 來呼叫 Splunk Restful API
但那是透過 CMD 也就是 Windows平台,現在假設我們程式需要佈署在Linux平台上
則語法也會不同。首先在Linux平台上有個好處,那就是大多數已經內建了curl
但是使用Java呼叫curl時,我必須先知道 curl 需在哪執行,你可以在Linux 下執行which curl
一樣使用ProcessBuilder
程式範例如下:
import java.io.*;
import java.util.*;

public class ProcessBuilderTest {
  public static void main(String args[]) 
     throws InterruptedException,IOException 
  {
  final List<String> commands = new ArrayList<String>();                

commands.add("/usr/bin/curl"); 
 commands.add("-k"); 
 commands.add("-u"); 
 commands.add("admin:hello"); 
 commands.add("-s"); 
 commands.add("https://localhost:8089/services/search/jobs/"+sid+"/results/");

ProcessBuilder builder = new ProcessBuilder(commands);
File dir = new File("/home");
builder.directory(dir);

    final Process process = builder.start();
    
    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line;
    while ((line = br.readLine()) != null) {
      System.out.println(line);
    }
    System.out.println("Program terminated!");
  }
}

如上面程式所示,只要能先得到Splunk Restful 回傳的 SID後加入程式,即可得到與Splunk Server上搜尋一樣的結果。
此外由於程式可能需要同時於Windows及Linux執行,所以可以使用下面程式來判別以決定command的組合模式
private static String OS = System.getProperty("os.name").toLowerCase();

private static boolean isWindows() {  
return (OS.indexOf("win") >= 0);
}
private static boolean isUnix() { 
return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0 );

當然Windows與Linux上指令上還有一些小差別,另外Linux可以使用空白,但Windows要使用%20或一些需要使用跳脫字元的用法,才可正確執行呼叫CURL,歡迎大家一起研究討論。

}

2014年7月7日 星期一

Java呼叫CMD的另一種方式使用ProcessBuilder(calling Splunk Restful API)

前幾天的文章已經可以順利的使用Java呼叫CMD
現在介紹另一種方式是使用ProcessBuilder呼叫,搭配前一篇Java處理字串中含有雙引號的字串
可以完整的呈現不使用批次檔,不用下 cd command to executing directory(可直接設定cmd執行目錄)

程式碼如下

import java.io.*;
import java.util.*;

public class ProcessBuilderTest {
  public static void main(String args[]) 
     throws InterruptedException,IOException 
  {
 final List<String> commands = new ArrayList<String>();                

 commands.add("cmd.exe");
 commands.add("/C");
 commands.add("curl -k -u admin:!QAZxsw2 -s https://localhost:8089/services/search/jobs/ -d\"search=| savedsearch selectFromDual\"");
 //在Java中若是字串中含有字串例如 " "name" " 應表示為 "\"name\" "
 //commands.add("curl -k -u admin:!QAZxsw2 -s https://localhost:8089/services/search/jobs/"+sid+"/results/");
 commands.add("start");

    //ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/C", "start");
ProcessBuilder builder = new ProcessBuilder(commands);
File dir = new File("C:\\Users\\Peter\\Desktop\\openssl-0.9.8h-1-bin\\bin");
builder.directory(dir);

    final Process process = builder.start();
    
    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line;
    while ((line = br.readLine()) != null) {
      System.out.println(line);
    }
    System.out.println("Program terminated!");
  }
}

Java如何在字串中含有另一個雙引號的字串

最近遇到這樣的情形,使用cURL工具 search Splunk時 search的字串中含有另一個字串
想要以Java的方式呈現,都會出現錯誤!

今天終於找到方法了

如下程式碼

public class Test{  
  
    public static void main(String[] args){  
        String str1 = "\"Peter\"";//字串兩邊含有雙引號
        String str2 = "Peter \"is\" boy";//字串中間含有雙引號
        String str3 = "\\Peter";//使用\字符可以使字串包含其他字串  
          
        System.out.println("字串一:" + str1);  
        System.out.println("字串二:" + str2);  
        System.out.println("字串三:" + str3);  
    }  
}

執行結果

請注意看 字串一的寫法 在中間的字串雙引號前 先加一個 \  雙引號結尾前 再加一個 \

參考Java处理本身包含双引号的String

2014年7月3日 星期四

使用 Java 呼叫 cmd.exe 並下指令(下)-Splunk Java Solution

跟著上一篇文章,除了讓CMD幫我們做事情外,我還需要將資料直接可以在Java中取用
則更改前一篇文章,改使用以下程式碼,如圖就可以在Eclipse Console看到如CMD裡顯示的狀態啦!

import java.io.*;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
public class AppLauncher {
  public static void main(String[] args) throws Exception
  {
      /*
       *若需外部傳入可用下列語法,執行時ex:java AppLauncher "cmd.exe /c c:123.bat"
       */     
    //String cmd = args.length == 0? "java -version" : args[0];
    String[] cmd = new String[3];
    cmd[0] = "cmd.exe" ;
    cmd[1] = "/C" ;
    //填入執行程式路徑
    cmd[2] = "D:/SplunkSearchId.bat" ;
   
    //-s 為curl 不顯示download進度訊息
    //String cmd = "java -version";
    Process process = Runtime.getRuntime().exec(cmd);
    new Thread(new SubTask(process.getInputStream())).start();
    new Thread(new SubTask(process.getErrorStream())).start();
    process.waitFor();
    //多印一空白行
    System.out.println();
    System.out.println("====================Application terminated=======================");
  }
}
class SubTask implements Runnable {
  public SubTask(InputStream istream)
  {
    if (istream == null){
      iReader = new BufferedReader(new InputStreamReader(System.in));
    }
    else
      iReader = new BufferedReader(new InputStreamReader(istream));
  }
  public void run()
  {
    try {
      String input = iReader.readLine();
      while (input != null)
      {
        //若需執行結果可將input傳出
        System.out.println(input);
        
        /*String html = input;
Document doc = Jsoup.parse(html, "", Parser.xmlParser());
   //String testValue = "0";
for (Element e : doc.select("sid")) {
       //System.out.println(e);
    System.out.println("hi: " + e.text());
    //testValue = e.text();
   }*/
        
        input = iReader.readLine();
      }
    }
    catch (IOException ioe) {
    }
  }
  private BufferedReader iReader;
}


另外請注意一下 程式碼中有註解的地方 是 XML Parser的方式,這邊使用JSOUP jar
因為Splunk Restful API回傳的default格式是XML,其實這樣已經是一個完整的Splunk with JAVA Solution (Java+CMD+cURL+JSOUP)


使用 Java 呼叫 cmd.exe 並下指令(上)

如題,最近由於研究 Splunk Restful API
想透過 API 得到我所要的資料,但Splunk Default支援使用cURL工具來做查詢
由於我cURL安裝好了後,還是得使用cmd下指令,而將來也必須一併整合至
Java,所以以下範例程式為 撰寫一支Java程式呼叫cmd,並執行一個.bat檔案(splunk curl 指令)
目的是取回Splunk Job ID, 圖示為程式的執行結果~*


import java.io.*;

public class CMD {

public static void main(String args[]) {
    String path = "D:\\SplunkSearchId.bat";

   Runtime run = Runtime.getRuntime();   
   try {   
        
    /*cmd /c dir 是執行完dir命令後關閉命令窗口。
 cmd /k dir 是執行完dir命令後不關閉命令窗口。
              cmd /c start dir /b會打開一個新窗口後執行dir指令,原窗口會關閉。
               cmd /k start dir 會打開一個新窗口後執行dir指令,原窗口不會關閉。*/
       Process process = run.exec("cmd /k start " + path);
   
        
       InputStream in = process.getInputStream();
       
       
   } catch (Exception e) {            
       e.printStackTrace();   
   }   
}

}




使用WLS SNMP Monitor CMD

最近某個專案要利用SNMP來監測WLS的狀態
在現在新的版本都建議要使用WLS的SNMP Agent功能(請參考WLS設定Trap http://weblogic-wonders.com/weblogic/2010/12/19/weblogic-snmp-to-monitor-jdbc-connection-pool/)
但是 假設我們手邊沒有其它工具可以觀察是否設定成功
WLS本身有提供Command Line的方式來供使用者測試

首先打開命令提示字元後,必須將WEBLOGIC_PATH加入
意思是使用cmd會根據PATH尋找對應的class

由於我安裝的WLS並沒有事先把WEBLOGIC_PATH設定好
所以請參考下圖至%WLS_HOME/server/bin下使用setWLSEnv.cmd or setWLSEnv.sh(Linux)
再echo看看是否已設定成功,接著就可以使用 WLS提供的monitor cmd了
注意第三張圖 -p(port) 是 你在WLS Admin Console設定 Trap的 port喔!