All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.konverge.library.Konverge Maven / Gradle / Ivy

/**
 * Copyright (C) 2009-2013 Nasrollah Kavian - All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/
 */
package io.konverge.library;

import java.io.File;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Locale;
import org.json.JSONObject;

/**
 * Konverge library for Java.
 */
public final class Konverge implements Runnable {

    private static String      s_apiKey;
    private static boolean     s_enableLocalLog;
    private static boolean     s_initialized;
    private static String      s_protocol;
    private static String      s_server;
    private static String      s_version;

    /**
    * 
    */
    public static final String TYPE_ASSERT    = "Assert";

    /**
    * 
    */
    public static final String TYPE_CRITICAL  = "Critical";

    /**
    * 
    */
    public static final String TYPE_DEBUG     = "Debug";

    /**
    * 
    */
    public static final String TYPE_ERROR     = "Error";

    /**
    * 
    */
    public static final String TYPE_EXCEPTION = "Exception";

    /**
    * 
    */
    public static final String TYPE_FEEDBACK  = "Feedback";

    /**
    * 
    */
    public static final String TYPE_INFO      = "Info";

    /**
    * 
    */
    public static final String TYPE_WARNING   = "Warning";

    private JSONObject         m_extra        = null;
    private String             m_stack        = null;
    private String             m_text         = null;
    private String             m_type         = null;

    /**
     * Send the assertion text to the server if the condition fails.
     * 
     * @param condition The assertion is captured only if the condition fails.
     * @param text The text to log.
     */
    public static void assertion(final boolean condition, final String text) {
        if(condition) {
            return;
        }
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(TYPE_ASSERT, stack, stack);
    }

    /**
     * Send the assertion text to the server.
     * 
     * @param text The text to log.
     */
    public static void assertion(final String text) {
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(TYPE_ASSERT, stack, stack);
    }

    private static String callStack(final String text) {
        final StringWriter stringWriter = new StringWriter();
        new Exception().printStackTrace(new PrintWriter(stringWriter));
        final ArrayList items = new ArrayList(Arrays.asList(stringWriter.toString().split("\n")));
        items.set(0, text);
        items.remove(1);
        items.remove(1);
        return Utility.join(items, "\n");
    }

    /**
     * Send the exception to the server. Used to capture arbitrary failures during runtime.
     * 
     * @param type A name used to categorize this event.
     * @param exception The exception object to capture.
     */
    public static void capture(final String type, final Exception exception) {
        if(!s_initialized) {
            return;
        }
        process(type, exception);
    }

    /**
     * Send the text to the server. Useful for capturing arbitrary data during runtime.
     * 
     * @param type A name used to categorize this event.
     * @param text The text to log.
     */
    public static void capture(final String type, final String text) {
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(type, stack, stack);
    }

