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

com.expedia.www.haystack.agent.span.spi.SpanAgent Maven / Gradle / Ivy

There is a newer version: 0.1.18
Show newest version
/*
 *  Copyright 2017 Expedia, Inc.
 *
 *     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.expedia.www.haystack.agent.span.spi;

import com.expedia.www.haystack.agent.core.Agent;
import com.expedia.www.haystack.agent.core.Dispatcher;
import com.expedia.www.haystack.agent.core.config.ConfigurationHelpers;
import com.expedia.www.haystack.agent.span.enricher.Enricher;
import com.expedia.www.haystack.agent.span.service.SpanAgentGrpcService;
import com.google.common.annotations.VisibleForTesting;
import com.typesafe.config.Config;
import io.grpc.Server;
import io.grpc.netty.NettyServerBuilder;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

public class SpanAgent implements Agent {
    private static Logger LOGGER = LoggerFactory.getLogger(SpanAgent.class);

    private List dispatchers;
    private Server server;

    @Override
    public String getName() {
        return "spans";
    }

    @Override
    public void initialize(final Config config) throws IOException {
        dispatchers = loadAndInitializeDispatchers(config, Thread.currentThread().getContextClassLoader());

        final int port = config.getInt("port");
        final List enrichers = loadSpanEnrichers(config);

        server = NettyServerBuilder
                .forPort(port)
                .directExecutor()
                .addService(new SpanAgentGrpcService(dispatchers, enrichers))
                .build()
                .start();

        LOGGER.info("span agent grpc server started on port {}....", port);

        try {
            server.awaitTermination();
        } catch (InterruptedException ex) {
            LOGGER.error("span agent server has been interrupted with exception", ex);
        }
    }

    @VisibleForTesting
    List loadSpanEnrichers(final Config config) {
        if (config.hasPath("enrichers")) {
            return config.getStringList("enrichers")
                    .stream()
                    .map(clazz -> {
                        try {
                            final Class c = Class.forName(clazz);
                            LOGGER.info("Initializing the span enricher with class name '{}'", clazz);
                            return (Enricher) c.newInstance();
                        } catch (Exception e) {
                            LOGGER.error("Fail to initialize the enricher with clazz name {}", clazz, e);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public void close() {
        try {
            for (final Dispatcher dispatcher : dispatchers) {
                dispatcher.close();
            }
            LOGGER.info("shutting down gRPC server and jmx reporter");
            server.shutdown();
        } catch (Exception ignored) {
        }
    }

    @VisibleForTesting
    List loadAndInitializeDispatchers(final Config config, ClassLoader cl) {
        final List dispatchers = new ArrayList<>();
        final ServiceLoader loadedDispatchers = ServiceLoader.load(Dispatcher.class, cl);

        for (final Dispatcher dispatcher : loadedDispatchers) {
            final Map dispatches = ConfigurationHelpers.readDispatchersConfig(config, getName());
            dispatches
                    .entrySet()
                    .stream()
                    .filter((e) -> e.getKey().equalsIgnoreCase(dispatcher.getName()))
                    .forEach((conf) -> {
                        dispatcher.initialize(conf.getValue());
                        dispatchers.add(dispatcher);
                    });
        }

        Validate.notEmpty(dispatchers, "Span agent dispatchers can't be an empty set");

        return dispatchers;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy