From f27e47cb1828edddae98737240e0031b3b9d914d Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Fri, 6 Aug 2010 02:25:23 +0000 Subject: [PATCH] CSPACE-2588: Add a simple profiling utility class --- .../CollectionSpaceJaxRsApplication.java | 10 +- .../client/sample/Sample.java | 6 +- .../services/common/ServiceMain.java | 358 +++++++++--------- .../services/common/profile/Profiler.java | 156 ++++++++ .../client/java/RepositoryJavaClientImpl.java | 13 +- 5 files changed, 357 insertions(+), 186 deletions(-) create mode 100644 services/common/src/main/java/org/collectionspace/services/common/profile/Profiler.java diff --git a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CollectionSpaceJaxRsApplication.java b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CollectionSpaceJaxRsApplication.java index dcf50b38e..dd974c382 100644 --- a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CollectionSpaceJaxRsApplication.java +++ b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CollectionSpaceJaxRsApplication.java @@ -49,6 +49,7 @@ import java.util.Set; import org.collectionspace.services.authorization.PermissionResource; import org.collectionspace.services.authorization.RoleResource; import org.collectionspace.services.common.security.SecurityInterceptor; +import org.collectionspace.services.common.profile.Profiler; /** * CollectionSpaceJaxRsApplication, the root application @@ -61,9 +62,16 @@ import org.collectionspace.services.common.security.SecurityInterceptor; public class CollectionSpaceJaxRsApplication extends Application { private Set singletons = new HashSet(); - private Set> empty = new HashSet>(); + private Set> empty = new HashSet>(); public CollectionSpaceJaxRsApplication() { + // + // Setup the profiler logger + // + Profiler.setup(); + // + // Instantiate all our JaxRS resources + // singletons.add(new SecurityInterceptor()); singletons.add(new AccountResource()); singletons.add(new RoleResource()); diff --git a/services/collectionobject/sample/sample/src/main/java/org/collectionspace/services/collectionobject/client/sample/Sample.java b/services/collectionobject/sample/sample/src/main/java/org/collectionspace/services/collectionobject/client/sample/Sample.java index 799446a1a..0eedbaa11 100644 --- a/services/collectionobject/sample/sample/src/main/java/org/collectionspace/services/collectionobject/client/sample/Sample.java +++ b/services/collectionobject/sample/sample/src/main/java/org/collectionspace/services/collectionobject/client/sample/Sample.java @@ -211,9 +211,9 @@ public class Sample { depts.add("urn:org.collectionspace.services.department:Registrar"); depts.add("urn:org.walkerart.department:Fine Art"); collectionObject.setAge(""); // Test using an empty String. - collectionObject.setBriefDescription("Papier mache bird mask with horns, " + - "painted red with black and yellow spots. " + - "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns)."); +// collectionObject.setBriefDescription("Papier mache bird mask with horns, " + +// "painted red with black and yellow spots. " + +// "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns)."); MultipartOutput multipart = new MultipartOutput(); OutputPart commonPart = multipart.addPart(collectionObject, diff --git a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java index f76dbb9d4..0cfbcfeb4 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java +++ b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java @@ -1,179 +1,179 @@ -/** - * Copyright 2009 University of California at Berkeley - */ -package org.collectionspace.services.common; - -import java.util.Hashtable; -import java.util.List; - -import org.collectionspace.services.common.config.ServicesConfigReaderImpl; -import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl; -import org.collectionspace.services.common.tenant.TenantBindingType; -import org.collectionspace.services.common.types.PropertyItemType; -import org.collectionspace.services.common.types.PropertyType; -import org.collectionspace.services.nuxeo.client.java.NuxeoConnector; -import org.collectionspace.services.nuxeo.client.java.TenantRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Main class for Services layer. It reads configuration and performs service - * level initialization. It is a singleton. - * @author - */ -public class ServiceMain { - - /** - * volatile is used here to assume about ordering (post JDK 1.5) - */ - private static volatile ServiceMain instance = null; - final Logger logger = LoggerFactory.getLogger(ServiceMain.class); - private NuxeoConnector nuxeoConnector; - private String serverRootDir = null; - private ServicesConfigReaderImpl servicesConfigReader; - private TenantBindingConfigReaderImpl tenantBindingConfigReader; - - private ServiceMain() { - } - - /** - * getInstance returns the ServiceMain singleton instance after proper - * initialization in a thread-safe manner - * @return - */ - public static ServiceMain getInstance() { - if (instance == null) { - synchronized (ServiceMain.class) { - if (instance == null) { - ServiceMain temp = new ServiceMain(); - try { - temp.initialize(); - } catch (Exception e) { - instance = null; - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new RuntimeException(e); - } - } - instance = temp; - } - } - } - return instance; - } - - private void initialize() throws Exception { - setServerRootDir(); - readConfig(); - propagateConfiguredProperties(); - if (getClientType().equals(ClientType.JAVA)) { - nuxeoConnector = NuxeoConnector.getInstance(); - nuxeoConnector.initialize( - getServicesConfigReader().getConfiguration().getRepositoryClient()); - } - } - - /** - * release releases all resources occupied by service layer infrastructure - * but not necessarily those occupied by individual services - */ - public void release() { - try { - if (nuxeoConnector != null) { - nuxeoConnector.release(); - } - instance = null; - } catch (Exception e) { - e.printStackTrace(); - //gobble it - } - } - - private void readConfig() throws Exception { - //read service config - servicesConfigReader = new ServicesConfigReaderImpl(getServerRootDir()); - getServicesConfigReader().read(); - - tenantBindingConfigReader = new TenantBindingConfigReaderImpl(getServerRootDir()); - getTenantBindingConfigReader().read(); - } - - private void propagateConfiguredProperties() { - List repoPropListHolder = - servicesConfigReader.getConfiguration().getRepositoryClient().getProperties(); - if (repoPropListHolder != null && !repoPropListHolder.isEmpty()) { - List propList = repoPropListHolder.get(0).getItem(); - if (propList != null && !propList.isEmpty()) { - tenantBindingConfigReader.setDefaultPropertiesOnTenants(propList, true); - } - } - } - - void retrieveAllWorkspaceIds() throws Exception { - //all configs are read, connector is initialized, retrieve workspaceids - Hashtable tenantBindings = - getTenantBindingConfigReader().getTenantBindings(); - TenantRepository.get().setup(tenantBindings); - } - - /** - * getWorkspaceId returns workspace id for given tenant and service name - * @param tenantId - * @param serviceName - * @return - */ - public String getWorkspaceId(String tenantId, String serviceName) { - return TenantRepository.get().getWorkspaceId(tenantId, serviceName); - } - - /** - * @return the nuxeoConnector - */ - public NuxeoConnector getNuxeoConnector() { - return nuxeoConnector; - } - - /** - * @return the serverRootDir - */ - public String getServerRootDir() { - return serverRootDir; - } - - private void setServerRootDir() { - serverRootDir = System.getProperty("jboss.server.home.dir"); - if (serverRootDir == null) { - serverRootDir = "."; //assume server is started from server root, e.g. server/cspace - } - } - - - /** - * @return the serviceConfig - */ - public ServiceConfig getServiceConfig() { - return getServicesConfigReader().getConfiguration(); - } - - /** - * @return the clientType - */ - public ClientType getClientType() { - return getServicesConfigReader().getClientType(); - } - - /** - * @return the servicesConfigReader - */ - public ServicesConfigReaderImpl getServicesConfigReader() { - return servicesConfigReader; - } - - /** - * @return the tenantBindingConfigReader - */ - public TenantBindingConfigReaderImpl getTenantBindingConfigReader() { - return tenantBindingConfigReader; - } -} +/** + * Copyright 2009-2010 University of California at Berkeley + */ +package org.collectionspace.services.common; + +import java.util.Hashtable; +import java.util.List; + +import org.collectionspace.services.common.config.ServicesConfigReaderImpl; +import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl; +import org.collectionspace.services.common.tenant.TenantBindingType; +import org.collectionspace.services.common.types.PropertyItemType; +import org.collectionspace.services.common.types.PropertyType; +import org.collectionspace.services.nuxeo.client.java.NuxeoConnector; +import org.collectionspace.services.nuxeo.client.java.TenantRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Main class for Services layer. It reads configuration and performs service + * level initialization. It is a singleton. + * @author + */ +public class ServiceMain { + + /** + * volatile is used here to assume about ordering (post JDK 1.5) + */ + private static volatile ServiceMain instance = null; + final Logger logger = LoggerFactory.getLogger(ServiceMain.class); + private NuxeoConnector nuxeoConnector; + private String serverRootDir = null; + private ServicesConfigReaderImpl servicesConfigReader; + private TenantBindingConfigReaderImpl tenantBindingConfigReader; + + private ServiceMain() { + } + + /** + * getInstance returns the ServiceMain singleton instance after proper + * initialization in a thread-safe manner + * @return + */ + public static ServiceMain getInstance() { + if (instance == null) { + synchronized (ServiceMain.class) { + if (instance == null) { + ServiceMain temp = new ServiceMain(); + try { + temp.initialize(); + } catch (Exception e) { + instance = null; + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else { + throw new RuntimeException(e); + } + } + instance = temp; + } + } + } + return instance; + } + + private void initialize() throws Exception { + setServerRootDir(); + readConfig(); + propagateConfiguredProperties(); + if (getClientType().equals(ClientType.JAVA)) { + nuxeoConnector = NuxeoConnector.getInstance(); + nuxeoConnector.initialize( + getServicesConfigReader().getConfiguration().getRepositoryClient()); + } + } + + /** + * release releases all resources occupied by service layer infrastructure + * but not necessarily those occupied by individual services + */ + public void release() { + try { + if (nuxeoConnector != null) { + nuxeoConnector.release(); + } + instance = null; + } catch (Exception e) { + e.printStackTrace(); + //gobble it + } + } + + private void readConfig() throws Exception { + //read service config + servicesConfigReader = new ServicesConfigReaderImpl(getServerRootDir()); + getServicesConfigReader().read(); + + tenantBindingConfigReader = new TenantBindingConfigReaderImpl(getServerRootDir()); + getTenantBindingConfigReader().read(); + } + + private void propagateConfiguredProperties() { + List repoPropListHolder = + servicesConfigReader.getConfiguration().getRepositoryClient().getProperties(); + if (repoPropListHolder != null && !repoPropListHolder.isEmpty()) { + List propList = repoPropListHolder.get(0).getItem(); + if (propList != null && !propList.isEmpty()) { + tenantBindingConfigReader.setDefaultPropertiesOnTenants(propList, true); + } + } + } + + void retrieveAllWorkspaceIds() throws Exception { + //all configs are read, connector is initialized, retrieve workspaceids + Hashtable tenantBindings = + getTenantBindingConfigReader().getTenantBindings(); + TenantRepository.get().setup(tenantBindings); + } + + /** + * getWorkspaceId returns workspace id for given tenant and service name + * @param tenantId + * @param serviceName + * @return + */ + public String getWorkspaceId(String tenantId, String serviceName) { + return TenantRepository.get().getWorkspaceId(tenantId, serviceName); + } + + /** + * @return the nuxeoConnector + */ + public NuxeoConnector getNuxeoConnector() { + return nuxeoConnector; + } + + /** + * @return the serverRootDir + */ + public String getServerRootDir() { + return serverRootDir; + } + + private void setServerRootDir() { + serverRootDir = System.getProperty("jboss.server.home.dir"); + if (serverRootDir == null) { + serverRootDir = "."; //assume server is started from server root, e.g. server/cspace + } + } + + + /** + * @return the serviceConfig + */ + public ServiceConfig getServiceConfig() { + return getServicesConfigReader().getConfiguration(); + } + + /** + * @return the clientType + */ + public ClientType getClientType() { + return getServicesConfigReader().getClientType(); + } + + /** + * @return the servicesConfigReader + */ + public ServicesConfigReaderImpl getServicesConfigReader() { + return servicesConfigReader; + } + + /** + * @return the tenantBindingConfigReader + */ + public TenantBindingConfigReaderImpl getTenantBindingConfigReader() { + return tenantBindingConfigReader; + } +} diff --git a/services/common/src/main/java/org/collectionspace/services/common/profile/Profiler.java b/services/common/src/main/java/org/collectionspace/services/common/profile/Profiler.java new file mode 100644 index 000000000..a628bf82e --- /dev/null +++ b/services/common/src/main/java/org/collectionspace/services/common/profile/Profiler.java @@ -0,0 +1,156 @@ +/** + * Profiler.java + * + * {Purpose of This Class} + * + * {Other Notes Relating to This Class (Optional)} + * + * $LastChangedBy: $ + * $LastChangedRevision: $ + * $LastChangedDate: $ + * + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + * + * http://www.collectionspace.org + * http://wiki.collectionspace.org + * + * Copyright © 2009 {Contributing Institution} + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + */ +package org.collectionspace.services.common.profile; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * The Class Profiler. + */ +public class Profiler { + + /** The start time. */ + private long startTime = 0; + + /** The stop time. */ + private long stopTime = 0; + + /** The final time. */ + private long finalTime = 0; + + /** The message prefix. */ + private String messagePrefix = "Default profiler prefix:"; + + /** The profiler logger. */ + private static String LOG4J_CATEGORY = "perf.collectionspace"; + private static Logger profilerLogger = LoggerFactory.getLogger(LOG4J_CATEGORY); + + /** + * private default constructor. + */ + private Profiler() { + //empty default constructor + } + + /** + * Sets the message prefix. + * + * @param theMessagePrefix the new message prefix + */ + protected void setMessagePrefix(String theMessagePrefix) { + messagePrefix = theMessagePrefix + ":"; + } + + protected StringBuffer getMessagePrefix() { + return new StringBuffer(messagePrefix); + } + + /** + * Instantiates a new profiler. + * @param theObject + * + * @param theClass the the class + */ + public Profiler(Object theObject) { + if (theObject != null) { + this.setMessagePrefix(theObject.getClass().getSimpleName()); + } + } + /** + * Instantiates a new profiler. + * + * @param theMessagePrefix the the message prefix + */ + public Profiler(String theMessagePrefix) { + this.setMessagePrefix(theMessagePrefix); + } + + /* + * For some reason, we need to call this method "early" at startup time for our + * Logger instance to get created correctly. FIXME: REM - Can we figure this out and fix it? + */ + /** + * Setup. + */ + public static void setup() { + //do nothing + } + + /** + * Gets the logger. + * + * @return the logger + */ + protected Logger getLogger() { + return profilerLogger; + } + + /** + * Private log. + * + * @param inMessage the in message + */ + public void log(String inMessage) { + if (getLogger().isDebugEnabled() == true) { + StringBuffer finalMessage = getMessagePrefix(); + if (inMessage != null) { + finalMessage.append(inMessage); + } + getLogger().debug(finalMessage.toString()); + } + } + + /** + * Start + */ + public void start() { + if (getLogger().isDebugEnabled() == true) { + StringBuffer message = getMessagePrefix(); + message.append(">>>> Start >>>>"); + getLogger().debug(message.toString()); + } + startTime = System.currentTimeMillis(); + } + + /** + * Stop. + */ + public void stop() { + stopTime = System.currentTimeMillis(); + finalTime = finalTime + (stopTime - startTime); + if (getLogger().isDebugEnabled() == true) { + StringBuffer message = getMessagePrefix(); + message.append("<<<< Stopped <<<< ["); + message.append(finalTime); + message.append("ms]"); + message.append('\n'); + getLogger().debug(message.toString()); + } + } +} diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index 1ff686e61..8e98d20fc 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -35,6 +35,7 @@ import org.collectionspace.services.common.document.DocumentWrapperImpl; import org.collectionspace.services.nuxeo.util.NuxeoUtils; import org.collectionspace.services.common.query.IQueryManager; import org.collectionspace.services.common.repository.RepositoryClient; +import org.collectionspace.services.common.profile.Profiler; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; @@ -144,12 +145,14 @@ public class RepositoryJavaClientImpl implements RepositoryClient { } /** The logger. */ private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class); - +// private final Logger profilerLogger = LoggerFactory.getLogger("remperf"); +// private String foo = Profiler.createLogger(); /** * Instantiates a new repository java client impl. */ public RepositoryJavaClientImpl() { //Empty constructor + } /** @@ -640,12 +643,16 @@ public class RepositoryJavaClientImpl implements RepositoryClient { // If we have limit and/or offset, then pass true to get totalSize // in returned DocumentModelList. + Profiler profiler = new Profiler(this); + profiler.log("Executing NXQL query: " + query.toString()); + profiler.start(); if ((queryContext.docFilter.getOffset() > 0) || (queryContext.docFilter.getPageSize() > 0)) { docList = repoSession.query(query, null, queryContext.docFilter.getPageSize(), queryContext.docFilter.getOffset(), true); } else { docList = repoSession.query(query); } + profiler.stop(); //set repoSession to handle the document ((DocumentModelHandler) handler).setRepositorySession(repoSession); @@ -914,12 +921,12 @@ public class RepositoryJavaClientImpl implements RepositoryClient { // TODO This is a slow method for tenant-filter // We should make this a property that is indexed. // - query.append(" WHERE ecm:path STARTSWITH '/" + queryContext.domain + "'"); +// query.append(" WHERE ecm:path STARTSWITH '/" + queryContext.domain + "'"); // // Restrict search to the current tenant ID. Is the domain path filter (above) still needed? // - query.append(IQueryManager.SEARCH_QUALIFIER_AND + DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA + ":" + query.append(/*IQueryManager.SEARCH_QUALIFIER_AND +*/ " WHERE " + DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA + ":" + DocumentModelHandler.COLLECTIONSPACE_CORE_TENANTID + " = " + queryContext.tenantId); // -- 2.47.3