Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add runtime warnings for the deprecated extensions used in Siddhi Apps #1734

Merged
merged 4 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@

boolean deprecated() default false;

String deprecationNotice() default "";

Parameter[] parameters() default {};

ParameterOverload[] parameterOverloads() default {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,10 @@ public interface SiddhiAppRuntime {
*/
void enablePlayBack(boolean playBackEnabled, Long idleTime, Long incrementInMilliseconds);

/**
* Method to get Siddhi App runtime warnings.
*
* @return list of recorded runtime warnings.
*/
Set<String> getWarnings();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package io.siddhi.core;

import com.lmax.disruptor.ExceptionHandler;
import io.siddhi.annotation.Extension;
import io.siddhi.core.aggregation.AggregationRuntime;
import io.siddhi.core.config.SiddhiAppContext;
import io.siddhi.core.debugger.SiddhiDebugger;
Expand Down Expand Up @@ -67,6 +68,7 @@
import io.siddhi.core.util.statistics.metrics.Level;
import io.siddhi.core.window.Window;
import io.siddhi.query.api.SiddhiApp;
import io.siddhi.query.api.annotation.Annotation;
import io.siddhi.query.api.definition.AbstractDefinition;
import io.siddhi.query.api.definition.AggregationDefinition;
import io.siddhi.query.api.definition.Attribute;
Expand All @@ -84,6 +86,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -136,6 +139,7 @@ public class SiddhiAppRuntimeImpl implements SiddhiAppRuntime {
private boolean runningWithoutSources = false;
private Future futureIncrementalPersistor;
private boolean incrementalDataPurging = true;
private Set<String> warnings = new HashSet<>();


public SiddhiAppRuntimeImpl(Map<String, AbstractDefinition> streamDefinitionMap,
Expand Down Expand Up @@ -176,7 +180,7 @@ public SiddhiAppRuntimeImpl(Map<String, AbstractDefinition> streamDefinitionMap,
onDemandQueryLatencyTracker = QueryParserHelper.createLatencyTracker(siddhiAppContext, "query",
SiddhiConstants.METRIC_INFIX_ON_DEMAND_QUERIES, null);
}

collectDeprecateWarnings();
for (Map.Entry<String, List<Sink>> sinkEntries : sinkMap.entrySet()) {
addCallback(sinkEntries.getKey(),
new SinkCallback(sinkEntries.getValue(), streamDefinitionMap.get(sinkEntries.getKey())));
Expand Down Expand Up @@ -925,4 +929,41 @@ public void enablePlayBack(boolean playBackEnabled, Long idleTime, Long incremen
}
}
}

private void collectDeprecateWarnings() {
Map<String, Class> deprecatedExtensions = siddhiAppContext.getSiddhiContext().getDeprecatedSiddhiExtensions();
List<AbstractDefinition> extensionsInUse = new ArrayList<>();
extensionsInUse.addAll(streamDefinitionMap.values());
extensionsInUse.addAll(tableDefinitionMap.values());
extensionsInUse.addAll(windowDefinitionMap.values());
extensionsInUse.addAll(aggregationDefinitionMap.values());
for (AbstractDefinition extDefinition : extensionsInUse) {
for (Annotation annotation : extDefinition.getAnnotations()) {
String type = annotation.getElement(SiddhiConstants.ANNOTATION_ELEMENT_TYPE);
if (annotation.getName().equalsIgnoreCase(SiddhiConstants.ANNOTATION_SOURCE)) {
type = "source:" + type;
}
if (annotation.getName().equalsIgnoreCase(SiddhiConstants.ANNOTATION_SINK)) {
type = "sink:" + type;
}
if (annotation.getName().equalsIgnoreCase(SiddhiConstants.ANNOTATION_STORE)) {
type = "store:" + type;
}
if (type != null && deprecatedExtensions.containsKey(type)) {
Class ext = deprecatedExtensions.get(type);
Extension extAnnotation = (Extension) ext.getAnnotation(Extension.class);
String warning = extAnnotation.deprecationNotice().isEmpty()
? type + " is being deprecated."
: extAnnotation.deprecationNotice();
warnings.add(warning);
log.warn(warning);
}
}
}
}

@Override
public Set<String> getWarnings() {
return warnings;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class SiddhiContext {

private ExceptionHandler<Object> defaultDisrupterExceptionHandler;
private Map<String, Class> siddhiExtensions = new HashMap<>();
private Map<String, Class> deprecatedSiddhiExtensions = new HashMap<>();
private PersistenceStore persistenceStore = null;
private IncrementalPersistenceStore incrementalPersistenceStore = null;
private ErrorStore errorStore = null;
Expand All @@ -62,7 +63,7 @@ public class SiddhiContext {
private Map<String, Object> attributes;

public SiddhiContext() {
SiddhiExtensionLoader.loadSiddhiExtensions(siddhiExtensions, extensionHolderMap);
SiddhiExtensionLoader.loadSiddhiExtensions(siddhiExtensions, extensionHolderMap, deprecatedSiddhiExtensions);
siddhiDataSources = new ConcurrentHashMap<String, DataSource>();
statisticsConfiguration = new StatisticsConfiguration(new SiddhiMetricsFactory());
configManager = new InMemoryConfigManager();
Expand Down Expand Up @@ -154,6 +155,10 @@ public ConcurrentHashMap<Class, AbstractExtensionHolder> getExtensionHolderMap()
return extensionHolderMap;
}

public Map<String, Class> getDeprecatedSiddhiExtensions() {
return deprecatedSiddhiExtensions;
}

public ExceptionHandler<Object> getDefaultDisrupterExceptionHandler() {
return defaultDisrupterExceptionHandler;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
public class SiddhiExtensionLoader {

private static final Logger log = Logger.getLogger(SiddhiExtensionLoader.class);
private static List<Class> extensionNameSpaceList = new ArrayList<>();
private static final Class ATTRIBUTE_AGGREGATOR_EXECUTOR_CLASS = AttributeAggregatorExecutor.class;
private static final Class DISTRIBUTION_STRATEGY_CLASS = DistributionStrategy.class;
private static final Class FUNCTION_EXECUTOR_CLASS = FunctionExecutor.class;
Expand All @@ -72,6 +71,7 @@ public class SiddhiExtensionLoader {
private static final Class STREAM_PROCESSOR_CLASS = StreamProcessor.class;
private static final Class TABLE_CLASS = Table.class;
private static final Class WINDOW_PROCESSOR_CLASS = WindowProcessor.class;
private static List<Class> extensionNameSpaceList = new ArrayList<>();

static {
extensionNameSpaceList.add(DISTRIBUTION_STRATEGY_CLASS);
Expand All @@ -92,45 +92,51 @@ public class SiddhiExtensionLoader {
/**
* Helper method to load the Siddhi extensions.
*
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param deprecatedSiddhiExtensionsMap reference map for the deprecated Siddhi extensions
*/
public static void loadSiddhiExtensions(Map<String, Class> siddhiExtensionsMap,
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderMap) {
loadLocalExtensions(siddhiExtensionsMap, extensionHolderMap);
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderMap,
Map<String, Class> deprecatedSiddhiExtensionsMap) {
loadLocalExtensions(siddhiExtensionsMap, extensionHolderMap, deprecatedSiddhiExtensionsMap);
BundleContext bundleContext = ReferenceHolder.getInstance().getBundleContext();
if (bundleContext != null) {
loadExtensionOSGI(bundleContext, siddhiExtensionsMap, extensionHolderMap);
loadExtensionOSGI(bundleContext, siddhiExtensionsMap, extensionHolderMap, deprecatedSiddhiExtensionsMap);
}
}

/**
* Load Extensions in OSGi environment.
*
* @param bundleContext OSGi bundleContext
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param bundleContext OSGi bundleContext
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param deprecatedSiddhiExtensionsMap reference map for the deprecated Siddhi extensions
*/
private static void loadExtensionOSGI(BundleContext bundleContext,
Map<String, Class> siddhiExtensionsMap,
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderMap) {
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderMap,
Map<String, Class> deprecatedSiddhiExtensionsMap) {
ExtensionBundleListener extensionBundleListener
= new ExtensionBundleListener(siddhiExtensionsMap, extensionHolderMap);
= new ExtensionBundleListener(siddhiExtensionsMap, extensionHolderMap, deprecatedSiddhiExtensionsMap);
bundleContext.addBundleListener(extensionBundleListener);
extensionBundleListener.loadAllExtensions(bundleContext);
}

/**
* Load Siddhi extensions in java non OSGi environment.
*
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param deprecatedSiddhiExtensionsMap reference map for the deprecated Siddhi extensions
*/
private static void loadLocalExtensions(Map<String, Class> siddhiExtensionsMap,
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderMap) {
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderMap,
Map<String, Class> deprecatedSiddhiExtensionsMap) {
Iterable<Class<?>> extensions = ClassIndex.getAnnotated(Extension.class);
for (Class extension : extensions) {
addExtensionToMap(extension, siddhiExtensionsMap, extensionHolderMap);
addExtensionToMap(extension, siddhiExtensionsMap, extensionHolderMap, deprecatedSiddhiExtensionsMap);
}

// load extensions related to incremental aggregation
Expand All @@ -149,13 +155,14 @@ private static void loadLocalExtensions(Map<String, Class> siddhiExtensionsMap,
/**
* Adding extensions to Siddhi siddhiExtensionsMap.
*
* @param extensionClass extension class
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param extensionClass extension class
* @param siddhiExtensionsMap reference map for the Siddhi extension
* @param extensionHolderMap reference map for the Siddhi extension holder
* @param deprecatedSiddhiExtensionsMap reference map for the deprecated Siddhi extensions
*/
private static void addExtensionToMap(Class extensionClass, Map<String, Class> siddhiExtensionsMap,
ConcurrentHashMap<Class, AbstractExtensionHolder>
extensionHolderMap) {
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderMap,
Map<String, Class> deprecatedSiddhiExtensionsMap) {
Extension siddhiExtensionAnnotation = (Extension) extensionClass.getAnnotation(Extension.class);
if (siddhiExtensionAnnotation != null) {
if (!siddhiExtensionAnnotation.name().isEmpty()) {
Expand All @@ -166,6 +173,9 @@ private static void addExtensionToMap(Class extensionClass, Map<String, Class> s
Class existingValue = siddhiExtensionsMap.get(key);
if (existingValue == null) {
previousClass = siddhiExtensionsMap.put(key, extensionClass);
if (siddhiExtensionAnnotation.deprecated()) {
deprecatedSiddhiExtensionsMap.put(key, extensionClass);
}
for (Class clazz : extensionNameSpaceList) {
putToExtensionHolderMap(clazz, extensionClass, key,
extensionHolderMap);
Expand All @@ -179,6 +189,9 @@ private static void addExtensionToMap(Class extensionClass, Map<String, Class> s
}
} else {
previousClass = siddhiExtensionsMap.put(siddhiExtensionAnnotation.name(), extensionClass);
if (siddhiExtensionAnnotation.deprecated()) {
deprecatedSiddhiExtensionsMap.put(siddhiExtensionAnnotation.name(), extensionClass);
}
if (previousClass != null) {
log.warn("Dropping extension '" + previousClass + "' as '" + extensionClass + "' is " +
"loaded with the same name '" + siddhiExtensionAnnotation.name() + "'");
Expand Down Expand Up @@ -220,6 +233,7 @@ private static void putToExtensionHolderMap(

/**
* Remove extensions to Siddhi siddhiExtensionsHolderMap.
*
* @param extensionKey fully qualified extension name (namespace:extensionName)
* @param extension extension class (eg:HttpSource)
* @param extensionHolderConcurrentHashMap reference map for the Siddhi extension holder
Expand Down Expand Up @@ -265,12 +279,15 @@ private static class ExtensionBundleListener implements BundleListener {

private Map<Class, Integer> bundleExtensions = new HashMap<Class, Integer>();
private Map<String, Class> siddhiExtensionsMap;
private Map<String, Class> deprecatedSiddhiExtensionsMap;
private ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderConcurrentHashMap;

ExtensionBundleListener(Map<String, Class> siddhiExtensionsMap,
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderConcurrentHashMap) {
ConcurrentHashMap<Class, AbstractExtensionHolder> extensionHolderConcurrentHashMap,
Map<String, Class> deprecatedSiddhiExtensionsMap) {
this.siddhiExtensionsMap = siddhiExtensionsMap;
this.extensionHolderConcurrentHashMap = extensionHolderConcurrentHashMap;
this.deprecatedSiddhiExtensionsMap = deprecatedSiddhiExtensionsMap;
}

@Override
Expand All @@ -286,7 +303,8 @@ private void addExtensions(Bundle bundle) {
ClassLoader classLoader = bundle.adapt(BundleWiring.class).getClassLoader();
Iterable<Class<?>> extensions = ClassIndex.getAnnotated(Extension.class, classLoader);
for (Class extension : extensions) {
addExtensionToMap(extension, siddhiExtensionsMap, extensionHolderConcurrentHashMap);
addExtensionToMap(extension, siddhiExtensionsMap,
extensionHolderConcurrentHashMap, deprecatedSiddhiExtensionsMap);
bundleExtensions.put(extension, (int) bundle.getBundleId());
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 io.siddhi.core.managment;

import io.siddhi.core.SiddhiAppRuntime;
import io.siddhi.core.SiddhiManager;
import io.siddhi.core.event.Event;
import io.siddhi.core.stream.input.InputHandler;
import io.siddhi.core.util.EventPrinter;
import org.apache.log4j.Logger;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class WarningTestCase {
private static final Logger log = Logger.getLogger(WarningTestCase.class);

@BeforeMethod
public void init() {
// do nothing.
}

@Test
public void warningTest() throws InterruptedException {
log.info("warningTest");
SiddhiManager siddhiManager = new SiddhiManager();
String streams = "" +
"define stream StockStream (symbol string, price float, volume long); " +
"@Store(type=\"testStoreContainingInMemoryTable\")\n" +
"define table StockTable (symbol string, volume long); ";

String query1 = "" +
"@info(name = 'query1') " +
"from StockStream\n" +
"select symbol, volume\n" +
"insert into StockTable ;";
SiddhiAppRuntime siddhiAppRuntime = siddhiManager.createSiddhiAppRuntime(streams + query1);
InputHandler stockStream = siddhiAppRuntime.getInputHandler("StockStream");
siddhiAppRuntime.start();

stockStream.send(new Object[]{"WSO2", 55.6f, 100L});
stockStream.send(new Object[]{"IBM", 75.6f, 100L});
Thread.sleep(1000);

Event[] events = siddhiAppRuntime.query("" +
"from StockTable ");
EventPrinter.print(events);
AssertJUnit.assertEquals(2, events.length);
AssertJUnit.assertEquals(1, siddhiAppRuntime.getWarnings().size());
AssertJUnit.assertTrue(siddhiAppRuntime.getWarnings()
.contains("store:testStoreContainingInMemoryTable is being deprecated for testing purposes."));
siddhiAppRuntime.shutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
*/
@Extension(
name = "testStoreContainingInMemoryTable",
deprecated = true,
deprecationNotice = "store:testStoreContainingInMemoryTable is being deprecated for testing purposes.",
namespace = "store",
description = "Using this implementation a testing for store extension can be done.",
examples = {
Expand Down
2 changes: 1 addition & 1 deletion modules/siddhi-query-compiler/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,6 @@
</build>

<properties>
<mavan.findbugsplugin.exclude.file>findbugs-exclude.xml</mavan.findbugsplugin.exclude.file>
<mavan.findbugsplugin.exclude.file>../../findbugs-exclude.xml</mavan.findbugsplugin.exclude.file>
</properties>
</project>