カスタムhive url parse関数
hiveでnginxログurlを分析するときには、常にパールスurlが必要です。hiveの中で持参した関数のパーシャ_urlはこの機能を実現することができますが、フォーマットに対する要求は比較的厳しく、直接にnginx logsのrequestフィールドに使用することはできません。
hive -e "select parse_url('http://facebook.com/path1/p.php?k1=v1&k2=v2#Ref1', 'HOST') from dual"
facebook.com
hive -e "select parse_url('facebook.com/path1/p.php?k1=v1&k2=v2#Ref1', 'HOST') from dual"
NULL
レゲックスカットもできます。extractで実現しますが、正則を書く必要があります。性能にも問題があります。hive -e "select regexp_extract('GET /vips-mobile/router.do?api_key=24415b921531551cb2ba756b885ce783&app_version=1.8.6&fields=sku_id HTTP/1.1','.+? +(.+?)app_version=(.+?)&(.+) .+?',2) from dual"
1.8.6
自分で一つ書くことを考えて、パールスを参考にします。urlのudf:コードは以下の通りです。package com.hive.myudf;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.hadoop.hive.ql.exec.UDF;
public class UDFNginxParseUrl extends UDF {
private String schemal = "http://";
private String host1 = null;
private Pattern p1 = null;
private URL url = null;
private Pattern p = null;
private String lastKey = null;
public UDFNginxParseUrl() {
}
public String evaluate(String host1, String urlStr, String partToExtract) {
if (host1 == null || urlStr == null || partToExtract == null) {
return null;
}
p1 = Pattern.compile("(.+?) +(.+?) (.+)");
Matcher m1 = p1.matcher(urlStr);
if (m1.matches()){
String realUrl = schemal + host1 + m1.group(2);
System.out.println("URL is " + realUrl);
try{
url = new URL(realUrl);
}catch (Exception e){
return null;
}
}
/*
if (lastUrlStr == null || !urlStr.equals(lastUrlStr)) {
try {
url = new URL(urlStr);
} catch (Exception e) {
return null;
}
}
lastUrlStr = urlStr;
*/
if (partToExtract.equals("HOST")) {
return url.getHost();
}
if (partToExtract.equals("PATH")) {
return url.getPath();
}
if (partToExtract.equals("QUERY")) {
return url.getQuery();
}
if (partToExtract.equals("REF")) {
return url.getRef();
}
if (partToExtract.equals("PROTOCOL")) {
return url.getProtocol();
}
if (partToExtract.equals("FILE")) {
return url.getFile();
}
if (partToExtract.equals("AUTHORITY")) {
return url.getAuthority();
}
if (partToExtract.equals("USERINFO")) {
return url.getUserInfo();
}
return null;
}
public String evaluate(String host, String urlStr, String partToExtract, String key) {
if (!partToExtract.equals("QUERY")) {
return null;
}
String query = this.evaluate(host, urlStr, partToExtract);
if (query == null) {
return null;
}
if (!key.equals(lastKey)) {
p = Pattern.compile("(&|^)" + key + "=([^&]*)");
}
lastKey = key;
Matcher m = p.matcher(query);
if (m.find()) {
return m.group(2);
}
return null;
}
}
add jarとcreate functionの後テスト:hive -e "select nginx_url_parse('test.test.com','GET /vips-mobile/router.do?api_key=24415&app_version=1.8.6&fields=sku_id HTTP/1.1','HOST') FROM dual;"
test.test.com
hive -e "select nginx_url_parse('test.test.com','GET /vips-mobile/router.do?api_key=24415&app_version=1.8.6&fields=sku_id HTTP/1.1','QUERY','api_key') FROM dual;"
24415
これは直接にinxのログに適用できます。