From 2f18fc821c6284a13de2878db27142e84b7bf9f0 Mon Sep 17 00:00:00 2001 From: ayolajayamaha Date: Mon, 27 Jul 2015 22:27:27 +0530 Subject: [PATCH] PHOENIX-2186 Creating backend services for the Phoenix Tracing Web App (Nishani) Conflicts: pom.xml --- bin/phoenix_utils.py | 8 + bin/traceserver.py | 188 ++++++++++++ phoenix-tracing-webapp/README.md | 15 + phoenix-tracing-webapp/pom.xml | 122 ++++++++ .../src/build/trace-server-runnable.xml | 60 ++++ .../src/main/config/checkstyle/checker.xml | 281 ++++++++++++++++++ .../src/main/config/checkstyle/header.txt | 16 + .../main/config/checkstyle/suppressions.xml | 46 +++ .../tracingwebapp/http/ConnectionFactory.java | 43 +++ .../tracingwebapp/http/EntityFactory.java | 101 +++++++ .../phoenix/tracingwebapp/http/Main.java | 81 +++++ .../tracingwebapp/http/TraceServlet.java | 152 ++++++++++ .../src/main/webapp/WEB-INF/web.xml | 15 + .../src/main/webapp/index.html | 16 + pom.xml | 2 + 15 files changed, 1146 insertions(+) create mode 100755 bin/traceserver.py create mode 100755 phoenix-tracing-webapp/README.md create mode 100755 phoenix-tracing-webapp/pom.xml create mode 100755 phoenix-tracing-webapp/src/build/trace-server-runnable.xml create mode 100755 phoenix-tracing-webapp/src/main/config/checkstyle/checker.xml create mode 100755 phoenix-tracing-webapp/src/main/config/checkstyle/header.txt create mode 100755 phoenix-tracing-webapp/src/main/config/checkstyle/suppressions.xml create mode 100644 phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/ConnectionFactory.java create mode 100644 phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/EntityFactory.java create mode 100755 phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/Main.java create mode 100755 phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/TraceServlet.java create mode 100755 phoenix-tracing-webapp/src/main/webapp/WEB-INF/web.xml create mode 100755 phoenix-tracing-webapp/src/main/webapp/index.html diff --git a/bin/phoenix_utils.py b/bin/phoenix_utils.py index bfb47377036..13dd3601370 100755 --- a/bin/phoenix_utils.py +++ b/bin/phoenix_utils.py @@ -56,6 +56,7 @@ def setPath(): PHOENIX_CLIENT_JAR_PATTERN = "phoenix-*-client.jar" PHOENIX_THIN_CLIENT_JAR_PATTERN = "phoenix-*-thin-client.jar" PHOENIX_QUERYSERVER_JAR_PATTERN = "phoenix-server-*-runnable.jar" + PHOENIX_TRACESERVER_JAR_PATTERN = "phoenix-tracing-webapp-*-runnable.jar" PHOENIX_TESTS_JAR_PATTERN = "phoenix-core-*-tests*.jar" # Backward support old env variable PHOENIX_LIB_DIR replaced by PHOENIX_CLASS_PATH @@ -119,6 +120,13 @@ def setPath(): if phoenix_queryserver_jar == "": phoenix_queryserver_jar = findFileInPathWithoutRecursion(PHOENIX_QUERYSERVER_JAR_PATTERN, os.path.join(current_dir, "..")) + global phoenix_traceserver_jar + phoenix_traceserver_jar = find(PHOENIX_TRACESERVER_JAR_PATTERN, os.path.join(current_dir, "..", "phoenix-tracing-webapp", "target", "*")) + if phoenix_traceserver_jar == "": + phoenix_traceserver_jar = findFileInPathWithoutRecursion(PHOENIX_TRACESERVER_JAR_PATTERN, os.path.join(current_dir, "..", "lib")) + if phoenix_traceserver_jar == "": + phoenix_traceserver_jar = findFileInPathWithoutRecursion(PHOENIX_TRACESERVER_JAR_PATTERN, os.path.join(current_dir, "..")) + global phoenix_thin_client_jar phoenix_thin_client_jar = find(PHOENIX_THIN_CLIENT_JAR_PATTERN, os.path.join(current_dir, "..", "phoenix-server-client", "target", "*")) diff --git a/bin/traceserver.py b/bin/traceserver.py new file mode 100755 index 00000000000..3d1219309d0 --- /dev/null +++ b/bin/traceserver.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python +############################################################################ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################ + +# +# Script to handle launching the trace server process. +# +# usage: traceserver.py [start|stop] +# + +import datetime +import getpass +import os +import os.path +import signal +import subprocess +import sys +import tempfile + +try: + import daemon + daemon_supported = True +except ImportError: + # daemon script not supported on some platforms (windows?) + daemon_supported = False + +import phoenix_utils + +phoenix_utils.setPath() + +command = None +args = sys.argv + +if len(args) > 1: + if args[1] == 'start': + command = 'start' + elif args[1] == 'stop': + command = 'stop' +if command: + args = args[2:] + +if os.name == 'nt': + args = subprocess.list2cmdline(args[1:]) +else: + import pipes # pipes module isn't available on Windows + args = " ".join([pipes.quote(v) for v in args[1:]]) + +# HBase configuration folder path (where hbase-site.xml reside) for +# HBase/Phoenix client side property override +hbase_config_path = phoenix_utils.hbase_conf_dir + +# default paths ## TODO: add windows support +java_home = os.getenv('JAVA_HOME') +hbase_pid_dir = os.path.join(tempfile.gettempdir(), 'phoenix') +phoenix_log_dir = os.path.join(tempfile.gettempdir(), 'phoenix') +phoenix_file_basename = 'phoenix-%s-traceserver' % getpass.getuser() +phoenix_log_file = '%s.log' % phoenix_file_basename +phoenix_out_file = '%s.out' % phoenix_file_basename +phoenix_pid_file = '%s.pid' % phoenix_file_basename +opts = os.getenv('PHOENIX_TRACESERVER_OPTS', '') + +# load hbase-env.??? to extract JAVA_HOME, HBASE_PID_DIR, HBASE_LOG_DIR +hbase_env_path = None +hbase_env_cmd = None +if os.name == 'posix': + hbase_env_path = os.path.join(hbase_config_path, 'hbase-env.sh') + hbase_env_cmd = ['bash', '-c', 'source %s && env' % hbase_env_path] +elif os.name == 'nt': + hbase_env_path = os.path.join(hbase_config_path, 'hbase-env.cmd') + hbase_env_cmd = ['cmd.exe', '/c', 'call %s & set' % hbase_env_path] +if not hbase_env_path or not hbase_env_cmd: + print >> sys.stderr, "hbase-env file unknown on platform %s" % os.name + sys.exit(-1) + +hbase_env = {} +if os.path.isfile(hbase_env_path): + p = subprocess.Popen(hbase_env_cmd, stdout = subprocess.PIPE) + for x in p.stdout: + (k, _, v) = x.partition('=') + hbase_env[k.strip()] = v.strip() + +if hbase_env.has_key('JAVA_HOME'): + java_home = hbase_env['JAVA_HOME'] +if hbase_env.has_key('HBASE_PID_DIR'): + hbase_pid_dir = hbase_env['HBASE_PID_DIR'] +if hbase_env.has_key('HBASE_LOG_DIR'): + phoenix_log_dir = hbase_env['HBASE_LOG_DIR'] +if hbase_env.has_key('PHOENIX_TRACESERVER_OPTS'): + opts = hbase_env['PHOENIX_TRACESERVER_OPTS'] + +log_file_path = os.path.join(phoenix_log_dir, phoenix_log_file) +out_file_path = os.path.join(phoenix_log_dir, phoenix_out_file) +pid_file_path = os.path.join(hbase_pid_dir, phoenix_pid_file) + +if java_home: + java = os.path.join(java_home, 'bin', 'java') +else: + java = 'java' + +# " -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n " + \ +# " -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true" + \ +java_cmd = '%(java)s -cp ' + hbase_config_path + os.pathsep + phoenix_utils.phoenix_traceserver_jar + \ + " -Dproc_phoenixtraceserver" + \ + " -Dlog4j.configuration=file:" + os.path.join(phoenix_utils.current_dir, "log4j.properties") + \ + " -Dpsql.root.logger=%(root_logger)s" + \ + " -Dpsql.log.dir=%(log_dir)s" + \ + " -Dpsql.log.file=%(log_file)s" + \ + " " + opts + \ + " org.apache.phoenix.tracingwebapp.http.Main " + args + +if command == 'start': + if not daemon_supported: + print >> sys.stderr, "daemon mode not supported on this platform" + sys.exit(-1) + + # run in the background + d = os.path.dirname(out_file_path) + if not os.path.exists(d): + os.makedirs(d) + with open(out_file_path, 'a+') as out: + context = daemon.DaemonContext( + pidfile = daemon.PidFile(pid_file_path, 'Trace Server already running, PID file found: %s' % pid_file_path), + stdout = out, + stderr = out, + ) + print 'starting Trace Server, logging to %s' % log_file_path + with context: + # this block is the main() for the forked daemon process + child = None + cmd = java_cmd % {'java': java, 'root_logger': 'INFO,DRFA', 'log_dir': phoenix_log_dir, 'log_file': phoenix_log_file} + + # notify the child when we're killed + def handler(signum, frame): + if child: + child.send_signal(signum) + sys.exit(0) + signal.signal(signal.SIGTERM, handler) + + print '%s launching %s' % (datetime.datetime.now(), cmd) + child = subprocess.Popen(cmd.split()) + sys.exit(child.wait()) + +elif command == 'stop': + if not daemon_supported: + print >> sys.stderr, "daemon mode not supported on this platform" + sys.exit(-1) + + if not os.path.exists(pid_file_path): + print >> sys.stderr, "no Trace Server to stop because PID file not found, %s" % pid_file_path + sys.exit(0) + + if not os.path.isfile(pid_file_path): + print >> sys.stderr, "PID path exists but is not a file! %s" % pid_file_path + sys.exit(1) + + pid = None + with open(pid_file_path, 'r') as p: + pid = int(p.read()) + if not pid: + sys.exit("cannot read PID file, %s" % pid_file_path) + + print "stopping Trace Server pid %s" % pid + with open(out_file_path, 'a+') as out: + print >> out, "%s terminating Trace Server" % datetime.datetime.now() + os.kill(pid, signal.SIGTERM) + +else: + # run in the foreground using defaults from log4j.properties + cmd = java_cmd % {'java': java, 'root_logger': 'INFO,console', 'log_dir': '.', 'log_file': 'psql.log'} + child = subprocess.Popen(cmd.split()) + sys.exit(child.wait()) \ No newline at end of file diff --git a/phoenix-tracing-webapp/README.md b/phoenix-tracing-webapp/README.md new file mode 100755 index 00000000000..d2af4486e28 --- /dev/null +++ b/phoenix-tracing-webapp/README.md @@ -0,0 +1,15 @@ +# TracingWebApp +1. Build the web application- + *mvn clean install* + +2. Start the TracingWebApp + *java -jar target/phoenix-tracing-webapp-4.5.0-SNAPSHOT-runnable.jar* + +3. View the Content - + *http://localhost:8864/webapp/#* + + ###Note + You can set the port of the trace app by -Dphoenix.traceserver.http.port={portNo} + + eg: + `-Dphoenix.traceserver.http.port=8887` server will start in 8887 diff --git a/phoenix-tracing-webapp/pom.xml b/phoenix-tracing-webapp/pom.xml new file mode 100755 index 00000000000..a13bbc344c8 --- /dev/null +++ b/phoenix-tracing-webapp/pom.xml @@ -0,0 +1,122 @@ + + + + + 4.0.0 + + + org.apache.phoenix + phoenix + 4.6.0-HBase-1.1-SNAPSHOT + + + phoenix-tracing-webapp + Phoenix - Tracing Web Application + Tracing web application will visualize the phoenix traces + + + ${project.basedir}/.. + + + + + org.eclipse.jetty + jetty-server + + ${jettyVersion} + provided + + + org.eclipse.jetty + jetty-webapp + + ${jettyVersion} + provided + + + org.apache.hadoop + hadoop-common + provided + + + org.apache.phoenix + phoenix-core + provided + + + org.apache.hbase + hbase-common + provided + + + commons-logging + commons-logging + provided + + + org.codehaus.jackson + jackson-core-asl + provided + + + org.codehaus.jackson + jackson-mapper-asl + provided + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + maven-assembly-plugin + + + runnable + package + + single + + + true + + + true + org.apache.phoenix.tracingwebapp.http.Main + + + ${project.artifactId}-${project.version} + + src/build/trace-server-runnable.xml + + + + + + + + + diff --git a/phoenix-tracing-webapp/src/build/trace-server-runnable.xml b/phoenix-tracing-webapp/src/build/trace-server-runnable.xml new file mode 100755 index 00000000000..21b3bde99e2 --- /dev/null +++ b/phoenix-tracing-webapp/src/build/trace-server-runnable.xml @@ -0,0 +1,60 @@ + + + + + runnable + + jar + + false + + + + metaInf-services + + + + + / + true + true + provided + + + + + src/main/webapp + + + + + README.md + / + true + + + diff --git a/phoenix-tracing-webapp/src/main/config/checkstyle/checker.xml b/phoenix-tracing-webapp/src/main/config/checkstyle/checker.xml new file mode 100755 index 00000000000..ecf39462fbe --- /dev/null +++ b/phoenix-tracing-webapp/src/main/config/checkstyle/checker.xml @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phoenix-tracing-webapp/src/main/config/checkstyle/header.txt b/phoenix-tracing-webapp/src/main/config/checkstyle/header.txt new file mode 100755 index 00000000000..2a4297155ea --- /dev/null +++ b/phoenix-tracing-webapp/src/main/config/checkstyle/header.txt @@ -0,0 +1,16 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/phoenix-tracing-webapp/src/main/config/checkstyle/suppressions.xml b/phoenix-tracing-webapp/src/main/config/checkstyle/suppressions.xml new file mode 100755 index 00000000000..6662eca9792 --- /dev/null +++ b/phoenix-tracing-webapp/src/main/config/checkstyle/suppressions.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/ConnectionFactory.java b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/ConnectionFactory.java new file mode 100644 index 00000000000..b7a1df1adcf --- /dev/null +++ b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/ConnectionFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.tracingwebapp.http; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +/** +* +* ConnectionFactory is to handle database connection +* +*/ +public class ConnectionFactory { + + private static Connection con; + //TODO : need to get port and host from configuration + protected static String PHOENIX_HOST = "localhost"; + protected static int PHOENIX_PORT = 2181; + + public static Connection getConnection() throws SQLException, ClassNotFoundException { + if (con == null || con.isClosed()) { + Class.forName("org.apache.phoenix.jdbc.PhoenixDriver"); + con = DriverManager.getConnection("jdbc:phoenix:"+PHOENIX_HOST+":"+PHOENIX_PORT); + } + return con; + } +} diff --git a/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/EntityFactory.java b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/EntityFactory.java new file mode 100644 index 00000000000..afb6312e2e8 --- /dev/null +++ b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/EntityFactory.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.tracingwebapp.http; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * EntityFactory is used to get results entities For SQL query + */ +public class EntityFactory { + + private String queryString; + protected Connection connection; + + public EntityFactory(Connection connection, String queryString) { + this.queryString = queryString; + this.connection = connection; + } + + public Map findSingle(Object[] params) throws SQLException { + List> objects = this.findMultiple(params); + + if (objects.size() != 1) { + throw new SQLException("Query did not produce one object it produced: " + + objects.size() + " objects."); + } + + Map object = objects.get(0); // get first record; + + return object; + } + + public List> findMultiple(Object[] params) + throws SQLException { + ResultSet rs = null; + PreparedStatement ps = null; + try { + ps = this.connection.prepareStatement(this.queryString); + for (int i = 0; i < params.length; ++i) { + ps.setObject(1, params[i]); + } + + rs = ps.executeQuery(); + return getEntitiesFromResultSet(rs); + } catch (SQLException e) { + throw (e); + } finally { + if (rs != null) { + rs.close(); + } + if (ps != null) { + ps.close(); + } + } + } + + protected static List> getEntitiesFromResultSet( + ResultSet resultSet) throws SQLException { + ArrayList> entities = new ArrayList<>(); + while (resultSet.next()) { + entities.add(getEntityFromResultSet(resultSet)); + } + return entities; + } + + protected static Map getEntityFromResultSet(ResultSet resultSet) + throws SQLException { + ResultSetMetaData metaData = resultSet.getMetaData(); + int columnCount = metaData.getColumnCount(); + Map resultsMap = new HashMap<>(); + for (int i = 1; i <= columnCount; ++i) { + String columnName = metaData.getColumnName(i).toLowerCase(); + Object object = resultSet.getObject(i); + resultsMap.put(columnName, object); + } + return resultsMap; + } + +} diff --git a/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/Main.java b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/Main.java new file mode 100755 index 00000000000..5875fc12a5e --- /dev/null +++ b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/Main.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.tracingwebapp.http; + +import java.net.URL; +import java.security.ProtectionDomain; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configured; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.util.Tool; +import org.apache.hadoop.util.ToolRunner; +import org.apache.log4j.BasicConfigurator; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.WebAppContext; + +/** + * tracing web app runner + */ +public final class Main extends Configured implements Tool { + + protected static final Log LOG = LogFactory.getLog(Main.class); + public static final String PHONIX_DBSERVER_PORT_KEY = + "phoenix.dbserver.port"; + public static final int DEFAULT_DBSERVER_PORT = 2181; + public static final String PHONIX_DBSERVER_HOST_KEY = + "phoenix.dbserver.host"; + public static final String DEFAULT_DBSERVER_HOST = "localhost"; + public static final String TRACE_SERVER_HTTP_PORT_KEY = + "phoenix.traceserver.http.port"; + public static final int DEFAULT_HTTP_PORT = 8864; + public static final String TRACE_SERVER_HTTP_JETTY_HOME_KEY = + "phoenix.traceserver.http.home"; + public static final String DEFAULT_HTTP_HOME = "/"; + + public static void main(String[] args) throws Exception { + int ret = ToolRunner.run(HBaseConfiguration.create(), new Main(), args); + System.exit(ret); + } + + @Override + public int run(String[] arg0) throws Exception { + // logProcessInfo(getConf()); + final int port = getConf().getInt(TRACE_SERVER_HTTP_PORT_KEY, + DEFAULT_HTTP_PORT); + BasicConfigurator.configure(); + final String home = getConf().get(TRACE_SERVER_HTTP_JETTY_HOME_KEY, + DEFAULT_HTTP_HOME); + //setting up the embedded server + ProtectionDomain domain = Main.class.getProtectionDomain(); + URL location = domain.getCodeSource().getLocation(); + String webappDirLocation = location.toString().split("target")[0] +"src/main/webapp"; + Server server = new Server(port); + WebAppContext root = new WebAppContext(); + + root.setContextPath(home); + root.setDescriptor(webappDirLocation + "/WEB-INF/web.xml"); + root.setResourceBase(webappDirLocation); + root.setParentLoaderPriority(true); + server.setHandler(root); + + server.start(); + server.join(); + return 0; + } +} diff --git a/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/TraceServlet.java b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/TraceServlet.java new file mode 100755 index 00000000000..de047baa49d --- /dev/null +++ b/phoenix-tracing-webapp/src/main/java/org/apache/phoenix/tracingwebapp/http/TraceServlet.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.phoenix.tracingwebapp.http; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.codehaus.jackson.map.ObjectMapper; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +/** + * + * Server to show trace information + * + */ +public class TraceServlet extends HttpServlet { + + private static final long serialVersionUID = -354285100083055559L; + private static Connection con; + protected String DEFAULT_LIMIT = "25"; + protected String DEFAULT_COUNTBY = "hostname"; + protected String LOGIC_AND = "AND"; + protected String LOGIC_OR = "OR"; + protected String TRACING_TABLE = "SYSTEM.TRACING_STATS"; + + + + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + //reading url params + String action = request.getParameter("action"); + String limit = request.getParameter("limit"); + String traceid = request.getParameter("traceid"); + String parentid = request.getParameter("parentid"); + String jsonObject = "{}"; + if ("getall".equals(action)) { + jsonObject = getAll(limit); + } else if ("getCount".equals(action)) { + jsonObject = getCount("description"); + } else if ("getDistribution".equals(action)) { + jsonObject = getCount(DEFAULT_COUNTBY); + } else if ("searchTrace".equals(action)) { + jsonObject = searchTrace(parentid, traceid, LOGIC_OR); + } else { + jsonObject = "{ \"Server\": \"Phoenix Tracing Web App\", \"API version\": 0.1 }"; + } + //response send as json + response.setContentType("application/json"); + String output = jsonObject; + PrintWriter out = response.getWriter(); + out.print(output); + out.flush(); + } + + //get all trace results with limit count + protected String getAll(String limit) { + String json = null; + if(limit == null) { + limit = DEFAULT_LIMIT; + } + String sqlQuery = "SELECT * FROM " + TRACING_TABLE + " LIMIT "+limit; + json = getResults(sqlQuery); + return getJson(json); + } + + //get count on traces can pick on param to count + protected String getCount(String countby) { + String json = null; + if(countby == null) { + countby = DEFAULT_COUNTBY; + } + String sqlQuery = "SELECT "+countby+", COUNT(*) AS count FROM " + TRACING_TABLE + " GROUP BY "+countby+" HAVING COUNT(*) > 1 "; + json = getResults(sqlQuery); + return json; + } + + //search the trace over parent id or trace id + protected String searchTrace(String parentId, String traceId,String logic) { + String json = null; + String query = null; + if(parentId != null && traceId != null) { + query = "SELECT * FROM " + TRACING_TABLE + " WHERE parent_id="+parentId+" "+logic+" trace_id="+traceId; + }else if (parentId != null && traceId == null) { + query = "SELECT * FROM " + TRACING_TABLE + " WHERE parent_id="+parentId; + }else if(parentId == null && traceId != null) { + query = "SELECT * FROM " + TRACING_TABLE + " WHERE trace_id="+traceId; + } + json = getResults(query); + return getJson(json); + } + + //return json string + protected String getJson(String json) { + String output = json.toString().replace("_id\":", "_id\":\"") + .replace(",\"hostname", "\",\"hostname") + .replace(",\"parent", "\",\"parent") + .replace(",\"end", "\",\"end"); + return output; + } + + //get results with passing sql query + protected String getResults(String sqlQuery) { + String json = null; + if(sqlQuery == null){ + json = "{error:true,msg:'SQL was null'}"; + }else{ + try { + con = ConnectionFactory.getConnection(); + EntityFactory nutrientEntityFactory = new EntityFactory(con,sqlQuery); + List> nutrients = nutrientEntityFactory + .findMultiple(new Object[] {}); + ObjectMapper mapper = new ObjectMapper(); + json = mapper.writeValueAsString(nutrients); + } catch (Exception e) { + json = "{error:true,msg:'Serrver Error:"+e.getMessage()+"'}"; + } finally { + if (con != null) { + try { + con.close(); + } catch (SQLException e) { + json = "{error:true,msg:'SQL Serrver Error:"+e.getMessage()+"'}"; + } + } + } + } + return json; + } +} diff --git a/phoenix-tracing-webapp/src/main/webapp/WEB-INF/web.xml b/phoenix-tracing-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 00000000000..ed4ced2b514 --- /dev/null +++ b/phoenix-tracing-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + Trace + org.apache.phoenix.tracingwebapp.http.TraceServlet + + + Trace + /trace/* + + diff --git a/phoenix-tracing-webapp/src/main/webapp/index.html b/phoenix-tracing-webapp/src/main/webapp/index.html new file mode 100755 index 00000000000..7f131fc33fd --- /dev/null +++ b/phoenix-tracing-webapp/src/main/webapp/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Phoenix Tracing WebApp + + + +

Phoenix Tracing Web App

+ + + diff --git a/pom.xml b/pom.xml index 703831ab5c2..161343a42d6 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ phoenix-pherf phoenix-spark phoenix-assembly + phoenix-tracing-webapp @@ -110,6 +111,7 @@ 2.7 2.1.2 1.3.0-incubating + 8.1.7.v20120910 1.8.5