[KARAF-3205] Refactor create-dump to be more low level
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/e55fd0a0 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/e55fd0a0 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/e55fd0a0 Branch: refs/heads/master Commit: e55fd0a05e651ebfe8dac26f1de56e356afe034f Parents: 9ec4442 Author: Guillaume Nodet <[email protected]> Authored: Tue Sep 9 18:43:49 2014 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Tue Sep 9 18:43:57 2014 +0200 ---------------------------------------------------------------------- assemblies/features/framework/pom.xml | 10 + .../resources/etc/config.properties | 1 + diagnostic/NOTICE | 71 ----- diagnostic/boot/NOTICE | 71 +++++ diagnostic/boot/pom.xml | 73 +++++ .../org/apache/karaf/diagnostic/core/Dump.java | 85 ++++++ .../karaf/diagnostic/core/DumpDestination.java | 42 +++ .../karaf/diagnostic/core/DumpProvider.java | 29 ++ .../common/ClosingEntryOutputStreamWrapper.java | 75 +++++ .../core/common/DirectoryDumpDestination.java | 59 ++++ .../core/common/TextDumpProvider.java | 66 +++++ .../core/common/ZipDumpDestination.java | 85 ++++++ .../diagnostic/core/internal/Activator.java | 54 ++++ .../core/providers/BundleDumpProvider.java | 85 ++++++ .../core/providers/EnvironmentDumpProvider.java | 290 ++++++++++++++++++ .../core/providers/HeapDumpProvider.java | 68 +++++ .../core/providers/MemoryDumpProvider.java | 54 ++++ .../core/providers/ThreadDumpProvider.java | 118 ++++++++ .../src/main/resources/OSGI-INF/bundle.info | 16 + diagnostic/core/NOTICE | 71 +++++ diagnostic/core/pom.xml | 134 +++++++++ .../karaf/diagnostic/command/DumpCommand.java | 86 ++++++ .../diagnostic/common/FeaturesDumpProvider.java | 78 +++++ .../diagnostic/common/LogDumpProvider.java | 81 ++++++ .../diagnostic/common/TextDumpProvider.java | 66 +++++ .../karaf/diagnostic/internal/Activator.java | 100 +++++++ .../management/DiagnosticDumpMBean.java | 42 +++ .../internal/DiagnosticDumpMBeanImpl.java | 76 +++++ .../src/main/resources/OSGI-INF/bundle.info | 16 + diagnostic/pom.xml | 104 +------ .../karaf/diagnostic/command/DumpCommand.java | 97 ------- .../diagnostic/core/DiagnosticDumpMBean.java | 42 --- .../karaf/diagnostic/core/DumpDestination.java | 42 --- .../karaf/diagnostic/core/DumpProvider.java | 29 -- .../common/ClosingEntryOutputStreamWrapper.java | 75 ----- .../core/common/DirectoryDumpDestination.java | 55 ---- .../core/common/TextDumpProvider.java | 66 ----- .../core/common/ZipDumpDestination.java | 79 ----- .../core/internal/BundleDumpProvider.java | 85 ------ .../core/internal/DiagnosticDumpMBeanImpl.java | 89 ------ .../core/internal/EnvironmentDumpProvider.java | 291 ------------------- .../core/internal/FeaturesDumpProvider.java | 79 ----- .../core/internal/HeapDumpProvider.java | 59 ---- .../core/internal/LogDumpProvider.java | 83 ------ .../core/internal/MemoryDumpProvider.java | 54 ---- .../core/internal/ThreadDumpProvider.java | 118 -------- .../core/internal/osgi/Activator.java | 131 --------- .../src/main/resources/OSGI-INF/bundle.info | 18 -- pom.xml | 6 + 49 files changed, 2045 insertions(+), 1659 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/assemblies/features/framework/pom.xml ---------------------------------------------------------------------- diff --git a/assemblies/features/framework/pom.xml b/assemblies/features/framework/pom.xml index 2652bdc..52aaffd 100644 --- a/assemblies/features/framework/pom.xml +++ b/assemblies/features/framework/pom.xml @@ -60,6 +60,11 @@ <scope>runtime</scope> </dependency> <dependency> + <groupId>org.apache.karaf.diagnostic</groupId> + <artifactId>org.apache.karaf.diagnostic.boot</artifactId> + <scope>runtime</scope> + </dependency> + <dependency> <groupId>org.eclipse</groupId> <artifactId>osgi</artifactId> <scope>runtime</scope> @@ -236,6 +241,11 @@ <destFileName>karaf-jmx-boot.jar</destFileName> </artifactItem> <artifactItem> + <groupId>org.apache.karaf.diagnostic</groupId> + <artifactId>org.apache.karaf.diagnostic.boot</artifactId> + <outputDirectory>target/classes/resources/lib</outputDirectory> + </artifactItem> + <artifactItem> <groupId>org.apache.karaf</groupId> <artifactId>org.apache.karaf.exception</artifactId> <outputDirectory>target/classes/resources/lib/endorsed</outputDirectory> http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties ---------------------------------------------------------------------- diff --git a/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties b/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties index b0978da..93d6c54 100644 --- a/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties +++ b/assemblies/features/framework/src/main/filtered-resources/resources/etc/config.properties @@ -74,6 +74,7 @@ org.osgi.framework.system.packages= \ org.apache.karaf.jaas.boot;version="${karaf.osgi.version}", \ org.apache.karaf.jaas.boot.principal;version="${karaf.osgi.version}", \ org.apache.karaf.management.boot;version="${karaf.osgi.version}", \ + org.apache.karaf.diagnostic.core;version="${karaf.osgi.version}", \ org.apache.karaf.version;version="${karaf.osgi.version}", \ ${jre-${java.specification.version}} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/NOTICE ---------------------------------------------------------------------- diff --git a/diagnostic/NOTICE b/diagnostic/NOTICE deleted file mode 100644 index b70f1f9..0000000 --- a/diagnostic/NOTICE +++ /dev/null @@ -1,71 +0,0 @@ -Apache Karaf -Copyright 2010-2014 The Apache Software Foundation - - -I. Included Software - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). -Licensed under the Apache License 2.0. - -This product uses software developed at -The OSGi Alliance (http://www.osgi.org/). -Copyright (c) OSGi Alliance (2000, 2010). -Licensed under the Apache License 2.0. - -This product includes software developed at -OW2 (http://www.ow2.org/). -Licensed under the BSD License. - -This product includes software developed at -OPS4J (http://www.ops4j.org/). -Licensed under the Apache License 2.0. - -This product includes software developed at -Eclipse Foundation (http://www.eclipse.org/). -Licensed under the EPL. - -This product includes software written by -Antony Lesuisse. -Licensed under Public Domain. - - -II. Used Software - -This product uses software developed at -FUSE Source (http://www.fusesource.org/). -Licensed under the Apache License 2.0. - -This product uses software developed at -AOP Alliance (http://aopalliance.sourceforge.net/). -Licensed under the Public Domain. - -This product uses software developed at -Tanuki Software (http://www.tanukisoftware.com/). -Licensed under the Apache License 2.0. - -This product uses software developed at -Jasypt (http://jasypt.sourceforge.net/). -Licensed under the Apache License 2.0. - -This product uses software developed at -JLine (http://jline.sourceforge.net). -Licensed under the BSD License. - -This product uses software developed at -SLF4J (http://www.slf4j.org/). -Licensed under the MIT License. - -This product uses software developed at -SpringSource (http://www.springsource.org/). -Licensed under the Apache License 2.0. - -This product includes software from http://www.json.org. -Copyright (c) 2002 JSON.org - - -III. License Summary -- Apache License 2.0 -- BSD License -- EPL License -- MIT License http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/NOTICE ---------------------------------------------------------------------- diff --git a/diagnostic/boot/NOTICE b/diagnostic/boot/NOTICE new file mode 100644 index 0000000..b70f1f9 --- /dev/null +++ b/diagnostic/boot/NOTICE @@ -0,0 +1,71 @@ +Apache Karaf +Copyright 2010-2014 The Apache Software Foundation + + +I. Included Software + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). +Licensed under the Apache License 2.0. + +This product uses software developed at +The OSGi Alliance (http://www.osgi.org/). +Copyright (c) OSGi Alliance (2000, 2010). +Licensed under the Apache License 2.0. + +This product includes software developed at +OW2 (http://www.ow2.org/). +Licensed under the BSD License. + +This product includes software developed at +OPS4J (http://www.ops4j.org/). +Licensed under the Apache License 2.0. + +This product includes software developed at +Eclipse Foundation (http://www.eclipse.org/). +Licensed under the EPL. + +This product includes software written by +Antony Lesuisse. +Licensed under Public Domain. + + +II. Used Software + +This product uses software developed at +FUSE Source (http://www.fusesource.org/). +Licensed under the Apache License 2.0. + +This product uses software developed at +AOP Alliance (http://aopalliance.sourceforge.net/). +Licensed under the Public Domain. + +This product uses software developed at +Tanuki Software (http://www.tanukisoftware.com/). +Licensed under the Apache License 2.0. + +This product uses software developed at +Jasypt (http://jasypt.sourceforge.net/). +Licensed under the Apache License 2.0. + +This product uses software developed at +JLine (http://jline.sourceforge.net). +Licensed under the BSD License. + +This product uses software developed at +SLF4J (http://www.slf4j.org/). +Licensed under the MIT License. + +This product uses software developed at +SpringSource (http://www.springsource.org/). +Licensed under the Apache License 2.0. + +This product includes software from http://www.json.org. +Copyright (c) 2002 JSON.org + + +III. License Summary +- Apache License 2.0 +- BSD License +- EPL License +- MIT License http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/pom.xml ---------------------------------------------------------------------- diff --git a/diagnostic/boot/pom.xml b/diagnostic/boot/pom.xml new file mode 100644 index 0000000..3f9b882 --- /dev/null +++ b/diagnostic/boot/pom.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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/xsd/maven-4.0.0.xsd"> + + <!-- + + 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. + --> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.karaf</groupId> + <artifactId>karaf</artifactId> + <version>4.0.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <groupId>org.apache.karaf.diagnostic</groupId> + <artifactId>org.apache.karaf.diagnostic.boot</artifactId> + <packaging>bundle</packaging> + <name>Apache Karaf :: Diagnostic :: Boot</name> + <description>Diagnostic Core implementation</description> + + <properties> + <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory> + </properties> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Export-Package> + org.apache.karaf.diagnostic.core + </Export-Package> + <Private-Package> + org.apache.karaf.diagnostic.core.common, + org.apache.karaf.diagnostic.core.internal, + org.apache.karaf.diagnostic.core.providers + </Private-Package> + <Karaf-Activator> + org.apache.karaf.diagnostic.core.internal.Activator + </Karaf-Activator> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java new file mode 100644 index 0000000..3a4df0a --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/Dump.java @@ -0,0 +1,85 @@ +/* + * 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.karaf.diagnostic.core; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination; +import org.apache.karaf.diagnostic.core.common.ZipDumpDestination; +import org.apache.karaf.diagnostic.core.providers.BundleDumpProvider; +import org.apache.karaf.diagnostic.core.providers.EnvironmentDumpProvider; +import org.apache.karaf.diagnostic.core.providers.HeapDumpProvider; +import org.apache.karaf.diagnostic.core.providers.MemoryDumpProvider; +import org.apache.karaf.diagnostic.core.providers.ThreadDumpProvider; +import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; + +/** + * Dump helper + */ +public final class Dump { + + public static DumpDestination directory(File file) { + return new DirectoryDumpDestination(file); + } + + public static DumpDestination zip(File file) { + return new ZipDumpDestination(file); + } + + public static void dump(BundleContext bundleContext, DumpDestination destination) { + List<DumpProvider> providers = new ArrayList<DumpProvider>(); + providers.add(new EnvironmentDumpProvider(bundleContext)); + providers.add(new MemoryDumpProvider()); + providers.add(new ThreadDumpProvider()); + providers.add(new HeapDumpProvider()); + providers.add(new BundleDumpProvider(bundleContext)); + for (DumpProvider provider : providers) { + try { + provider.createDump(destination); + } catch (Throwable t) { + // Ignore + } + } + try { + for (ServiceReference<DumpProvider> ref : bundleContext.getServiceReferences(DumpProvider.class, null)) { + DumpProvider provider = bundleContext.getService(ref); + try { + provider.createDump(destination); + } catch (Throwable t) { + // Ignore + } finally { + bundleContext.ungetService(ref); + } + } + } catch (InvalidSyntaxException e) { + // Ignore + } + try { + destination.save(); + } catch (Throwable t) { + // Ignore + } + System.out.println("Created dump " + destination.toString()); + } + + // Private constructor + private Dump() { } +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java new file mode 100644 index 0000000..39c4edc --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java @@ -0,0 +1,42 @@ +/* + * 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.karaf.diagnostic.core; + +import java.io.OutputStream; + +/** + * Destination for created dumps. + */ +public interface DumpDestination { + + /** + * Creates new entry in dump destination. + * + * Destination does not close returned output stream by default, dump + * provider should do this after completing write operation. + * + * @param name Name of file in destination. + * @return Output stream ready to write. + * @throws Exception When entry cannot be added. + */ + OutputStream add(String name) throws Exception; + + /** + * Complete creation of the dump. + */ + void save() throws Exception; + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java new file mode 100644 index 0000000..ec7724c --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java @@ -0,0 +1,29 @@ +/* + * 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.karaf.diagnostic.core; + +/** + * Interface which represents instance of tool which can provide dump + * information. + */ +public interface DumpProvider { + + /** + * Creates dump in given entry. + */ + void createDump(DumpDestination destination) throws Exception; + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java new file mode 100644 index 0000000..0c4f9db --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java @@ -0,0 +1,75 @@ +/* + * 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.karaf.diagnostic.core.common; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.ZipOutputStream; + +/** + * Output stream which closes entry instead closing whole stream. + */ +public class ClosingEntryOutputStreamWrapper extends OutputStream { + + /** + * Wrapped ZIP output stream. + */ + private ZipOutputStream outputStream; + + /** + * Creates new OutputStream. + * + * @param outputStream Wrapped output stream. + */ + public ClosingEntryOutputStreamWrapper(ZipOutputStream outputStream) { + this.outputStream = outputStream; + } + + /** + * {@inheritDoc} + */ + @Override + public void write(int b) throws IOException { + outputStream.write(b); + } + + /** + * {@inheritDoc} + */ + @Override + public void write(byte[] b) throws IOException { + outputStream.write(b); + } + + /** + * {@inheritDoc} + */ + @Override + public void write(byte[] b, int off, int len) + throws IOException { + outputStream.write(b, off, len); + } + + /** + * {@inheritDoc} + */ + @Override + public void close() throws IOException { + // close entry instead of closing zip stream. + outputStream.closeEntry(); + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java new file mode 100644 index 0000000..689ab34 --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java @@ -0,0 +1,59 @@ +/* + * 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.karaf.diagnostic.core.common; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; + +import org.apache.karaf.diagnostic.core.DumpDestination; + +/** + * Class which packages dumps to given directory. + */ +public class DirectoryDumpDestination implements DumpDestination { + + /** + * Directory where dump files will be created. + */ + private File directory; + + public DirectoryDumpDestination(File file) { + this.directory = file; + + if (!file.exists()) { + file.mkdirs(); + } + } + + public OutputStream add(String name) throws Exception { + File destination = new File(directory, name); + if (name.contains("/") || name.contains("\\")) { + // if name contains slashes we need to create sub directory + destination.getParentFile().mkdirs(); + } + return new FileOutputStream(destination); + } + + public void save() throws Exception { + // do nothing, all should be written to output streams + } + + @Override + public String toString() { + return "directory: " + directory; + } +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java new file mode 100644 index 0000000..0b97d6f --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java @@ -0,0 +1,66 @@ +/* + * 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.karaf.diagnostic.core.common; + +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +import org.apache.karaf.diagnostic.core.DumpDestination; +import org.apache.karaf.diagnostic.core.DumpProvider; + +/** + * Base class for dump providers which writes text to destination. + */ +public abstract class TextDumpProvider implements DumpProvider { + + /** + * Name of the file. + */ + private final String name; + + /** + * Creates new dump provider. + * + * @param name Name of the file. + */ + protected TextDumpProvider(String name) { + this.name = name; + } + + /** + * {@inheritDoc} + */ + @Override + public final void createDump(DumpDestination destination) throws Exception { + OutputStream outputStream = destination.add(name); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + try { + writeDump(outputStreamWriter); + } finally { + outputStreamWriter.close(); + outputStream.close(); + } + } + + /** + * This method should create output. + * + * @param outputStreamWriter Stream which points to file specified in constructor. + * @throws Exception If any problem occur. + */ + protected abstract void writeDump(OutputStreamWriter outputStreamWriter) throws Exception; + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java new file mode 100644 index 0000000..66481fb --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java @@ -0,0 +1,85 @@ +/* + * 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.karaf.diagnostic.core.common; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.apache.karaf.diagnostic.core.DumpDestination; + +/** + * Class which packages dumps to ZIP archive. + */ +public class ZipDumpDestination implements DumpDestination { + + /** + * Destination streem. + */ + private ZipOutputStream outputStream; + private File file; + + /** + * Creates new dump in given directory. + * + * @param directory Target directory. + * @param name Name of the archive. + */ + public ZipDumpDestination(File directory, String name) { + this(new File(directory, name)); + } + + /** + * Creates new dump in given file (zip archive). + * + * @param file Destination file. + */ + public ZipDumpDestination(File file) { + try { + this.file = file; + outputStream = new ZipOutputStream(new FileOutputStream( + file)); + } catch (FileNotFoundException e) { + // sometimes this can occur, but we simply re throw and let + // caller handle exception + throw new RuntimeException("Unable to create dump destination", e); + } + } + + /** + * {@inheritDoc} + */ + public OutputStream add(String name) throws Exception { + ZipEntry zipEntry = new ZipEntry(name); + outputStream.putNextEntry(zipEntry); + return new ClosingEntryOutputStreamWrapper(outputStream); + } + + /** + * Closes archive handle. + */ + public void save() throws Exception { + outputStream.close(); + } + + @Override + public String toString() { + return "zip: " + file; + } +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java new file mode 100644 index 0000000..fa6b010 --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/internal/Activator.java @@ -0,0 +1,54 @@ +/* + * 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.karaf.diagnostic.core.internal; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.karaf.diagnostic.core.Dump; +import org.apache.karaf.diagnostic.core.DumpDestination; +import org.apache.karaf.diagnostic.core.common.ZipDumpDestination; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import sun.misc.Signal; +import sun.misc.SignalHandler; + +public class Activator implements BundleActivator, SignalHandler { + + private static final String SIGNAL = "HUP"; + + private BundleContext bundleContext; + private SignalHandler previous; + + public void start(BundleContext context) throws Exception { + bundleContext = context; + previous = Signal.handle(new Signal(SIGNAL), this); + } + + public void stop(BundleContext context) throws Exception { + Signal.handle(new Signal(SIGNAL), previous); + } + + public void handle(Signal signal) { + SimpleDateFormat dumpFormat = new SimpleDateFormat("yyyy-MM-dd_HHmmss-SSS"); + String fileName = "dump-" + dumpFormat.format(new Date()) + ".zip"; + DumpDestination destination = new ZipDumpDestination(new File(fileName)); + Dump.dump(bundleContext, destination); + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java new file mode 100644 index 0000000..871097e --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/BundleDumpProvider.java @@ -0,0 +1,85 @@ +/* + * 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.karaf.diagnostic.core.providers; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.HashMap; +import java.util.Map; + +import org.apache.karaf.diagnostic.core.common.TextDumpProvider; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** + * Dump provider which produces file named bundles.txt with list of + * installed bundles and it's state. + */ +public class BundleDumpProvider extends TextDumpProvider { + + /** + * Static map with state mask to string representation. + */ + private static Map<Integer, String> stateMap = new HashMap<Integer, String>(); + + /** + * Map bundle states to string representation. + */ + static { + stateMap.put(0x00000001, "UNINSTALLED"); + stateMap.put(0x00000002, "INSTALLED"); + stateMap.put(0x00000004, "RESOLVED"); + stateMap.put(0x00000008, "STARTING"); + stateMap.put(0x00000010, "STOPPING"); + stateMap.put(0x00000020, "ACTIVE"); + } + + /** + * Bundle context. + */ + private BundleContext bundleContext; + + /** + * Creates new bundle information file. + * + * @param context Bundle context to access framework state. + */ + public BundleDumpProvider(BundleContext context) { + super("bundles.txt"); + this.bundleContext = context; + } + + /** + * {@inheritDoc} + */ + protected void writeDump(OutputStreamWriter writer) throws IOException { + // get bundle states + Bundle[] bundles = bundleContext.getBundles(); + + writer.write("Number of installed bundles " + bundles.length + "\n"); + + // create file header + writer.write("Id\tSymbolic name\tVersion\tState\n"); + for (Bundle bundle : bundles) { + // write row :) + writer.write(bundle.getBundleId() + "\t" + bundle.getSymbolicName() + '\t' + bundle.getVersion() + + "\t" + stateMap.get(bundle.getState()) + "\n"); + } + + writer.flush(); + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java new file mode 100644 index 0000000..b86fb8d --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/EnvironmentDumpProvider.java @@ -0,0 +1,290 @@ +/* + * 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.karaf.diagnostic.core.providers; + +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.management.ClassLoadingMXBean; +import java.lang.management.CompilationMXBean; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryUsage; +import java.lang.management.OperatingSystemMXBean; +import java.lang.management.RuntimeMXBean; +import java.lang.management.ThreadMXBean; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.karaf.diagnostic.core.common.TextDumpProvider; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** + * Provider which dumps runtime environment information to file named environment.txt. + */ +public class EnvironmentDumpProvider extends TextDumpProvider { + + private static final String KEY_VALUE_FORMAT = "%1$s\t: %2$s"; + private static final String INDENT_KEY_VALUE_FORMAT = " "+KEY_VALUE_FORMAT; + private final BundleContext bundleContext; + + /** + * Creates new dump entry which contains information about the runtime environment. + */ + public EnvironmentDumpProvider(final BundleContext context) { + super("environment.txt"); + this.bundleContext = context; + } + + @Override + protected void writeDump(final OutputStreamWriter outputStream) throws Exception { + if( null == outputStream) { + return; + } + final PrintWriter outPW = new PrintWriter(outputStream); + // current date/time + final DateFormat dateTimeFormatInstance = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.ENGLISH); + outPW.printf(KEY_VALUE_FORMAT,"Dump timestamp", dateTimeFormatInstance.format(new Date(System.currentTimeMillis()))).println(); + outPW.println(); + // karaf information + dumpKarafInformation(outPW); + outPW.println(); + // OSGi information + dumpOSGiInformation(outPW); + outPW.println(); + // OS information + dumpOSInformation(outPW); + outPW.println(); + // general information about JVM + dumpVMInformation(outPW, dateTimeFormatInstance); + outPW.println(); + // threads + dumpThreadsInformation(outPW); + outPW.println(); + // classes + dumpClassesInformation(outPW); + outPW.println(); + // memory + dumpMemoryInformation(outPW); + outPW.println(); + // garbage collector + dumpGCInformation(outPW); + } + + private void dumpKarafInformation(final PrintWriter outPW) { + outPW.printf(KEY_VALUE_FORMAT, "Karaf", System.getProperty("karaf.name", "root") + ' ' + System.getProperty("karaf.version", "")).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "home", System.getProperty("karaf.home", "")).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "base", System.getProperty("karaf.base", "")).println(); + } + + private void dumpOSGiInformation(final PrintWriter outPW) { + if( null == bundleContext ) { + return; + } + outPW.println("OSGi:"); + final Bundle[] bundles = bundleContext.getBundles(); + for (final Bundle bundle : bundles) { + if( null == bundle || !!!"osgi.core".equals(bundle.getSymbolicName())) { + continue; + } + outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", bundle.getVersion()).println(); + break; + } + outPW.printf(INDENT_KEY_VALUE_FORMAT, "framework", bundleContext.getBundle(0).getSymbolicName() + " - " + + bundleContext.getBundle(0).getVersion()).println(); + } + + private void dumpOSInformation(final PrintWriter outPW) { + final OperatingSystemMXBean mxBean = ManagementFactory.getOperatingSystemMXBean(); + if( null == mxBean) { + return; + } + outPW.printf(KEY_VALUE_FORMAT, "Operating System", mxBean.getName() + ' ' + mxBean.getVersion()).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "architecture", mxBean.getArch()).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "processors", mxBean.getAvailableProcessors()).println(); +// outPW.printf(INDENT_KEY_VALUE_FORMAT, "current system load average", mxBean.getSystemLoadAverage()).println(); + } + + private void dumpVMInformation(final PrintWriter outPW, + final DateFormat dateTimeFormatInstance) { + final RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean(); + if( mxBean == null ) { + return; + } + outPW.printf(KEY_VALUE_FORMAT,"Instance name", mxBean.getName()).println(); + outPW.printf(KEY_VALUE_FORMAT,"Start time", dateTimeFormatInstance.format(new Date(mxBean.getStartTime()))).println(); + outPW.printf(KEY_VALUE_FORMAT,"Uptime", printDuration(mxBean.getUptime())).println(); + outPW.println(); + outPW.printf(KEY_VALUE_FORMAT, "Java VM", mxBean.getVmName() + " " + mxBean.getVmVersion()).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "vendor", mxBean.getVmVendor()).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", System.getProperty("java.version")).println(); + outPW.println(); + outPW.println("Input arguments:"); + final List<String> inputArguments = mxBean.getInputArguments(); + for (final String argument : inputArguments) { + if( argument != null && argument.contains("=")) { + final String[] split = argument.split("="); + outPW.printf(INDENT_KEY_VALUE_FORMAT, split[0], split[1]).println(); + } else { + outPW.printf(INDENT_KEY_VALUE_FORMAT, argument,"").println(); + } + } + outPW.println("Classpath:"); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "boot classpath", mxBean.getBootClassPath()).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "library path", mxBean.getLibraryPath()).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "classpath", mxBean.getClassPath()).println(); + outPW.println("System properties:"); + final Map<String, String> systemProperties = mxBean.getSystemProperties(); + for (final Entry<String, String> property : systemProperties.entrySet()) { + outPW.printf(INDENT_KEY_VALUE_FORMAT, property.getKey(), property.getValue()).println(); + } + outPW.println(); + // JIT information + final CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean(); + if( compilationMXBean != null ) { + outPW.printf(KEY_VALUE_FORMAT, "JIT compiler", compilationMXBean.getName()).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "total compile time", printDuration(compilationMXBean.getTotalCompilationTime())).println(); + } + } + + private void dumpThreadsInformation(final PrintWriter outPW) { + final ThreadMXBean mxBean = ManagementFactory.getThreadMXBean(); + if( null == mxBean) { + return; + } + outPW.println("Threads:"); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "live", formatLong(mxBean.getThreadCount())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "daemon", formatLong(mxBean.getDaemonThreadCount())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "peak", formatLong(mxBean.getPeakThreadCount())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", formatLong(mxBean.getTotalStartedThreadCount())).println(); + } + + private void dumpClassesInformation(final PrintWriter outPW) { + final ClassLoadingMXBean mxBean = ManagementFactory.getClassLoadingMXBean(); + if( null == mxBean) { + return; + } + outPW.println("Classes:"); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "loaded", formatLong(mxBean.getLoadedClassCount())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", formatLong(mxBean.getTotalLoadedClassCount())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "unloaded", formatLong(mxBean.getUnloadedClassCount())).println(); + } + + private void dumpMemoryInformation(final PrintWriter outPW) { + final MemoryMXBean mxBean = ManagementFactory.getMemoryMXBean(); + if( null == mxBean) { + return; + } + final MemoryUsage heapMemoryUsage = mxBean.getHeapMemoryUsage(); + final MemoryUsage nonHeapMemoryUsage = mxBean.getNonHeapMemoryUsage(); + if( heapMemoryUsage != null ) { + outPW.println("HEAP Memory:"); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", printMemory(heapMemoryUsage.getCommitted())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", printMemory(heapMemoryUsage.getInit())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", printMemory(heapMemoryUsage.getUsed())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", printMemory(heapMemoryUsage.getMax())).println(); + } + if( nonHeapMemoryUsage != null ) { + outPW.println("NON-HEAP Memory:"); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", printMemory(nonHeapMemoryUsage.getCommitted())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", printMemory(nonHeapMemoryUsage.getInit())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", printMemory(nonHeapMemoryUsage.getUsed())).println(); + outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", printMemory(nonHeapMemoryUsage.getMax())).println(); + } + } + + private void dumpGCInformation(final PrintWriter outPW) { + final List<GarbageCollectorMXBean> mxBeans = ManagementFactory.getGarbageCollectorMXBeans(); + if( null == mxBeans || mxBeans.isEmpty()) { + return; + } + final MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean(); + if( memoryMxBean != null ) { + outPW.printf(INDENT_KEY_VALUE_FORMAT, "pending objects", formatLong(memoryMxBean.getObjectPendingFinalizationCount())).println(); + } + final String gcFormat ="'%1$s' collections: %2$s\ttime: %3$s"; + outPW.println(); + for (final GarbageCollectorMXBean mxBean : mxBeans) { + if( null == mxBean) { + continue; + } + outPW.printf(KEY_VALUE_FORMAT, "Garbage Collectors", String.format(gcFormat, mxBean.getName(), formatLong(mxBean.getCollectionCount()), printDuration(mxBean.getCollectionTime()))).println(); + } + } + + + private String formatLong(final long longValue) { + final NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH)); + return fmtI.format(longValue); + } + + private String printMemory(final long bytes) { + if( bytes <= 1024) { + return formatLong(bytes)+" bytes"; + } + return formatLong(bytes/1024)+" kbytes"; + } + + /** + * Prints the duration in a human readable format as X days Y hours Z minutes etc. + * + * @param uptime the uptime in millis + * @return the time used for displaying on screen or in logs + */ + private String printDuration(double uptime) { + // Code based on code taken from Karaf + // https://svn.apache.org/repos/asf/karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java + + uptime /= 1000; + if (uptime < 60) { + final NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH)); + return fmtD.format(uptime) + " seconds"; + } + uptime /= 60; + if (uptime < 60) { + final long minutes = (long) uptime; + final String s = formatLong(minutes) + (minutes > 1 ? " minutes" : " minute"); + return s; + } + uptime /= 60; + if (uptime < 24) { + final long hours = (long) uptime; + final long minutes = (long) ((uptime - hours) * 60); + String s = formatLong(hours) + (hours > 1 ? " hours" : " hour"); + if (minutes != 0) { + s += " " + formatLong(minutes) + (minutes > 1 ? " minutes" : " minute"); + } + return s; + } + uptime /= 24; + final long days = (long) uptime; + final long hours = (long) ((uptime - days) * 24); + String s = formatLong(days) + (days > 1 ? " days" : " day"); + if (hours != 0) { + s += " " + formatLong(hours) + (hours > 1 ? " hours" : " hour"); + } + return s; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java new file mode 100644 index 0000000..6a6f040 --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/HeapDumpProvider.java @@ -0,0 +1,68 @@ +/* + * 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.karaf.diagnostic.core.providers; + +import com.sun.management.HotSpotDiagnosticMXBean; +import org.apache.karaf.diagnostic.core.DumpDestination; +import org.apache.karaf.diagnostic.core.DumpProvider; + +import javax.management.MBeanServer; +import java.io.File; +import java.io.FileInputStream; +import java.io.OutputStream; +import java.lang.management.ManagementFactory; + +/** + * Create a heap dump. + */ +public class HeapDumpProvider implements DumpProvider { + + public void createDump(DumpDestination destination) throws Exception { + File heapDumpFile = null; + FileInputStream in = null; + OutputStream out = null; + try { + MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); + HotSpotDiagnosticMXBean diagnosticMXBean = ManagementFactory.newPlatformMXBeanProxy(mBeanServer, + "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); + heapDumpFile = File.createTempFile("heapdump", ".txt"); + heapDumpFile.delete(); + diagnosticMXBean.dumpHeap(heapDumpFile.getAbsolutePath(), false); + // copy the dump in the destination + in = new FileInputStream(heapDumpFile); + out = destination.add("heapdump.txt"); + byte[] buffer = new byte[2048]; + int l; + while (((l = in.read(buffer)) != -1)) { + out.write(buffer, 0, l); + } + } finally { + if (in != null) { + in.close(); + } + if (out != null) { + out.flush(); + out.close(); + } + // remove the original dump + if (heapDumpFile != null && heapDumpFile.exists()) { + heapDumpFile.delete(); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java new file mode 100644 index 0000000..8e99339 --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/MemoryDumpProvider.java @@ -0,0 +1,54 @@ +/* + * 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.karaf.diagnostic.core.providers; + +import java.io.OutputStreamWriter; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; + +import org.apache.karaf.diagnostic.core.common.TextDumpProvider; + +/** + * Provider which dump the memory information in the memory.txt file. + */ +public class MemoryDumpProvider extends TextDumpProvider { + + public MemoryDumpProvider() { + super("memory.txt"); + } + + @Override + protected void writeDump(OutputStreamWriter outputStream) throws Exception { + MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); + + outputStream.write("Number of objects waiting finalization: " + memoryMXBean.getObjectPendingFinalizationCount() + "\n\n"); + + outputStream.write("Heap:\n"); + outputStream.write("\tInit: " + memoryMXBean.getHeapMemoryUsage().getInit() + "\n"); + outputStream.write("\tUser: " + memoryMXBean.getHeapMemoryUsage().getUsed() + "\n"); + outputStream.write("\tCommitted: " + memoryMXBean.getHeapMemoryUsage().getCommitted() + "\n"); + outputStream.write("\tMax: " + memoryMXBean.getHeapMemoryUsage().getMax() + "\n"); + + outputStream.write("Non-Heap: \n"); + outputStream.write("\tInit: " + memoryMXBean.getNonHeapMemoryUsage().getInit() + "\n"); + outputStream.write("\tUser: " + memoryMXBean.getNonHeapMemoryUsage().getUsed() + "\n"); + outputStream.write("\tCommitted: " + memoryMXBean.getNonHeapMemoryUsage().getCommitted() + "\n"); + outputStream.write("\tMax: " + memoryMXBean.getNonHeapMemoryUsage().getMax() + "\n"); + + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java new file mode 100644 index 0000000..9f6b25b --- /dev/null +++ b/diagnostic/boot/src/main/java/org/apache/karaf/diagnostic/core/providers/ThreadDumpProvider.java @@ -0,0 +1,118 @@ +/* + * 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.karaf.diagnostic.core.providers; + +import java.io.OutputStreamWriter; +import java.lang.management.LockInfo; +import java.lang.management.ManagementFactory; +import java.lang.management.MonitorInfo; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; + +import org.apache.karaf.diagnostic.core.common.TextDumpProvider; + +/** + * Provider which dumps thread info to file named threads.txt. + */ +public class ThreadDumpProvider extends TextDumpProvider { + + /** + * Creates new dump entry which contains information about threads. + */ + public ThreadDumpProvider() { + super("threads.txt"); + } + + @Override + protected void writeDump(OutputStreamWriter outputStream) throws Exception { + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + + outputStream.write("Number of threads: " + threadMXBean.getThreadCount() + "\n"); + + for (ThreadInfo threadInfo : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), Integer.MAX_VALUE)) { + outputStream.write(getDumpThreadString(threadInfo) + "\n\n"); + } + + } + + protected String getDumpThreadString(ThreadInfo threadInfo) { + StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() + "\"" + " Id=" + threadInfo.getThreadId() + " " + + threadInfo.getThreadState()); + if (threadInfo.getLockName() != null) { + sb.append(" on " + threadInfo.getLockName()); + } + if (threadInfo.getLockOwnerName() != null) { + sb.append(" owned by \"" + threadInfo.getLockOwnerName() + "\" Id=" + threadInfo.getLockOwnerId()); + } + if (threadInfo.isSuspended()) { + sb.append(" (suspended)"); + } + if (threadInfo.isInNative()) { + sb.append(" (in native)"); + } + sb.append('\n'); + int i = 0; + StackTraceElement[] stackTrace = threadInfo.getStackTrace(); + for (; i < stackTrace.length; i++) { + StackTraceElement ste = stackTrace[i]; + sb.append("\tat " + ste.toString()); + sb.append('\n'); + if (i == 0 && threadInfo.getLockInfo() != null) { + Thread.State ts = threadInfo.getThreadState(); + switch (ts) { + case BLOCKED: + sb.append("\t- blocked on " + threadInfo.getLockInfo()); + sb.append('\n'); + break; + case WAITING: + sb.append("\t- waiting on " + threadInfo.getLockInfo()); + sb.append('\n'); + break; + case TIMED_WAITING: + sb.append("\t- waiting on " + threadInfo.getLockInfo()); + sb.append('\n'); + break; + default: + } + } + + for (MonitorInfo mi : threadInfo.getLockedMonitors()) { + if (mi.getLockedStackDepth() == i) { + sb.append("\t- locked " + mi); + sb.append('\n'); + } + } + } + if (i < stackTrace.length) { + sb.append("\t..."); + sb.append('\n'); + } + + LockInfo[] locks = threadInfo.getLockedSynchronizers(); + if (locks.length > 0) { + sb.append("\n\tNumber of locked synchronizers = " + locks.length); + sb.append('\n'); + for (LockInfo li : locks) { + sb.append("\t- " + li); + sb.append('\n'); + } + } + sb.append('\n'); + return sb.toString(); + } + + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/boot/src/main/resources/OSGI-INF/bundle.info ---------------------------------------------------------------------- diff --git a/diagnostic/boot/src/main/resources/OSGI-INF/bundle.info b/diagnostic/boot/src/main/resources/OSGI-INF/bundle.info new file mode 100644 index 0000000..6f8f9cb --- /dev/null +++ b/diagnostic/boot/src/main/resources/OSGI-INF/bundle.info @@ -0,0 +1,16 @@ +h1. Synopsis + +${project.name} + +${project.description} + +Maven URL: +[mvn:${project.groupId}/${project.artifactId}/${project.version}] + +h1. Description + +The diagnostic boot bundle contains the core diagnostic implementation along with the signal handler. + +h1. See also + +Diagnostic - section of the Karaf User Guide. http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/NOTICE ---------------------------------------------------------------------- diff --git a/diagnostic/core/NOTICE b/diagnostic/core/NOTICE new file mode 100644 index 0000000..b70f1f9 --- /dev/null +++ b/diagnostic/core/NOTICE @@ -0,0 +1,71 @@ +Apache Karaf +Copyright 2010-2014 The Apache Software Foundation + + +I. Included Software + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). +Licensed under the Apache License 2.0. + +This product uses software developed at +The OSGi Alliance (http://www.osgi.org/). +Copyright (c) OSGi Alliance (2000, 2010). +Licensed under the Apache License 2.0. + +This product includes software developed at +OW2 (http://www.ow2.org/). +Licensed under the BSD License. + +This product includes software developed at +OPS4J (http://www.ops4j.org/). +Licensed under the Apache License 2.0. + +This product includes software developed at +Eclipse Foundation (http://www.eclipse.org/). +Licensed under the EPL. + +This product includes software written by +Antony Lesuisse. +Licensed under Public Domain. + + +II. Used Software + +This product uses software developed at +FUSE Source (http://www.fusesource.org/). +Licensed under the Apache License 2.0. + +This product uses software developed at +AOP Alliance (http://aopalliance.sourceforge.net/). +Licensed under the Public Domain. + +This product uses software developed at +Tanuki Software (http://www.tanukisoftware.com/). +Licensed under the Apache License 2.0. + +This product uses software developed at +Jasypt (http://jasypt.sourceforge.net/). +Licensed under the Apache License 2.0. + +This product uses software developed at +JLine (http://jline.sourceforge.net). +Licensed under the BSD License. + +This product uses software developed at +SLF4J (http://www.slf4j.org/). +Licensed under the MIT License. + +This product uses software developed at +SpringSource (http://www.springsource.org/). +Licensed under the Apache License 2.0. + +This product includes software from http://www.json.org. +Copyright (c) 2002 JSON.org + + +III. License Summary +- Apache License 2.0 +- BSD License +- EPL License +- MIT License http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/pom.xml ---------------------------------------------------------------------- diff --git a/diagnostic/core/pom.xml b/diagnostic/core/pom.xml new file mode 100644 index 0000000..c9cdaa1 --- /dev/null +++ b/diagnostic/core/pom.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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/xsd/maven-4.0.0.xsd"> + + <!-- + + 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. + --> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.karaf</groupId> + <artifactId>karaf</artifactId> + <version>4.0.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <groupId>org.apache.karaf.diagnostic</groupId> + <artifactId>org.apache.karaf.diagnostic.core</artifactId> + <packaging>bundle</packaging> + <name>Apache Karaf :: Diagnostic :: Core</name> + <description>Core implementation using Karaf diagnostic using the diagnostic common services</description> + + <properties> + <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory> + </properties> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.karaf</groupId> + <artifactId>org.apache.karaf.util</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.karaf.features</groupId> + <artifactId>org.apache.karaf.features.core</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.karaf.diagnostic</groupId> + <artifactId>org.apache.karaf.diagnostic.boot</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.karaf.shell</groupId> + <artifactId>org.apache.karaf.shell.core</artifactId> + <optional>true</optional> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <directory>${project.basedir}/src/main/resources</directory> + <includes> + <include>**/*</include> + </includes> + </resource> + <resource> + <directory>${project.basedir}/src/main/resources</directory> + <filtering>true</filtering> + <includes> + <include>**/*.info</include> + </includes> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.karaf.tooling</groupId> + <artifactId>karaf-services-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Export-Package> + org.apache.karaf.diagnostic.management + </Export-Package> + <Import-Package> + com.sun.management*;resolution:=optional, + * + </Import-Package> + <Private-Package> + org.apache.karaf.diagnostic.command, + org.apache.karaf.diagnostic.common, + org.apache.karaf.diagnostic.internal, + org.apache.karaf.diagnostic.management.internal, + org.apache.karaf.util, + org.apache.karaf.util.tracker + </Private-Package> + <Provide-Capability> + ${capabilities} + </Provide-Capability> + <Require-Capability> + ${requirements} + </Require-Capability> + <Bundle-Activator> + org.apache.karaf.diagnostic.internal.Activator + </Bundle-Activator> + <Karaf-Commands>*</Karaf-Commands> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java ---------------------------------------------------------------------- diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java new file mode 100644 index 0000000..a7f0694 --- /dev/null +++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java @@ -0,0 +1,86 @@ +/* + * 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.karaf.diagnostic.command; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import org.apache.karaf.diagnostic.core.Dump; +import org.apache.karaf.diagnostic.core.DumpDestination; +import org.apache.karaf.shell.api.action.Action; +import org.apache.karaf.shell.api.action.Argument; +import org.apache.karaf.shell.api.action.Command; +import org.apache.karaf.shell.api.action.Option; +import org.apache.karaf.shell.api.action.lifecycle.Reference; +import org.apache.karaf.shell.api.action.lifecycle.Service; +import org.osgi.framework.BundleContext; + +/** + * Command to create dump from shell. + */ +@Command(scope = "dev", name = "dump-create", description = "Creates zip archive with diagnostic info.") +@Service +public class DumpCommand implements Action { + + /** + * Output format of the filename if not defined otherwise + */ + private SimpleDateFormat dumpFormat = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); + + /** + * Directory switch. + */ + @Option(name = "-d", aliases = "--directory", description = "Creates dump in a directory in place of a ZIP archive") + boolean directory; + + /** + * Name of created directory or archive. + */ + @Argument(name = "name", description = "Name of created zip or directory", required = false) + String fileName; + + @Reference + BundleContext bundleContext; + + @Override + public Object execute() throws Exception { + DumpDestination destination; + + // create default file name if none provided + if (fileName == null || fileName.trim().length() == 0) { + fileName = dumpFormat.format(new Date()); + if (!directory) { + fileName += ".zip"; + } + } + File target = new File(fileName); + + // if directory switch is on, create dump in directory + if (directory) { + destination = Dump.directory(target); + } else { + destination = Dump.zip(target); + } + + Dump.dump(bundleContext, destination); + + return null; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java new file mode 100644 index 0000000..4d90841 --- /dev/null +++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/FeaturesDumpProvider.java @@ -0,0 +1,78 @@ +/* + * 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.karaf.diagnostic.common; + +import java.io.OutputStreamWriter; + +import org.apache.karaf.features.BundleInfo; +import org.apache.karaf.features.Feature; +import org.apache.karaf.features.FeaturesService; +import org.apache.karaf.features.Repository; + +/** + * Dump provider which add file named features.txt with informations + * about installed features and repositories. + */ +public class FeaturesDumpProvider extends TextDumpProvider { + + /** + * Feature service. + */ + private final FeaturesService features; + + /** + * Creates new dump entry witch contains information about + * karaf features. + * + * @param features Feature service. + */ + public FeaturesDumpProvider(FeaturesService features) { + super("features.txt"); + this.features = features; + } + + /** + * {@inheritDoc} + */ + protected void writeDump(OutputStreamWriter outputStreamWriter) throws Exception { + // creates header + outputStreamWriter.write("Repositories:\n"); + + // list repositories + for (Repository repo : features.listRepositories()) { + outputStreamWriter.write(repo.getURI() + " (" + repo.getName() + ")\n"); + } + + // list features + outputStreamWriter.write("\nfeatures:\n"); + for (Feature feature : features.listFeatures()) { + outputStreamWriter.write(feature.getName() + " " + feature.getVersion()); + outputStreamWriter.write(" installed: " + features.isInstalled(feature)); + outputStreamWriter.write("\nBundles:\n"); + for (BundleInfo bundle : feature.getBundles()) { + outputStreamWriter.write("\t" + bundle.getLocation()); + if (bundle.getStartLevel() != 0) { + outputStreamWriter.write(" start level " + bundle.getStartLevel()); + } + outputStreamWriter.write("\n\n"); + } + } + + // flush & close stream + outputStreamWriter.close(); + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.java new file mode 100644 index 0000000..9fcd44a --- /dev/null +++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/LogDumpProvider.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.karaf.diagnostic.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.OutputStream; +import java.util.Dictionary; +import java.util.Enumeration; + +import org.apache.karaf.diagnostic.core.DumpDestination; +import org.apache.karaf.diagnostic.core.DumpProvider; +import org.apache.karaf.util.StreamUtils; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * Dump provider which copies log files from data/log directory to + * destination. + */ +public class LogDumpProvider implements DumpProvider { + + private final BundleContext bundleContext; + + public LogDumpProvider(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + /** + * Attach log entries from directory. + */ + public void createDump(DumpDestination destination) throws Exception { + // get the ConfigAdmin service + ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); + if (ref == null) { + return; + } + + // get the PAX Logging configuration + ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) bundleContext.getService(ref); + try { + Configuration configuration = configurationAdmin.getConfiguration("org.ops4j.pax.logging"); + + // get the ".file" Pax Logging properties + Dictionary dictionary = configuration.getProperties(); + for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) { + String property = (String) e.nextElement(); + if (property.endsWith(".file")) { + // it's a file appender, get the file location + String location = (String) dictionary.get(property); + File file = new File(location); + if (file.exists()) { + FileInputStream inputStream = new FileInputStream(file); + OutputStream outputStream = destination.add("log/" + file.getName()); + StreamUtils.copy(inputStream, outputStream); + } + } + } + } catch (Exception e) { + throw e; + } finally { + bundleContext.ungetService(ref); + } + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e55fd0a0/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java ---------------------------------------------------------------------- diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java new file mode 100644 index 0000000..52f2289 --- /dev/null +++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/common/TextDumpProvider.java @@ -0,0 +1,66 @@ +/* + * 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.karaf.diagnostic.common; + +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +import org.apache.karaf.diagnostic.core.DumpDestination; +import org.apache.karaf.diagnostic.core.DumpProvider; + +/** + * Base class for dump providers which writes text to destination. + */ +public abstract class TextDumpProvider implements DumpProvider { + + /** + * Name of the file. + */ + private final String name; + + /** + * Creates new dump provider. + * + * @param name Name of the file. + */ + protected TextDumpProvider(String name) { + this.name = name; + } + + /** + * {@inheritDoc} + */ + @Override + public final void createDump(DumpDestination destination) throws Exception { + OutputStream outputStream = destination.add(name); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + try { + writeDump(outputStreamWriter); + } finally { + outputStreamWriter.close(); + outputStream.close(); + } + } + + /** + * This method should create output. + * + * @param outputStreamWriter Stream which points to file specified in constructor. + * @throws Exception If any problem occur. + */ + protected abstract void writeDump(OutputStreamWriter outputStreamWriter) throws Exception; + +}
