package com.netflix.suro.sink; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import com.netflix.config.DynamicStringProperty; import com.netflix.governator.annotations.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.PostConstruct; import java.util.Map; /** * {@link com.netflix.config.DynamicProperty} driven sink configuration. Whenever a change is made to the * dynamic property, this module will parse the JSON and set a new configuration on the * main SinkManager. * * @author elandau */ public class DynamicPropertySinkConfigurator { private static final Logger log = LoggerFactory.getLogger(DynamicPropertySinkConfigurator.class); public static final String SINK_PROPERTY = "SuroServer.sinkConfig"; private final SinkManager sinkManager; private final ObjectMapper jsonMapper; @Configuration(SINK_PROPERTY) private String initialSink; @Inject public DynamicPropertySinkConfigurator( SinkManager sinkManager, ObjectMapper jsonMapper) { this.sinkManager = sinkManager; this.jsonMapper = jsonMapper; } @PostConstruct public void init() { DynamicStringProperty sinkDescription = new DynamicStringProperty(SINK_PROPERTY, initialSink) { @Override protected void propertyChanged() { buildSink(get(), false); } }; buildSink(sinkDescription.get(), true); } private void buildSink(String sink, boolean initStart) { try { Map<String, Sink> newSinkMap = jsonMapper.readValue(sink, new TypeReference<Map<String, Sink>>(){}); if ( !newSinkMap.containsKey("default") ) { throw new IllegalStateException("default sink should be defined"); } if (initStart) { sinkManager.initialSet(newSinkMap); } else { sinkManager.set(newSinkMap); } } catch (Exception e) { log.error("Exception on building SinkManager: " + e.getMessage(), e); } } }