    protected static void capture(final Throwable throwable) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_EXCEPTION, throwable);
    }

    /**
     * Send the critical exception to the server. Used to capture essential failures during runtime.
     * 
     * @param exception The exception object to capture.
     */
    public static void critical(final Exception exception) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_CRITICAL, exception);
    }

    /**
     * Send the critical text to the server. Used to capture essential failures during runtime.
     * 
     * @param text The text to log.
     */
    public static void critical(final String text) {
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(TYPE_CRITICAL, stack, stack);
    }

    /**
     * Send the debug exception to the server. Used to capture arbitrary failures during runtime.
     * 
     * @param exception The exception object to capture.
     */
    public static void debug(final Exception exception) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_DEBUG, exception);
    }

    /**
     * Send the debug text to the server. Useful for capturing arbitrary data during runtime.
     * 
     * @param text The text to log.
     */
    public static void debug(final String text) {
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(TYPE_DEBUG, stack, stack);
    }

    /**
     * Send the error exception to the server. Used to capture arbitrary failures during runtime.
     * 
     * @param exception The exception object to capture.
     */
    public static void error(final Exception exception) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_ERROR, exception);
    }

    /**
     * Send the error text to the server. Useful for capturing arbitrary data during runtime.
     * 
     * @param text The text to log.
     */
    public static void error(final String text) {
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(TYPE_ERROR, stack, stack);
    }

    /**
     * Typically used within the catch of a try/catch statement. This will send the exception object to the server.
     * 
     * @param exception The exception object to capture.
     */
    public static void exception(final Exception exception) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_EXCEPTION, exception);
    }

    /**
     * Send the feedback text to the server. Useful for leveraging our full system for feedbacks but allows you the ability to design the GUI.
     * 
     * @param text The feedback text.
     */
    public static void feedback(final String text) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_FEEDBACK, text, null);
    }

    private static JSONObject getExtra() {
        final JSONObject extra = new JSONObject();
        try {
            Class.forName("io.konverge.library.ServletFilter").getMethod("getExtra", JSONObject.class).invoke(null, extra);
        }
        catch(final Exception e) {
            e.printStackTrace();
        }
        return extra;
    }

    /**
     * Send the info exception to the server. Used to capture arbitrary failures during runtime.
     * 
     * @param exception The exception object to capture.
     */
    public static void info(final Exception exception) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_INFO, exception);
    }

    /**
     * Send the info text to the server. Useful for capturing arbitrary data during runtime.
     * 
     * @param text The text to log.
     */
    public static void info(final String text) {
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(TYPE_INFO, stack, stack);
    }

    /**
     * Initializes the library using konverge.json located in the root of the classes folder.
     */
    public static synchronized void initialize() {
        //System.out.println(Utility.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("konverge.json")));
        //System.out.println(Utility.toString(Agent.class.getClassLoader().getResourceAsStream("konverge.json")));
        //System.out.println(Agent.class.getResource("/konverge.json"));
        try {
            // Load the file from the current directory.
            final JSONObject config = new JSONObject(Utility.toString(new FileInputStream(new File(URLDecoder.decode(
                Agent.class.getProtectionDomain().getCodeSource().getLocation().getPath(),
                "UTF-8")).getParentFile().getPath() + File.separator + "konverge.json")));

            String server = null;
            String apiKey = null;
            String version = null;
            boolean useSSL = true;

            // Iterate through values
            final Iterator iter = config.keys();
            while(iter.hasNext()) {
                final String name = (String)iter.next();
                // Match Server.
                if(name.equalsIgnoreCase("Server")) {
                    server = config.optString(name);
                }
                else if(name.equalsIgnoreCase("APIKey")) {
                    apiKey = config.optString(name);
                }
                else if(name.equalsIgnoreCase("Version")) {
                    version = config.optString(name);
                }
                else if(name.equalsIgnoreCase("UseSSL")) {
                    useSSL = config.optString(name).equalsIgnoreCase("true") || config.optBoolean(name);
                }
            }

            // Initialize Konverge
            if(server != null && apiKey != null && version != null) {
                Konverge.initialize(server, apiKey, version, useSSL);
            }
            else if(apiKey != null && version != null) {
                Konverge.initialize(apiKey, version);
            }
        }
        catch(final Exception e) {
        }
    }

    /**
     * Initializes the library with the developer's API credentials.
     * 
     * @param apiKey The developer's API key.
     * @param version The applications version string.
     */
    public static synchronized void initialize(final String apiKey, final String version) {
        initialize("api.konverge.co", apiKey, version, true);
    }

    /**
     * This initializes the Konverge library with the developer's credentials for storing items.
     * 
     * @param server The server to send data to.
     * @param apiKey The developer's API key.
     * @param version The applications version string.
     * @param useSSL Enable the use of SSL.
     */
    public static synchronized void initialize(final String server, final String apiKey, final String version, final boolean useSSL) {
        s_initialized = false;
        s_enableLocalLog = false;
        if(server == null || apiKey == null || version == null) {
            return;
        }
        s_server = server;
        s_apiKey = apiKey;
        s_version = version;
        s_protocol = useSSL ? "https://" : "http://";

        final UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler();
        if(!(currentHandler instanceof ExceptionHandler)) {
            Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
        }
        s_initialized = true;
    }

    /**
     * @return true if initialized
     */
    public static boolean isInitialized() {
        return s_initialized;
    }

    private static void process(final String type, final String text, final String stack) {
        try {
            new Thread(new Konverge(type, text, stack, getExtra())).start();
        }
        catch(final Throwable ignore) {
        }
    }

    protected static void process(final String type, final Throwable throwable) {
        final StringWriter stringWriter = new StringWriter();
        throwable.printStackTrace(new PrintWriter(stringWriter));
        final String stack = stringWriter.toString();
        process(type, stack, stack);
    }

    /**
     * This will turn on/off logging to the local system log.
     * 
     * @param enabled When set to true additional debug info will be shown in the log. For example when an exception is captured, the exception call
     *            stack is logged.
     */
    public static void setLocalLogEnabled(final boolean enabled) {
        s_enableLocalLog = enabled;
    }

    /**
     * Provides an online and centralized location for trace logging which is only stored temporarily.
     * 
     * @param category A name used to categorize the messages.
     * @param message The message to log temporarily.
     */
    public static void trace(final String category, final String message) {
        if(!s_initialized) {
            return;
        }
        final Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                new Request(s_protocol + s_server + "/rest/trace-add.jsp").setParameter("APIKey", s_apiKey)
                    .setParameter("Category", category != null ? category.trim() : "")
                    .setParameter("Message", message != null ? message.trim() : "")
                    .setParameter("Platform", 4)
                    .setParameter("Time", System.currentTimeMillis() / 1000)
                    .setParameter("Version", s_version)
                    .execute();
            }
        });
        try {
            thread.start();
        }
        catch(final Exception e) {
        }
    }

    /**
     * Send the warning exception to the server. Used to capture arbitrary failures during runtime.
     * 
     * @param exception The exception object to capture.
     */
    public static void warning(final Exception exception) {
        if(!s_initialized) {
            return;
        }
        process(TYPE_WARNING, exception);
    }

    /**
     * Send the warning text to the server. Useful for capturing arbitrary data during runtime.
     * 
     * @param text The text to log.
     */
    public static void warning(final String text) {
        if(!s_initialized) {
            return;
        }
        final String stack = callStack(text);
        process(TYPE_WARNING, stack, stack);
    }

    private Konverge() {
    }

    private Konverge(final String type, final String text, final String stack, final JSONObject extra) {
        m_type = type;
        m_text = text;
        m_stack = stack;
        m_extra = extra;
    }

    @Override
    public void run() {
        try {
            if(s_enableLocalLog && m_text != null) {
                System.out.println(m_text.trim());
            }

            try {
                if(m_stack != null) {
                    m_extra.put("CallStack", m_stack);
                }
                final JSONObject environment = new JSONObject();
                for(final String key : System.getenv().keySet()) {
                    environment.putOpt(key, System.getenv().get(key));
                }
                m_extra.put("Environment", environment);
                final JSONObject properties = new JSONObject();
                for(final Object key : System.getProperties().keySet()) {
                    properties.putOpt((String)key, System.getProperties().get(key));
                }
                m_extra.put("Properties", properties);
            }
            catch(final Throwable ignore) {
            }
            new Request(s_protocol + s_server + "/rest/event-add.jsp").setParameter("APIKey", s_apiKey)
                .setParameter("Event", m_text != null ? m_text.trim() : "")
                .setParameter("Extra", m_extra.toString())
                .setParameter("Locale", Locale.getDefault().getLanguage() + "-" + Locale.getDefault().getCountry())
                .setParameter("Opaque", "")
                .setParameter("Platform", 4)
                .setParameter("Time", System.currentTimeMillis() / 1000)
                .setParameter("Type", m_type)
                .setParameter("Version", s_version)
                .execute();
        }
        catch(final Throwable ignore) {
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy