Package com.seyren.core.service.live.server

Source Code of com.seyren.core.service.live.server.PickleHandler$PythonToJava

/**
* Licensed 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 com.seyren.core.service.live.server;

import static org.python.google.common.collect.ImmutableSet.*;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.Socket;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;

import org.python.core.PyList;
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.modules.cPickle;
import org.python.modules.struct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.seyren.core.service.live.Metric;
import com.seyren.core.service.live.MetricsTask;
import com.seyren.core.service.schedule.CheckRunnerFactory;
import com.seyren.core.store.ChecksStore;

/**
* See http://graphite.readthedocs.org/en/latest/feeding-carbon.html
*/
public class PickleHandler implements Runnable {
    private static final Logger LOGGER = LoggerFactory.getLogger(PickleHandler.class);
    private static final String ISO_8859_1 = "ISO-8859-1";

    private Socket socket;
    private Executor executor;
    private ChecksStore checksStore;
    private CheckRunnerFactory checkRunnerFactory;

    public PickleHandler(Socket socket, Executor executor, ChecksStore checksStore, CheckRunnerFactory checkRunnerFactory) {
        this.socket = socket;
        this.executor = executor;
        this.executor = executor;
        this.checksStore = checksStore;
        this.checkRunnerFactory = checkRunnerFactory;
    }

    @Override
    public void run() {
        LOGGER.debug("Accepted.");
        InputStream inputStream = null;
        try {
            inputStream = socket.getInputStream();

            while (true) {
                // http://graphite.readthedocs.org/en/latest/feeding-carbon.html
                // Send the data over a socket to Carbon’s pickle receiver
                // You’ll need to pack your pickled data into a packet containing a simple header:
                //   payload = pickle.dumps(listOfMetricTuples)
                //   header = struct.pack("!L", len(payload))
                //   message = header + payload
                // Here, we have to decode this kind of message
                BigInteger length = getLength(inputStream);
                LOGGER.debug("Pickle length {}", length);

                List<Metric> metrics = getMetrics(inputStream, length);
                LOGGER.debug("Pickle size: {}", metrics.size());
                executor.execute(new MetricsTask(copyOf(metrics), checksStore, checkRunnerFactory));
            }
        } catch (Exception e) {
            LOGGER.warn("An error occurs when decoding pickle message: '{}' (change log level to debug to see stack trace).", e.getMessage());
            LOGGER.debug("An error occurs when decoding pickle message: ", e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

    private BigInteger getLength(InputStream inputStream) throws IOException {
        byte[] bytes = new byte[4];
        inputStream.read(bytes);
        String stHeader = new String(bytes, ISO_8859_1);
        PyTuple tuple = struct.unpack("!L", stHeader);
        return (BigInteger) tuple.get(0);
    }

    @SuppressWarnings("unchecked")
    private List<Metric> getMetrics(InputStream inputStream, BigInteger length) throws IOException {
        byte[] bytes = new byte[length.intValue()];
        inputStream.read(bytes);
        String payload = new String(bytes, ISO_8859_1);

        PyString pyString = new PyString(payload);
        PyList pyList = (PyList) cPickle.loads(pyString);

        return Lists.transform(pyList, new PythonToJava());
    }

    private static class PythonToJava implements Function<Object, Metric> {
        @Override
        public Metric apply(Object pyObject) {
            PyTuple pyTuple = (PyTuple) pyObject;
            Metric metric = new Metric();
            metric.setName(pyTuple.get(0).toString());
            PyTuple data = ((PyTuple) pyTuple.get(1));
            metric.setTimestamp(new Date(((Number) data.get(0)).longValue() * 1000));
            metric.setValue(new BigDecimal(((Number) data.get(1)).doubleValue()));
            return metric;
        }
    }
}
TOP

Related Classes of com.seyren.core.service.live.server.PickleHandler$PythonToJava

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.