You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2009/09/15 16:52:13 UTC
svn commit: r815351 - in /sling/trunk/contrib/extensions/osgi-profiler: ./
src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/sling/ src/main/java/org/apache/sling/osgi/
src/main/java/org/apache/sling/os...
Author: bdelacretaz
Date: Tue Sep 15 14:52:13 2009
New Revision: 815351
URL: http://svn.apache.org/viewvc?rev=815351&view=rev
Log:
SLING-1109 - OSGi events recorder and console plugin
Added:
sling/trunk/contrib/extensions/osgi-profiler/ (with props)
sling/trunk/contrib/extensions/osgi-profiler/pom.xml (with props)
sling/trunk/contrib/extensions/osgi-profiler/src/
sling/trunk/contrib/extensions/osgi-profiler/src/main/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/impl/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/OsgiEventsRecorder.java (with props)
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/Activator.java (with props)
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/FelixConsolePlugin.java (with props)
sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/OsgiEventsRecorderImpl.java (with props)
sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/
sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/
sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/metatype/
sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/metatype/metatype.properties (with props)
Propchange: sling/trunk/contrib/extensions/osgi-profiler/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Tue Sep 15 14:52:13 2009
@@ -0,0 +1,15 @@
+target
+sling
+bin
+logs
+jackrabbit-repository
+derby.log
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+
Added: sling/trunk/contrib/extensions/osgi-profiler/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/osgi-profiler/pom.xml?rev=815351&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/osgi-profiler/pom.xml (added)
+++ sling/trunk/contrib/extensions/osgi-profiler/pom.xml Tue Sep 15 14:52:13 2009
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>6</version>
+ <relativePath>../../../parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.sling.osgi.event.recorder</artifactId>
+ <packaging>bundle</packaging>
+ <version>0.1-SNAPSHOT</version>
+
+ <name>Apache Sling OSGi events recorder</name>
+ <description>
+ Records OSGi events and displays a simple graph of events times
+ on the Felix Webconsole.
+ </description>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/event-recorder</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/event-recorder</developerConnection>
+ <url>http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/event-recorder</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.apache.sling.osgi.event.recorder
+ </Export-Package>
+ <Private-Package>
+ org.apache.sling.osgi.event.recorder.impl.*
+ </Private-Package>
+ <DynamicImport-Package>
+ org.apache.felix.webconsole
+ </DynamicImport-Package>
+ <Bundle-Activator>
+ org.apache.sling.osgi.event.recorder.impl.Activator
+ </Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <excludePackageNames>
+ org.apache.sling.osgi.event.recorder.impl
+ </excludePackageNames>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.webconsole</artifactId>
+ <version>1.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
Propchange: sling/trunk/contrib/extensions/osgi-profiler/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/OsgiEventsRecorder.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/OsgiEventsRecorder.java?rev=815351&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/OsgiEventsRecorder.java (added)
+++ sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/OsgiEventsRecorder.java Tue Sep 15 14:52:13 2009
@@ -0,0 +1,62 @@
+/*
+ * 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.sling.osgi.event.recorder;
+
+import java.util.Iterator;
+
+/** Record OSGi events and give access to them for display, profiling, etc. */
+public interface OsgiEventsRecorder {
+
+ public static class RecordedEvent {
+ public RecordedEvent(String entity, String id, String action) {
+ this.entity = entity;
+ this.id = id;
+ this.action = action;
+ this.timestamp = System.currentTimeMillis();
+ }
+
+ /** The OSGi "entity" (framework, bundle, service, etc.)
+ * that this event refers to */
+ public final String entity;
+
+ /** The entiy ID (bundle symbolic name, etc.) */
+ public final String id;
+
+ /** What happened to the entity (STARTED, etc) */
+ public final String action;
+
+ /** Event timestamp (clock time) */
+ public final long timestamp;
+ }
+
+ /** When the service started */
+ long getStartupTimestamp();
+
+ /** Timestamp of latest event (used to compute graph scales) */
+ long getLastTimestamp();
+
+ /** Clear the list of events and reset startup time */
+ void clear();
+
+ /** True if recording is enabled */
+ boolean isActive();
+
+ /** Return an Iterator on our recorded events */
+ Iterator<RecordedEvent> getEvents();
+}
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/OsgiEventsRecorder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/OsgiEventsRecorder.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/Activator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/Activator.java?rev=815351&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/Activator.java (added)
+++ sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/Activator.java Tue Sep 15 14:52:13 2009
@@ -0,0 +1,33 @@
+/*
+ * 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.sling.osgi.event.recorder.impl;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+ public void start(BundleContext ctx) throws Exception {
+ FelixConsolePlugin.initPlugin(ctx);
+ }
+
+ public void stop(BundleContext ctx) throws Exception {
+ FelixConsolePlugin.destroyPlugin();
+ }
+}
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/Activator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/Activator.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/FelixConsolePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/FelixConsolePlugin.java?rev=815351&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/FelixConsolePlugin.java (added)
+++ sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/FelixConsolePlugin.java Tue Sep 15 14:52:13 2009
@@ -0,0 +1,202 @@
+/*
+ * 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.sling.osgi.event.recorder.impl;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.sling.osgi.event.recorder.OsgiEventsRecorder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+
+/** Display recorded events as a simple graph on the Felix web console */
+@SuppressWarnings("serial")
+public class FelixConsolePlugin extends AbstractWebConsolePlugin {
+
+ public static final String LABEL = "OSGiEventsRecorder";
+ public static final String TITLE = "OSGi Events Recorder";
+
+ private static FelixConsolePlugin instance;
+ private ServiceRegistration serviceRegistration;
+ private ServiceTracker osgiEventsRecorderTracker;
+ private String lastClearString = "" + System.currentTimeMillis();
+
+ private static final String S = "overflow:visible; white-space:nowrap; text-align:right; padding: 2px; margin: 2px; ";
+ private static Map<String, String> styles = new HashMap<String, String>();
+ static {
+ styles.put(OsgiEventsRecorderImpl.ENTITY_BUNDLE, S + "background-color:#FFCACD; ");
+ styles.put(OsgiEventsRecorderImpl.ENTITY_FRAMEWORK, S + "background-color:#DCDCDC; ");
+ styles.put(OsgiEventsRecorderImpl.ENTITY_CONFIG, S + "background-color:#FFD700; ");
+ styles.put(OsgiEventsRecorderImpl.ENTITY_SERVICE, S + "background-color:#ADFF2F; ");
+ }
+
+ public void activate(BundleContext ctx) {
+ super.activate(ctx);
+
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(Constants.SERVICE_DESCRIPTION, "Web Console Plugin to display/profile OSGi events");
+ props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+ props.put(Constants.SERVICE_PID, getClass().getName());
+ props.put(WebConsoleConstants.PLUGIN_LABEL, LABEL);
+
+ serviceRegistration = ctx.registerService(WebConsoleConstants.SERVICE_NAME, this, props);
+ osgiEventsRecorderTracker = new ServiceTracker(ctx, OsgiEventsRecorder.class.getName(), null);
+ osgiEventsRecorderTracker.open();
+ }
+
+ public void deactivate() {
+ if(serviceRegistration != null) {
+ serviceRegistration.unregister();
+ serviceRegistration = null;
+ }
+
+ if(osgiEventsRecorderTracker != null) {
+ osgiEventsRecorderTracker.close();
+ }
+ super.deactivate();
+ }
+
+ public static void initPlugin(BundleContext context) {
+ if (instance == null) {
+ FelixConsolePlugin tmp = new FelixConsolePlugin();
+ tmp.activate(context);
+ instance = tmp;
+ }
+ }
+
+ public static void destroyPlugin() {
+ if (instance != null) {
+ try {
+ instance.deactivate();
+ } finally {
+ instance = null;
+ }
+ }
+ }
+
+ @Override
+ public String getLabel() {
+ return LABEL;
+ }
+
+ @Override
+ public String getTitle() {
+ return TITLE;
+ }
+
+ @Override
+ protected void renderContent(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ if(osgiEventsRecorderTracker == null) {
+ throw new ServletException("ServiceTracker not found");
+ }
+
+ final OsgiEventsRecorder rec = (OsgiEventsRecorder)osgiEventsRecorderTracker.getService();
+ if(rec == null) {
+ throw new ServletException("OsgiEventsRecorder not found");
+ }
+
+ // Use unique numbers to clear, to avoid clearing again if the browser is refreshed
+ final String clear = request.getParameter("clear");
+ if(clear != null && !clear.equals(lastClearString)) {
+ lastClearString = clear;
+ rec.clear();
+ }
+
+ final Iterator<OsgiEventsRecorder.RecordedEvent> it = rec.getEvents();
+ final PrintWriter w = response.getWriter();
+
+ w.println("<div class='fullwidth'><div class='statusline'>");
+ w.println("This plugin displays a timeline of OSGi events.");
+ w.println("<br/>");
+ w.println("Times in brackets are milliseconds since the first event was received.");
+ w.println("<br/>");
+ w.println("To profile system startup, install the recorder bundle with start level 1 to have it start early.");
+ w.println("</div></div>");
+
+ // Compute scale: startTime is 0, lastTimestamp is 100%
+ final long startTime = rec.getStartupTimestamp();
+ final long endTime = rec.getLastTimestamp();
+ final float scale = 100.0f / (endTime - startTime);
+
+ final String clearURL = "./" + LABEL + "?clear=" + System.currentTimeMillis();
+ w.println("<h3>OSGi Events Timeline (<a href='" + clearURL + "'>Clear</a>)</h3>");
+ w.println("<div class='fullwidth'>");
+ if(rec.isActive()) {
+ int count = 0;
+ while(it.hasNext()) {
+ count++;
+ renderEvent(w, it.next(), startTime, scale);
+ }
+ w.println("</div>");
+ w.println("<div class='fullwidth'><div class='statusline'>");
+ w.println(count);
+ w.println(" OSGi events displayed.");
+ w.println("</div>");
+ } else {
+ w.println("<div class='fullwidth'><div class='statusline'>");
+ w.println("OSGi Event Recorder is currently <b>disabled</b> by configuration.");
+ w.println("</div>");
+ }
+ }
+
+ private void renderEvent(PrintWriter w, OsgiEventsRecorder.RecordedEvent e, long start, float scale) {
+ final long msec = e.timestamp - start;
+
+ // Compute color bar size and make sure the bar is visible
+ int percent = (int)((msec) * scale);
+ percent = Math.max(percent, 2);
+
+ // Get style according to entity
+ String style = styles.get(e.entity);
+ if(style == null) {
+ style = "";
+ }
+
+ w.print("<div style='");
+ w.print(style);
+ w.print("width:");
+ w.print(percent);
+ w.print("%'>");
+ if(e.id != null) {
+ w.print("<b>");
+ w.print(e.id);
+ w.print("</b> ");
+ }
+ w.print(e.entity);
+ w.print(" ");
+ w.print(e.action);
+ w.print(" <b>(");
+ w.print(msec);
+ w.println(")</b></div>");
+ }
+}
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/FelixConsolePlugin.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/FelixConsolePlugin.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/OsgiEventsRecorderImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/OsgiEventsRecorderImpl.java?rev=815351&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/OsgiEventsRecorderImpl.java (added)
+++ sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/OsgiEventsRecorderImpl.java Tue Sep 15 14:52:13 2009
@@ -0,0 +1,253 @@
+/*
+ * 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.sling.osgi.event.recorder.impl;
+
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.sling.osgi.event.recorder.OsgiEventsRecorder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Events recorder service implementation.
+ *
+ * @scr.component immediate="true"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ * @scr.property name="service.description" value="OSGi events recorder"
+ * @scr.service
+ */
+public class OsgiEventsRecorderImpl
+ implements OsgiEventsRecorder, BundleListener, FrameworkListener, ServiceListener, ConfigurationListener {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private ServiceRegistration configReg;
+ private BundleContext ctx;
+ private long startupTime;
+ private long lastTimestamp;
+ private List<RecordedEvent> events;
+
+ static final String ENTITY_FRAMEWORK = "Framework";
+ static final String ENTITY_BUNDLE = "Bundle";
+ static final String ENTITY_CONFIG = "Config";
+ static final String ENTITY_SERVICE = "Service";
+
+ /** @scr.property type="Integer" valueRef="DEFAULT_MAX_EVENTS_RECORDED" */
+ public static final String PROP_MAX_EVENTS_RECORDED = "max.events.recorded";
+ public static final int DEFAULT_MAX_EVENTS_RECORDED = 5000;
+ private int maxEvents;
+
+ /** @scr.property type="Boolean" valueRef="DEFAULT_ACTIVE" */
+ public static final String PROP_ACTIVE = "recorder.active";
+ public static final boolean DEFAULT_ACTIVE = false;
+ private boolean active;
+
+ public void activate(ComponentContext cc) {
+ Dictionary<?, ?> cfg = cc.getProperties();
+ Object o = cfg.get(PROP_ACTIVE);
+ if(o != null) {
+ active = ((Boolean)o).booleanValue();
+ } else {
+ active = DEFAULT_ACTIVE;
+ }
+ o = cfg.get(PROP_MAX_EVENTS_RECORDED);
+ if(o != null) {
+ maxEvents = ((Integer)o).intValue();
+ } else {
+ maxEvents = DEFAULT_MAX_EVENTS_RECORDED;
+ }
+
+ if(!active) {
+ log.info("Recorder deactivated by configuration");
+ return;
+ }
+ log.info("Activating recorder, a maximum of {} events will be recorded", maxEvents);
+
+ startupTime = System.currentTimeMillis();
+ ctx = cc.getBundleContext();
+ ctx.addBundleListener(this);
+ ctx.addFrameworkListener(this);
+ ctx.addServiceListener(this);
+ configReg = ctx.registerService(ConfigurationListener.class.getName(),
+ this, null);
+
+ events = new LinkedList<RecordedEvent>();
+
+ log.warn("The OSGi event recorder consumes resources when recording events, turn it off if not using it");
+ }
+
+ public void deactivate(ComponentContext cc) {
+ configReg.unregister();
+ ctx.removeServiceListener(this);
+ ctx.removeFrameworkListener(this);
+ ctx.removeBundleListener(this);
+ events = null;
+ }
+
+ public Iterator<RecordedEvent> getEvents() {
+ if(events == null) {
+ return new LinkedList<RecordedEvent>().iterator();
+ }
+ return events.iterator();
+ }
+
+ public void clear() {
+ if(events != null) {
+ synchronized (events) {
+ events.clear();
+ startupTime = System.currentTimeMillis();
+ }
+ }
+ }
+
+ public long getStartupTimestamp() {
+ return startupTime;
+ }
+
+ public long getLastTimestamp() {
+ return lastTimestamp;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ private void recordEvent(String entity, String id, String action) {
+ final RecordedEvent r = new RecordedEvent(entity, id, action);
+ synchronized (events) {
+ while(events.size() > maxEvents) {
+ events.remove(0);
+ }
+ // First event resets start time
+ if(events.size() == 0) {
+ startupTime = System.currentTimeMillis();
+ }
+ events.add(r);
+ lastTimestamp = r.timestamp;
+ }
+ }
+
+ public void frameworkEvent(FrameworkEvent e) {
+ if(events != null) {
+ recordEvent(ENTITY_FRAMEWORK, null, getFrameworkEventType(e.getType()));
+ }
+ }
+
+ public void bundleChanged(BundleEvent e) {
+ if(events != null) {
+ recordEvent(ENTITY_BUNDLE, e.getBundle().getSymbolicName(), getBundleEventType(e.getType()));
+ }
+ }
+
+ public void configurationEvent(ConfigurationEvent e) {
+ if(events != null) {
+ recordEvent(ENTITY_CONFIG, e.getPid(), "CHANGED");
+ }
+ }
+
+ public void serviceChanged(ServiceEvent e) {
+ if(events != null) {
+ final ServiceReference ref = e.getServiceReference();
+ final StringBuilder id = new StringBuilder();
+ final Object pid = ref.getProperty("service.pid");
+ final Object sid = ref.getProperty("service.id");
+ if(pid != null) {
+ id.append(pid.toString());
+ } else {
+ final Object o = ref.getProperty("objectClass");
+ if(o instanceof String []) {
+ id.append(Arrays.asList((String[])o).toString());
+ } else {
+ id.append(o.toString());
+ }
+ id.append(" (");
+ id.append(ref.getBundle().getSymbolicName());
+ id.append(" bundle)");
+ }
+ if(sid != null) {
+ id.append(" (id=");
+ id.append(sid);
+ id.append(")");
+ }
+ recordEvent(ENTITY_SERVICE, id.toString(), getServiceEventType(e.getType()));
+ }
+ }
+
+ private static String getBundleEventType(int t) {
+ if(t == BundleEvent.STARTED) {
+ return "STARTED";
+ } else if(t == BundleEvent.RESOLVED) {
+ return "RESOLVED";
+ } else if(t == BundleEvent.STOPPED) {
+ return "STOPPED";
+ } else if(t == BundleEvent.UNRESOLVED) {
+ return "UNRESOLVED";
+ } else if(t == BundleEvent.UNINSTALLED) {
+ return "UNINSTALLED";
+ } else if(t == BundleEvent.INSTALLED) {
+ return "INSTALLED";
+ } else if(t == BundleEvent.UPDATED) {
+ return "UPDATED";
+ }
+ return String.valueOf(t);
+ }
+
+ private static String getFrameworkEventType(int t) {
+ if(t == FrameworkEvent.STARTED) {
+ return "STARTED";
+ } else if(t == FrameworkEvent.ERROR) {
+ return "ERROR";
+ } else if(t == FrameworkEvent.INFO) {
+ return "INFO";
+ } else if(t == FrameworkEvent.PACKAGES_REFRESHED) {
+ return "PACKAGES_REFRESHED";
+ } else if(t == FrameworkEvent.STARTLEVEL_CHANGED) {
+ return "STARTLEVEL_CHANGED";
+ } else if(t == FrameworkEvent.WARNING) {
+ return "WARNING";
+ }
+ return String.valueOf(t);
+ }
+
+ private static String getServiceEventType(int t) {
+ if(t == ServiceEvent.MODIFIED) {
+ return "MODIFIED";
+ } else if(t == ServiceEvent.REGISTERED) {
+ return "REGISTERED";
+ } else if(t == ServiceEvent.UNREGISTERING) {
+ return "UNREGISTERING";
+ }
+ return String.valueOf(t);
+ }
+
+}
\ No newline at end of file
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/OsgiEventsRecorderImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/java/org/apache/sling/osgi/event/recorder/impl/OsgiEventsRecorderImpl.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=815351&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/metatype/metatype.properties (added)
+++ sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/metatype/metatype.properties Tue Sep 15 14:52:13 2009
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+org.apache.sling.osgi.event.recorder.impl.OsgiEventsRecorderImpl.name = Apache Sling OSGi Events Recorder
+
+max.events.recorded.name = Max.events recorded
+max.events.recorded.description = The maximum number of events \
+ to record. If more events are received, the oldest ones are \
+ deleted to make room.
+
+recorder.active.name = Recorder active?
+recorder.active.description = Enable/disable events recording
+
+
\ No newline at end of file
Propchange: sling/trunk/contrib/extensions/osgi-profiler/src/main/resources/OSGI-INF/metatype/metatype.properties
------------------------------------------------------------------------------
svn:eol-style = native