/* * Copyright (c) 2013, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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 com.google.dart.tools.ui.instrumentation; import com.google.dart.engine.utilities.instrumentation.Base64; import com.google.dart.engine.utilities.instrumentation.HealthUtils; import com.google.dart.engine.utilities.instrumentation.Instrumentation; import com.google.dart.engine.utilities.instrumentation.InstrumentationBuilder; import com.google.dart.tools.core.DartCoreDebug; import com.google.dart.tools.ui.feedback.FeedbackUtils; import com.google.dart.tools.ui.feedback.FeedbackUtils.Stats; import org.eclipse.jface.text.IDocument; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; /** * {@code Heartbeat} provides utility methods that an external instrumentation plugin can call to * get periodic information about the health of the development environment. */ public class Heartbeat { private static final Heartbeat INSTANCE = new Heartbeat(); public static Heartbeat getInstance() { return INSTANCE; } /** * Log the information that is also reported in the feedback dialog */ private static void logFeedbackInfo(InstrumentationBuilder instrumentation) { instrumentation.metric("FB-VersionDetails", FeedbackUtils.getEditorVersionDetails()); instrumentation.metric("FB-OSName", FeedbackUtils.getOSName()); Stats stats = FeedbackUtils.getStats(); instrumentation.metric("FB-Stats-autoRunPubEnabled", stats.autoRunPubEnabled); instrumentation.metric("FB-Stats-numEditors", stats.numEditors); instrumentation.metric("FB-Stats-numProjects", stats.numProjects); instrumentation.metric("FB-Stats-numThreads", stats.numThreads); if (!DartCoreDebug.ENABLE_ANALYSIS_SERVER) { instrumentation.metric("FB-Stats-indexStats", "index: " + stats.indexStats); } } /** * This method logs information about the health of the development environment. It is imperative * that this method execute quickly as this is typically called once per minute. * * @param instrumentation the instrumentation used to log information (not {@code null}) */ public void heartbeat(InstrumentationBuilder instrumentation) { logFeedbackInfo(instrumentation); HealthUtils.logMemory(instrumentation); HealthUtils.logThreads(instrumentation); logWindowsPagesAndTabs(instrumentation); } private void logWindowsPagesAndTabs(InstrumentationBuilder instrumentation) { IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow activeWindow = workbench.getActiveWorkbenchWindow(); IWorkbenchWindow[] allWindows = workbench.getWorkbenchWindows(); instrumentation.metric("OpenWindowsCount", allWindows.length); for (int windowIndex = 0; windowIndex < allWindows.length; windowIndex++) { IWorkbenchWindow window = allWindows[windowIndex]; if (window == activeWindow) { instrumentation.metric("ActiveWindow", windowIndex); } String windowKey = "Window-" + windowIndex; IWorkbenchPage activePage = window.getActivePage(); IWorkbenchPage[] allPages = window.getPages(); instrumentation.metric(windowKey + "-OpenPageCount", allPages.length); for (int pageIndex = 0; pageIndex < allPages.length; pageIndex++) { IWorkbenchPage page = allPages[pageIndex]; if (page == activePage) { instrumentation.metric(windowKey + "-ActivePage", pageIndex); } String pageKey = windowKey + "-Page-" + pageIndex; IWorkbenchPart activePart = page.getActivePart(); IViewReference[] allViews = page.getViewReferences(); IEditorReference[] allEditors = page.getEditorReferences(); instrumentation.metric(pageKey + "-OpenViewCount", allViews.length); for (int viewIndex = 0; viewIndex < allViews.length; viewIndex++) { IViewReference view = allViews[viewIndex]; if (view == activePart) { instrumentation.metric(pageKey + "-ActiveView", viewIndex); } String viewKey = pageKey + "-View-" + viewIndex; instrumentation.metric(viewKey + "-Id", view.getId()); } for (int editorIndex = 0; editorIndex < allEditors.length; editorIndex++) { IEditorReference editor = allEditors[editorIndex]; if (editor == activePart) { instrumentation.metric(pageKey + "-ActiveEditorTab", editorIndex); } String editorKey = pageKey + "-Editor-" + editorIndex; instrumentation.metric(editorKey + "-Id", editor.getId()); instrumentation.metric(editorKey + "-Dirty", editor.isDirty()); instrumentation.data(editorKey + "-Name", editor.getTitle()); InstrumentationBuilder srcInstr = Instrumentation.builder("Editor-src-HB"); try { IEditorPart part = editor.getEditor(false); srcInstr.metric(editorKey + "-Id", editor.getId()); srcInstr.metric(editorKey + "-Dirty", editor.isDirty()); srcInstr.data(editorKey + "-Name", editor.getTitle()); if (part instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) part; IDocumentProvider provider = textEditor.getDocumentProvider(); if (provider != null) { IDocument document = provider.getDocument(textEditor.getEditorInput()); if (document != null) { String docSrc = document.get(); //TODO(lukechurch): Add a Java+Python compatible compressor here String docSrcb64 = Base64.encodeBytes(docSrc.getBytes()); srcInstr.data(editorKey + "-src", docSrcb64); } } } } catch (Exception e) { srcInstr.record(e); } finally { srcInstr.log(); } } } } } }