├── README.md
├── .gitignore
├── src
└── main
│ └── java
│ ├── org
│ └── kettle
│ │ ├── xp
│ │ ├── LastZoomBase.java
│ │ ├── SetDefaultJobZoomLevelExtensionPoint.java
│ │ ├── SetDefaultTransZoomLevelExtensionPoint.java
│ │ ├── LogJobExecutionTimeExtensionPoint.java
│ │ ├── LogTransExecutionTimeExtensionPoint.java
│ │ ├── DrawStepDebugLevelBeeExtensionPoint.java
│ │ ├── util
│ │ │ ├── SvgLoader.java
│ │ │ └── ZoomLevel.java
│ │ ├── DrawJobEntryDebugLevelBeeExtensionPoint.java
│ │ ├── SetStepDebugLevelExtensionPoint.java
│ │ └── ModifyJobEntryLogLevelExtensionPoint.java
│ │ ├── xul
│ │ ├── spoon_overlays.xul
│ │ ├── job_graph_overlays.xul
│ │ └── trans_graph_overlays.xul
│ │ ├── util
│ │ ├── Defaults.java
│ │ └── DebugLevelUtil.java
│ │ ├── PDIMessages.java
│ │ ├── StepDebugLevel.java
│ │ ├── DebugPluginsSpoonPlugin.java
│ │ ├── JobEntryDebugLevel.java
│ │ ├── DebugPluginsHelper.java
│ │ └── dialog
│ │ ├── StepDebugLevelDialog.java
│ │ └── JobEntryDebugLevelDialog.java
│ └── bee.svg
├── pom.xml
├── LICENSE
└── kettle-debug-plugin.iml
/README.md:
--------------------------------------------------------------------------------
1 | # kettle-debug-plugin
2 |
3 | Various useful plugins to increase esae of debugging transformations and jobs
4 |
5 | See: https://github.com/mattcasters/kettle-debug-plugin/wiki
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | .idea/
26 | .idea/compiler.xml
27 | .idea/encodings.xml
28 | .idea/uiDesigner.xml
29 | .idea/vcs.xml
30 |
31 | .idea/misc.xml
32 | .idea/workspace.xml
33 | target/
34 | kettle-debug-plugin.iml
35 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/LastZoomBase.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.kettle.xp.util.ZoomLevel;
4 | import org.pentaho.di.job.JobPainter;
5 | import org.pentaho.di.trans.TransPainter;
6 |
7 |
8 | public class LastZoomBase {
9 |
10 | private static int lastZoom;
11 |
12 | public void rememberTransZoomLevel(TransPainter transPainter) {
13 |
14 | ZoomLevel.getInstance().setLastTransMagnification( transPainter.getMagnification() );
15 | }
16 |
17 | public void rememberJobZoomLevel(JobPainter jobPainter) {
18 |
19 | ZoomLevel.getInstance().setLastJobMagnification( jobPainter.getMagnification() );
20 | }
21 |
22 |
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xul/spoon_overlays.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
13 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/util/Defaults.java:
--------------------------------------------------------------------------------
1 | package org.kettle.util;
2 |
3 | import java.util.Arrays;
4 | import java.util.HashSet;
5 | import java.util.List;
6 | import java.util.Set;
7 |
8 | public class Defaults {
9 | public static final String DEBUG_GROUP = "debug_plugin";
10 |
11 | public static final String STEP_ATTR_LOGLEVEL = "log_level";
12 | public static final String STEP_ATTR_START_ROW = "start_row";
13 | public static final String STEP_ATTR_END_ROW = "end_row";
14 | public static final String STEP_ATTR_CONDITION = "condition";
15 |
16 | public static final String JOBENTRY_ATTR_LOGLEVEL = "entry_log_level";
17 | public static final String JOBENTRY_ATTR_LOG_RESULT= "entry_log_result";
18 | public static final String JOBENTRY_ATTR_LOG_VARIABLES= "entry_log_variables";
19 | public static final String JOBENTRY_ATTR_LOG_RESULT_ROWS = "entry_log_result_rows";
20 | public static final String JOBENTRY_ATTR_LOG_RESULT_FILES = "entry_log_result_files";
21 |
22 | public static final String VARIABLE_KETTLE_DEBUG_DURATION = "KETTLE_DEBUG_DURATION";
23 |
24 | public static final Set VARIABLES_TO_IGNORE = getVariablesToIgnore();
25 |
26 | private static Set getVariablesToIgnore() {
27 | Set strings = new HashSet<>( );
28 |
29 | List valuesList = Arrays.asList("vfs.hc.embeddedMetastoreKey");
30 | strings.addAll( valuesList );
31 |
32 | return strings;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/SetDefaultJobZoomLevelExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.widgets.Combo;
5 | import org.eclipse.swt.widgets.Control;
6 | import org.eclipse.swt.widgets.Event;
7 | import org.eclipse.swt.widgets.ToolBar;
8 | import org.eclipse.swt.widgets.ToolItem;
9 | import org.kettle.xp.util.ZoomLevel;
10 | import org.pentaho.di.core.exception.KettleException;
11 | import org.pentaho.di.core.extension.ExtensionPoint;
12 | import org.pentaho.di.core.extension.ExtensionPointInterface;
13 | import org.pentaho.di.core.logging.LogChannelInterface;
14 | import org.pentaho.di.job.JobMeta;
15 | import org.pentaho.di.trans.TransMeta;
16 | import org.pentaho.di.ui.spoon.Spoon;
17 | import org.pentaho.di.ui.spoon.job.JobGraph;
18 | import org.pentaho.di.ui.spoon.trans.TransGraph;
19 |
20 | @ExtensionPoint(
21 | id = "SetDefaultJobZoomLevelExtensionPoint",
22 | description = "After a file is opened, set the appropriate zoom level",
23 | extensionPointId = "JobAfterOpen"
24 | )
25 | /**
26 | * Every time we load a transformation in Spoon, set the zoom level to what we used last time...
27 | */
28 | public class SetDefaultJobZoomLevelExtensionPoint implements ExtensionPointInterface {
29 |
30 | @Override public void callExtensionPoint( LogChannelInterface log, Object o ) throws KettleException {
31 |
32 | ZoomLevel.changeJobGraphZoomLevel();
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/SetDefaultTransZoomLevelExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.custom.CTabFolder;
5 | import org.eclipse.swt.custom.CTabItem;
6 | import org.eclipse.swt.graphics.GC;
7 | import org.eclipse.swt.graphics.Image;
8 | import org.eclipse.swt.graphics.Point;
9 | import org.eclipse.swt.widgets.Combo;
10 | import org.eclipse.swt.widgets.Composite;
11 | import org.eclipse.swt.widgets.Control;
12 | import org.eclipse.swt.widgets.Display;
13 | import org.eclipse.swt.widgets.Label;
14 | import org.eclipse.swt.widgets.ToolBar;
15 | import org.eclipse.swt.widgets.ToolItem;
16 | import org.kettle.xp.util.ZoomLevel;
17 | import org.pentaho.di.core.exception.KettleException;
18 | import org.pentaho.di.core.extension.ExtensionPoint;
19 | import org.pentaho.di.core.extension.ExtensionPointInterface;
20 | import org.pentaho.di.core.logging.LogChannelInterface;
21 | import org.pentaho.di.ui.spoon.Spoon;
22 | import org.pentaho.di.ui.spoon.trans.TransGraph;
23 |
24 | @ExtensionPoint(
25 | id = "SetDefaultTransZoomLevelExtensionPoint",
26 | description = "After a file is opened, set the appropriate zoom level",
27 | extensionPointId = "TransAfterOpen"
28 | )
29 | /**
30 | * Every time we load a transformation in Spoon, set the zoom level to what we used last time...
31 | */
32 | public class SetDefaultTransZoomLevelExtensionPoint implements ExtensionPointInterface {
33 |
34 | @Override public void callExtensionPoint( LogChannelInterface log, Object o ) throws KettleException {
35 |
36 | ZoomLevel.changeTransGraphZoomLevel();
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xul/job_graph_overlays.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
41 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xul/trans_graph_overlays.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
40 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/PDIMessages.java:
--------------------------------------------------------------------------------
1 | /*! ******************************************************************************
2 | *
3 | * Pentaho Data Integration
4 | *
5 | * Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
6 | *
7 | *******************************************************************************
8 | *
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with
11 | * the License. You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | *
21 | ******************************************************************************/
22 |
23 | package org.kettle;
24 |
25 | import java.util.Enumeration;
26 | import java.util.ResourceBundle;
27 |
28 | import org.pentaho.di.i18n.BaseMessages;
29 |
30 | public class PDIMessages extends ResourceBundle{
31 |
32 | // private static ResourceBundle lafBundle;
33 |
34 | private Class> clz = this.getClass();
35 |
36 | public PDIMessages(){
37 | }
38 |
39 | public PDIMessages(Class> pkg){
40 | this.clz = pkg;
41 | }
42 |
43 | @Override
44 | public Enumeration getKeys() {
45 | return null;
46 | }
47 |
48 | @Override
49 | protected Object handleGetObject(String key) {
50 | String result = BaseMessages.getString(clz, key);
51 | return result;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/LogJobExecutionTimeExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.kettle.util.DebugLevelUtil;
4 | import org.kettle.util.Defaults;
5 | import org.pentaho.di.core.exception.KettleException;
6 | import org.pentaho.di.core.extension.ExtensionPoint;
7 | import org.pentaho.di.core.extension.ExtensionPointInterface;
8 | import org.pentaho.di.core.logging.LogChannelInterface;
9 | import org.pentaho.di.job.Job;
10 | import org.pentaho.di.job.JobAdapter;
11 | import org.pentaho.di.trans.Trans;
12 | import org.pentaho.di.trans.TransAdapter;
13 |
14 | import java.util.concurrent.TimeUnit;
15 |
16 | @ExtensionPoint(
17 | id = "LogJobExecutionTimeExtensionPoint",
18 | description = "Logs execution time of a job when it finishes",
19 | extensionPointId = "JobStart"
20 | )
21 | /**
22 | * set the debug level right before the step starts to run
23 | */
24 | public class LogJobExecutionTimeExtensionPoint implements ExtensionPointInterface {
25 |
26 | @Override public void callExtensionPoint( LogChannelInterface log, Object o ) throws KettleException {
27 | if (!(o instanceof Job )) {
28 | return;
29 | }
30 |
31 | Job job = (Job) o;
32 |
33 | // If the KETTLE_DEBUG_DURATION variable is set to N or FALSE, we don't log duration
34 | //
35 | String durationVariable = job.getVariable( Defaults.VARIABLE_KETTLE_DEBUG_DURATION, "Y" );
36 | if ("N".equalsIgnoreCase( durationVariable ) || "FALSE".equalsIgnoreCase( durationVariable)) {
37 | // Nothing to do here
38 | return;
39 | }
40 |
41 | final long startTime = System.currentTimeMillis();
42 |
43 | job.addJobListener( new JobAdapter() {
44 | @Override public void jobFinished( Job job ) throws KettleException {
45 | long endTime = System.currentTimeMillis();
46 | double seconds = ((double)endTime - (double)startTime) / 1000;
47 | log.logBasic("Job duration : "+ seconds+" seconds [ "+ DebugLevelUtil.getDurationHMS( seconds ) +" ]");
48 |
49 | }
50 | } );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/LogTransExecutionTimeExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.kettle.util.DebugLevelUtil;
4 | import org.kettle.util.Defaults;
5 | import org.pentaho.di.core.exception.KettleException;
6 | import org.pentaho.di.core.extension.ExtensionPoint;
7 | import org.pentaho.di.core.extension.ExtensionPointInterface;
8 | import org.pentaho.di.core.logging.LogChannelInterface;
9 | import org.pentaho.di.core.logging.LogLevel;
10 | import org.pentaho.di.trans.Trans;
11 | import org.pentaho.di.trans.TransAdapter;
12 | import org.pentaho.di.trans.step.BaseStep;
13 | import org.pentaho.di.trans.step.StepInterface;
14 |
15 | import java.util.List;
16 | import java.util.Map;
17 | import java.util.concurrent.TimeUnit;
18 |
19 | @ExtensionPoint(
20 | id = "LogTransExecutionTimeExtensionPoint",
21 | description = "Logs execution time of a transformation when it finishes",
22 | extensionPointId = "TransformationPrepareExecution"
23 | )
24 | /**
25 | * set the debug level right before the step starts to run
26 | */
27 | public class LogTransExecutionTimeExtensionPoint implements ExtensionPointInterface {
28 |
29 | @Override public void callExtensionPoint( LogChannelInterface log, Object o ) throws KettleException {
30 | if (!(o instanceof Trans )) {
31 | return;
32 | }
33 |
34 | Trans trans= (Trans) o;
35 |
36 | // If the KETTLE_DEBUG_DURATION variable is set to N or FALSE, we don't log duration
37 | //
38 | String durationVariable = trans.getVariable( Defaults.VARIABLE_KETTLE_DEBUG_DURATION, "Y" );
39 | if ("N".equalsIgnoreCase( durationVariable ) || "FALSE".equalsIgnoreCase( durationVariable)) {
40 | // Nothing to do here
41 | return;
42 | }
43 |
44 | final long startTime = System.currentTimeMillis();
45 |
46 | trans.addTransListener( new TransAdapter() {
47 | @Override public void transFinished( Trans trans ) throws KettleException {
48 | long endTime = System.currentTimeMillis();
49 | double seconds = ((double)endTime - (double)startTime) / 1000;
50 | log.logBasic("Transformation duration : "+ seconds+" seconds [ "+ DebugLevelUtil.getDurationHMS( seconds ) +" ]");
51 | }
52 | } );
53 |
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/StepDebugLevel.java:
--------------------------------------------------------------------------------
1 | package org.kettle;
2 |
3 | import org.pentaho.di.core.Condition;
4 | import org.pentaho.di.core.logging.LogLevel;
5 |
6 | public class StepDebugLevel implements Cloneable {
7 | private LogLevel logLevel;
8 | private int startRow;
9 | private int endRow;
10 | private Condition condition;
11 |
12 | public StepDebugLevel() {
13 | condition = new Condition();
14 | logLevel=LogLevel.DEBUG;
15 | startRow=-1;
16 | endRow=-1;
17 | }
18 |
19 | public StepDebugLevel( LogLevel logLevel ) {
20 | this();
21 | this.logLevel = logLevel;
22 | }
23 |
24 | public StepDebugLevel( LogLevel logLevel, int startRow, int endRow, Condition condition ) {
25 | this(logLevel);
26 | this.startRow = startRow;
27 | this.endRow = endRow;
28 | this.condition = condition;
29 | }
30 |
31 | @Override public StepDebugLevel clone() {
32 | return new StepDebugLevel(logLevel, startRow, endRow, (Condition) condition.clone() );
33 | }
34 |
35 | /**
36 | * Gets logLevel
37 | *
38 | * @return value of logLevel
39 | */
40 | public LogLevel getLogLevel() {
41 | return logLevel;
42 | }
43 |
44 | /**
45 | * @param logLevel The logLevel to set
46 | */
47 | public void setLogLevel( LogLevel logLevel ) {
48 | this.logLevel = logLevel;
49 | }
50 |
51 | /**
52 | * Gets startRow
53 | *
54 | * @return value of startRow
55 | */
56 | public int getStartRow() {
57 | return startRow;
58 | }
59 |
60 | /**
61 | * @param startRow The startRow to set
62 | */
63 | public void setStartRow( int startRow ) {
64 | this.startRow = startRow;
65 | }
66 |
67 | /**
68 | * Gets endRow
69 | *
70 | * @return value of endRow
71 | */
72 | public int getEndRow() {
73 | return endRow;
74 | }
75 |
76 | /**
77 | * @param endRow The endRow to set
78 | */
79 | public void setEndRow( int endRow ) {
80 | this.endRow = endRow;
81 | }
82 |
83 | /**
84 | * Gets condition
85 | *
86 | * @return value of condition
87 | */
88 | public Condition getCondition() {
89 | return condition;
90 | }
91 |
92 | /**
93 | * @param condition The condition to set
94 | */
95 | public void setCondition( Condition condition ) {
96 | this.condition = condition;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/DrawStepDebugLevelBeeExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.kettle.StepDebugLevel;
4 | import org.kettle.util.DebugLevelUtil;
5 | import org.kettle.util.Defaults;
6 | import org.kettle.xp.util.SvgLoader;
7 | import org.pentaho.di.core.exception.KettleException;
8 | import org.pentaho.di.core.extension.ExtensionPoint;
9 | import org.pentaho.di.core.extension.ExtensionPointInterface;
10 | import org.pentaho.di.core.logging.LogChannelInterface;
11 | import org.pentaho.di.trans.TransPainterExtension;
12 | import org.pentaho.di.ui.spoon.Spoon;
13 |
14 | import java.awt.image.BufferedImage;
15 | import java.util.Map;
16 |
17 | @ExtensionPoint(
18 | id = "DrawStepDebugLevelBeeExtensionPoint",
19 | description = "Draw a bee over a step which has debug level information stored",
20 | extensionPointId = "TransPainterStep"
21 | )
22 | /**
23 | * Paint steps that have a debug level set...
24 | */
25 | public class DrawStepDebugLevelBeeExtensionPoint implements ExtensionPointInterface {
26 |
27 | private static BufferedImage beeImage;
28 |
29 | @Override public void callExtensionPoint( LogChannelInterface logChannelInterface, Object o ) throws KettleException {
30 | if ( !( o instanceof TransPainterExtension ) ) {
31 | return;
32 | }
33 |
34 | try {
35 | // The next statement sometimes causes an exception in WebSpoon
36 | // Keep it in the try/catch block
37 | //
38 | Spoon spoon = Spoon.getInstance();
39 | TransPainterExtension tpe = (TransPainterExtension) o;
40 |
41 | Map stepLevelMap = tpe.transMeta.getAttributesMap().get( Defaults.DEBUG_GROUP );
42 |
43 | if ( stepLevelMap != null ) {
44 |
45 | String stepname = tpe.stepMeta.getName();
46 |
47 | final StepDebugLevel debugLevel = DebugLevelUtil.getStepDebugLevel( stepLevelMap, stepname );
48 | if ( debugLevel != null ) {
49 |
50 | // Paint the bee...
51 | //
52 | // SwtUniversalImage beeImage = SwtSvgImageUtil.getUniversalImage( spoon.getDisplay(), this.getClass().getClassLoader(), "bee.svg" );
53 |
54 | if ( beeImage == null ) {
55 | beeImage = SvgLoader.transcodeSVGDocument( this.getClass().getClassLoader(), "bee.svg", 30, 26 );
56 | }
57 |
58 | tpe.gc.drawImage( beeImage, tpe.x1 + tpe.iconsize, tpe.y1 - tpe.iconsize / 2 );
59 |
60 | }
61 | }
62 | } catch ( Exception e ) {
63 | // Ignore error, not that important
64 | // logChannelInterface.logError( "Unable to handle specific debug level", e );
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/DebugPluginsSpoonPlugin.java:
--------------------------------------------------------------------------------
1 | /*! ******************************************************************************
2 | *
3 | * Pentaho Data Integration
4 | *
5 | * Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
6 | *
7 | *******************************************************************************
8 | *
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with
11 | * the License. You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | *
21 | ******************************************************************************/
22 |
23 | package org.kettle;
24 |
25 | import org.pentaho.di.ui.spoon.SpoonLifecycleListener;
26 | import org.pentaho.di.ui.spoon.SpoonPerspective;
27 | import org.pentaho.di.ui.spoon.SpoonPlugin;
28 | import org.pentaho.di.ui.spoon.SpoonPluginCategories;
29 | import org.pentaho.di.ui.spoon.SpoonPluginInterface;
30 | import org.pentaho.ui.xul.XulDomContainer;
31 | import org.pentaho.ui.xul.XulException;
32 |
33 | @SpoonPlugin( id = "Debug", image = "" )
34 | @SpoonPluginCategories( { "spoon", "trans-graph", "job-graph" } )
35 | public class DebugPluginsSpoonPlugin implements SpoonPluginInterface {
36 |
37 | public DebugPluginsSpoonPlugin() {
38 | }
39 |
40 | public void applyToContainer( String category, XulDomContainer container ) throws XulException {
41 | container.registerClassLoader( getClass().getClassLoader() );
42 |
43 | if ( category.equals( "spoon" ) ) {
44 | container.loadOverlay( "org/kettle/xul/spoon_overlays.xul" );
45 | container.addEventHandler( DebugPluginsHelper.getInstance() );
46 | }
47 | if ( category.equals( "trans-graph" ) ) {
48 | container.loadOverlay( "org/kettle/xul/trans_graph_overlays.xul" );
49 | container.addEventHandler( DebugPluginsHelper.getInstance() );
50 | }
51 | if ( category.equals( "job-graph" ) ) {
52 | container.loadOverlay( "org/kettle/xul/job_graph_overlays.xul" );
53 | container.addEventHandler( DebugPluginsHelper.getInstance() );
54 | }
55 | }
56 |
57 | public SpoonLifecycleListener getLifecycleListener() {
58 | return null;
59 | }
60 |
61 | public SpoonPerspective getPerspective() {
62 | return null;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/util/SvgLoader.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp.util;
2 |
3 | import org.apache.batik.transcoder.Transcoder;
4 | import org.apache.batik.transcoder.TranscoderInput;
5 | import org.apache.batik.transcoder.TranscoderOutput;
6 | import org.apache.batik.transcoder.image.PNGTranscoder;
7 | import org.pentaho.di.core.exception.KettleException;
8 |
9 | import javax.swing.*;
10 | import java.awt.*;
11 | import java.awt.image.BufferedImage;
12 | import java.io.ByteArrayOutputStream;
13 | import java.io.InputStream;
14 |
15 | public class SvgLoader {
16 |
17 | public static BufferedImage transcodeSVGDocument( ClassLoader classLoader, String filename, int width, int height ) throws KettleException {
18 | // Create a PNG transcoder.
19 | Transcoder t = new PNGTranscoder();
20 |
21 | // Set the transcoding hints.
22 | t.addTranscodingHint( PNGTranscoder.KEY_WIDTH, new Float(width) );
23 | t.addTranscodingHint( PNGTranscoder.KEY_HEIGHT, new Float(height) );
24 |
25 | // Create the transcoder input.
26 | //
27 | InputStream inputStream = classLoader.getResourceAsStream( filename );
28 | TranscoderInput input = new TranscoderInput( inputStream );
29 |
30 | ByteArrayOutputStream ostream = null;
31 | try {
32 | // Create the transcoder output.
33 | ostream = new ByteArrayOutputStream();
34 | TranscoderOutput output = new TranscoderOutput( ostream );
35 |
36 | // Save the image.
37 | t.transcode( input, output );
38 |
39 | // Flush and close the stream.
40 | ostream.flush();
41 | ostream.close();
42 | } catch( Exception ex ){
43 | throw new KettleException( "Error loading svg file "+filename, ex );
44 | }
45 |
46 | // Convert the byte stream into an image.
47 | byte[] imgData = ostream.toByteArray();
48 | Image img = Toolkit.getDefaultToolkit().createImage( imgData );
49 |
50 | // Wait until the entire image is loaded.
51 | MediaTracker tracker = new MediaTracker( new JPanel() );
52 | tracker.addImage( img, 0 );
53 | try {
54 | tracker.waitForID( 0 );
55 | } catch( InterruptedException ex ){
56 | throw new KettleException( "Interrupted", ex );
57 | }
58 |
59 | // Return the newly rendered image.
60 | //
61 | if (img instanceof BufferedImage) {
62 | return (BufferedImage)img;
63 | }
64 |
65 | // Convert to a buffered image for the Kettle GC API
66 | //
67 | BufferedImage bufferedImage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
68 | Graphics2D bufferedGc = bufferedImage.createGraphics();
69 | bufferedGc.drawImage(img, 0, 0, null);
70 | bufferedGc.dispose();
71 | return bufferedImage;
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/DrawJobEntryDebugLevelBeeExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.kettle.JobEntryDebugLevel;
4 | import org.kettle.util.DebugLevelUtil;
5 | import org.kettle.util.Defaults;
6 | import org.kettle.xp.util.SvgLoader;
7 | import org.pentaho.di.core.exception.KettleException;
8 | import org.pentaho.di.core.extension.ExtensionPoint;
9 | import org.pentaho.di.core.extension.ExtensionPointInterface;
10 | import org.pentaho.di.core.gui.GCInterface;
11 | import org.pentaho.di.core.logging.LogChannelInterface;
12 | import org.pentaho.di.job.JobPainterExtension;
13 | import org.pentaho.di.job.entry.JobEntryCopy;
14 | import org.pentaho.di.ui.core.PropsUI;
15 | import org.pentaho.di.ui.spoon.Spoon;
16 |
17 | import java.awt.image.BufferedImage;
18 | import java.io.UnsupportedEncodingException;
19 | import java.util.Map;
20 |
21 | @ExtensionPoint(
22 | id = "DrawJobEntryDebugLevelBeeExtensionPoint",
23 | description = "Draw a bee over a job entry which has debug level information stored",
24 | extensionPointId = "JobPainterArrow"
25 | )
26 | /**
27 | * We need to use the hop drawing logic because the job entry XP is not available
28 | */
29 | public class DrawJobEntryDebugLevelBeeExtensionPoint implements ExtensionPointInterface {
30 |
31 | private static BufferedImage beeImage;
32 |
33 | @Override public void callExtensionPoint( LogChannelInterface log, Object o ) throws KettleException {
34 | if ( !( o instanceof JobPainterExtension ) ) {
35 | return;
36 | }
37 |
38 | try {
39 | // The next statement sometimes causes an exception in WebSpoon
40 | // Keep it in the try/catch block
41 | //
42 | Spoon spoon = Spoon.getInstance();
43 | JobPainterExtension jpe = (JobPainterExtension) o;
44 | int iconsize = PropsUI.getInstance().getIconSize();
45 |
46 | Map entryLevelMap = jpe.jobMeta.getAttributesMap().get( Defaults.DEBUG_GROUP );
47 |
48 | if ( entryLevelMap != null ) {
49 |
50 | drawBee( jpe.gc, entryLevelMap, jpe.jobHop.getFromEntry(), jpe.x1, jpe.y1, iconsize );
51 | drawBee( jpe.gc, entryLevelMap, jpe.jobHop.getToEntry(), jpe.x2, jpe.y2, iconsize );
52 | }
53 | } catch ( Exception e ) {
54 | // Ignore error, not that important
55 | // logChannelInterface.logError( "Unable to handle specific debug level", e );
56 | }
57 | }
58 |
59 | private void drawBee( GCInterface gc, Map entryLevelMap, JobEntryCopy copy, int x, int y, int iconsize ) throws Exception {
60 |
61 | final JobEntryDebugLevel debugLevel = DebugLevelUtil.getJobEntryDebugLevel( entryLevelMap, copy.toString() );
62 | if ( debugLevel == null ) {
63 | return;
64 | }
65 |
66 | if ( beeImage == null ) {
67 | beeImage = SvgLoader.transcodeSVGDocument( this.getClass().getClassLoader(), "bee.svg", 30, 26 );
68 | }
69 |
70 | gc.drawImage( beeImage, x + iconsize / 2, y - iconsize );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/JobEntryDebugLevel.java:
--------------------------------------------------------------------------------
1 | package org.kettle;
2 |
3 | import org.pentaho.di.core.Condition;
4 | import org.pentaho.di.core.logging.LogLevel;
5 |
6 | public class JobEntryDebugLevel implements Cloneable {
7 | private LogLevel logLevel;
8 |
9 | private boolean loggingResult;
10 | private boolean loggingVariables;
11 | private boolean loggingResultRows;
12 | private boolean loggingResultFiles;
13 |
14 | public JobEntryDebugLevel() {
15 | logLevel=LogLevel.DEBUG;
16 | loggingResult=false;
17 | loggingVariables=false;
18 | loggingResultRows=false;
19 | loggingResultFiles=false;
20 | }
21 |
22 | public JobEntryDebugLevel( LogLevel logLevel ) {
23 | this();
24 | this.logLevel = logLevel;
25 | }
26 |
27 | public JobEntryDebugLevel( LogLevel logLevel, boolean loggingResult, boolean loggingVariables, boolean loggingResultRows, boolean loggingResultFiles) {
28 | this(logLevel);
29 | this.loggingResult = loggingResult;
30 | this.loggingVariables = loggingVariables;
31 | this.loggingResultRows = loggingResultRows;
32 | this.loggingResultFiles = loggingResultFiles;
33 | }
34 |
35 | @Override public JobEntryDebugLevel clone() {
36 | return new JobEntryDebugLevel(logLevel, loggingResult, loggingVariables, loggingResultRows, loggingResultFiles );
37 | }
38 |
39 |
40 | /**
41 | * Gets logLevel
42 | *
43 | * @return value of logLevel
44 | */
45 | public LogLevel getLogLevel() {
46 | return logLevel;
47 | }
48 |
49 | /**
50 | * @param logLevel The logLevel to set
51 | */
52 | public void setLogLevel( LogLevel logLevel ) {
53 | this.logLevel = logLevel;
54 | }
55 |
56 | /**
57 | * Gets loggingResult
58 | *
59 | * @return value of loggingResult
60 | */
61 | public boolean isLoggingResult() {
62 | return loggingResult;
63 | }
64 |
65 | /**
66 | * @param loggingResult The loggingResult to set
67 | */
68 | public void setLoggingResult( boolean loggingResult ) {
69 | this.loggingResult = loggingResult;
70 | }
71 |
72 | /**
73 | * Gets loggingVariables
74 | *
75 | * @return value of loggingVariables
76 | */
77 | public boolean isLoggingVariables() {
78 | return loggingVariables;
79 | }
80 |
81 | /**
82 | * @param loggingVariables The loggingVariables to set
83 | */
84 | public void setLoggingVariables( boolean loggingVariables ) {
85 | this.loggingVariables = loggingVariables;
86 | }
87 |
88 | /**
89 | * Gets loggingResultRows
90 | *
91 | * @return value of loggingResultRows
92 | */
93 | public boolean isLoggingResultRows() {
94 | return loggingResultRows;
95 | }
96 |
97 | /**
98 | * @param loggingResultRows The loggingResultRows to set
99 | */
100 | public void setLoggingResultRows( boolean loggingResultRows ) {
101 | this.loggingResultRows = loggingResultRows;
102 | }
103 |
104 | /**
105 | * Gets loggingResultFiles
106 | *
107 | * @return value of loggingResultFiles
108 | */
109 | public boolean isLoggingResultFiles() {
110 | return loggingResultFiles;
111 | }
112 |
113 | /**
114 | * @param loggingResultFiles The loggingResultFiles to set
115 | */
116 | public void setLoggingResultFiles( boolean loggingResultFiles ) {
117 | this.loggingResultFiles = loggingResultFiles;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.pentaho
7 | pentaho-ce-jar-parent-pom
8 | 8.1-SNAPSHOT
9 |
10 | kettle-debug-plugin
11 | ${project.artifactId}
12 | Various useful plugins to increase esae of debugging transformations and jobs
13 |
14 |
15 | Apache License, version 2.0
16 | https://www.apache.org/licenses/LICENSE-2.0
17 | repo
18 |
19 |
20 |
21 |
22 | 8.1-SNAPSHOT
23 | 1.9.5
24 | 4.4
25 |
26 |
27 |
28 |
29 | eclipse-maven-repo
30 | Eclipse Maven
31 | https://mvnrepository.com
32 |
33 |
34 |
35 |
36 |
37 |
38 | pentaho-kettle
39 | kettle-ui-swt
40 | ${pentaho-kettle.version}
41 |
42 |
43 | pentaho-kettle
44 | kettle-engine
45 | ${pentaho-kettle.version}
46 |
47 |
48 | junit
49 | junit
50 | ${junit.version}
51 | test
52 |
53 |
54 |
55 |
56 |
57 |
58 | install
59 |
60 |
61 |
62 | src/main/java
63 |
64 | **/*.properties
65 | **/*.xul
66 | **/*.svg
67 |
68 |
69 |
70 |
71 |
72 |
73 | maven-dependency-plugin
74 |
75 |
76 | install
77 |
78 | copy-dependencies
79 |
80 |
81 | ${project.build.directory}/lib
82 | provided
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | pentaho-kettle
95 | kettle-ui-swt
96 | ${pentaho-kettle.version}
97 |
98 |
99 | pentaho-kettle
100 | kettle-engine
101 | ${pentaho-kettle.version}
102 |
103 |
104 | junit
105 | junit
106 | ${junit.version}
107 | test
108 |
109 |
110 |
111 |
112 |
113 |
114 | kettle-debug-plugin
115 | 1.6.0-SNAPSHOT
116 |
117 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/util/ZoomLevel.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp.util;
2 |
3 | import org.apache.commons.lang.StringUtils;
4 | import org.eclipse.swt.SWT;
5 | import org.eclipse.swt.widgets.Combo;
6 | import org.eclipse.swt.widgets.Control;
7 | import org.eclipse.swt.widgets.Event;
8 | import org.eclipse.swt.widgets.Listener;
9 | import org.eclipse.swt.widgets.ToolBar;
10 | import org.eclipse.swt.widgets.ToolItem;
11 | import org.pentaho.di.core.Const;
12 | import org.pentaho.di.ui.core.PropsUI;
13 | import org.pentaho.di.ui.spoon.AbstractGraph;
14 | import org.pentaho.di.ui.spoon.Spoon;
15 | import org.pentaho.di.ui.spoon.job.JobGraph;
16 | import org.pentaho.di.ui.spoon.trans.TransGraph;
17 |
18 | public class ZoomLevel {
19 |
20 | public static final String PROPERTY_LAST_TRANS_MAGNIFICATION = "LastTransMagnification";
21 | public static final String PROPERTY_LAST_JOB_MAGNIFICATION = "LastJobMagnification";
22 |
23 | private static ZoomLevel zoomLevel;
24 |
25 | private float lastTransMagnification;
26 | private float lastJobMagnification;
27 |
28 | private ZoomLevel() {
29 | lastTransMagnification = (float) Const.toDouble( PropsUI.getInstance().getProperty( PROPERTY_LAST_TRANS_MAGNIFICATION ), 1.0f );
30 | lastJobMagnification = (float) Const.toDouble( PropsUI.getInstance().getProperty( PROPERTY_LAST_JOB_MAGNIFICATION ), 1.0f );
31 | }
32 |
33 | public static ZoomLevel getInstance() {
34 | if ( zoomLevel == null ) {
35 | zoomLevel = new ZoomLevel();
36 | }
37 |
38 | return zoomLevel;
39 | }
40 |
41 | public void saveProperties() {
42 | PropsUI.getInstance().setProperty( PROPERTY_LAST_TRANS_MAGNIFICATION, Float.toString( lastTransMagnification ) );
43 | PropsUI.getInstance().setProperty( PROPERTY_LAST_JOB_MAGNIFICATION, Float.toString( lastJobMagnification ) );
44 | }
45 |
46 | private static Listener zoomListener = event -> {
47 | // get the trans zoom level whenever it's changed actively anywhere by the user...
48 | //
49 | Combo combo = (Combo) event.widget;
50 | String oldZoom = combo.getText();
51 | String newZoom = oldZoom.substring( 0, event.start ) + event.text + oldZoom.substring( event.end );
52 |
53 | if ( StringUtils.isEmpty( oldZoom ) || StringUtils.isEmpty( newZoom ) ) {
54 | // Initial set, not worth remembering the incorrect value of 100% (sigh)
55 | //
56 | return;
57 | }
58 |
59 | String zoomText = newZoom.replace( "%", "" );
60 | double magnification = Const.toDouble( zoomText, 100.0D ) / 100;
61 | ZoomLevel.getInstance().setLastTransMagnification( (float) magnification );
62 | };
63 |
64 | public static final void changeTransGraphZoomLevel() {
65 | Spoon spoon = Spoon.getInstance();
66 | if ( spoon == null ) {
67 | // Not running in spoon, don't care about zoom level...
68 | //
69 | return;
70 | }
71 |
72 | ZoomLevel.getInstance().saveProperties();
73 |
74 | float magnification = ZoomLevel.getInstance().getLastTransMagnification();
75 |
76 | correctActiveGraphZoomLevel(spoon.getActiveTransGraph(), magnification);
77 | }
78 |
79 | private static void correctActiveGraphZoomLevel( AbstractGraph graph, float magnification ) {
80 | if ( graph == null ) {
81 | // Nothing to see here, move along!
82 | //
83 | return;
84 | }
85 |
86 | // Find the toolbar, try to set the zoom level based on the last transformation magnification...
87 | //
88 | for ( Control control : graph.getChildren() ) {
89 | if ( control instanceof ToolBar ) {
90 | ToolBar toolBar = (ToolBar) control;
91 | // This is the toolbar at the top of the transformation...
92 | // Find the Combo with the zoom level
93 | //
94 | for ( ToolItem toolItem : toolBar.getItems() ) {
95 | if ( toolItem.getControl() instanceof Combo ) {
96 | toolItem.setWidth( 150 );
97 |
98 | Combo zoomLevelCombo = (Combo) toolItem.getControl();
99 | if ( zoomLevelCombo.getItemCount() < 10 ) {
100 | zoomLevelCombo.add( " 400%", 0 );
101 | zoomLevelCombo.add( " 500%", 0 );
102 | zoomLevelCombo.add( " 750%", 0 );
103 | zoomLevelCombo.add( " 1000%", 0 );
104 | }
105 |
106 | zoomLevelCombo.setText( Integer.toString( Math.round( magnification * 100.0F ) ) + "%" );
107 |
108 | // Now update the magnification used in TransGraph
109 | //
110 | zoomLevelCombo.removeListener( SWT.Verify, zoomListener );
111 | zoomLevelCombo.notifyListeners( SWT.Selection, new Event() );
112 | zoomLevelCombo.addListener( SWT.Verify, zoomListener );
113 | return;
114 | }
115 | }
116 | }
117 | }
118 | }
119 |
120 |
121 | public static final void changeJobGraphZoomLevel() {
122 | Spoon spoon = Spoon.getInstance();
123 | if ( spoon == null ) {
124 | // Not running in spoon, don't care about zoom level...
125 | //
126 | return;
127 | }
128 |
129 | ZoomLevel.getInstance().saveProperties();
130 |
131 | float magnification = ZoomLevel.getInstance().getLastJobMagnification();
132 |
133 | correctActiveGraphZoomLevel( spoon.getActiveJobGraph(), magnification );
134 | }
135 |
136 |
137 | /**
138 | * Gets lastTransMagnification
139 | *
140 | * @return value of lastTransMagnification
141 | */
142 | public float getLastTransMagnification() {
143 | return lastTransMagnification;
144 | }
145 |
146 | /**
147 | * @param lastTransMagnification The lastTransMagnification to set
148 | */
149 | public void setLastTransMagnification( float lastTransMagnification ) {
150 | this.lastTransMagnification = lastTransMagnification;
151 | }
152 |
153 | /**
154 | * Gets lastJobMagnification
155 | *
156 | * @return value of lastJobMagnification
157 | */
158 | public float getLastJobMagnification() {
159 | return lastJobMagnification;
160 | }
161 |
162 | /**
163 | * @param lastJobMagnification The lastJobMagnification to set
164 | */
165 | public void setLastJobMagnification( float lastJobMagnification ) {
166 | this.lastJobMagnification = lastJobMagnification;
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/SetStepDebugLevelExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.kettle.StepDebugLevel;
4 | import org.kettle.util.DebugLevelUtil;
5 | import org.kettle.util.Defaults;
6 | import org.pentaho.di.core.Condition;
7 | import org.pentaho.di.core.exception.KettleException;
8 | import org.pentaho.di.core.exception.KettleStepException;
9 | import org.pentaho.di.core.extension.ExtensionPoint;
10 | import org.pentaho.di.core.extension.ExtensionPointInterface;
11 | import org.pentaho.di.core.logging.LogChannelInterface;
12 | import org.pentaho.di.core.logging.LogLevel;
13 | import org.pentaho.di.core.row.RowMetaInterface;
14 | import org.pentaho.di.trans.Trans;
15 | import org.pentaho.di.trans.step.BaseStep;
16 | import org.pentaho.di.trans.step.RowAdapter;
17 | import org.pentaho.di.trans.step.StepInterface;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.Map;
22 | import java.util.concurrent.atomic.AtomicLong;
23 |
24 | @ExtensionPoint(
25 | id = "SetStepDebugLevelExtensionPoint",
26 | description = "Set Step Debug Level Extension Point Plugin",
27 | extensionPointId = "TransformationStartThreads"
28 | )
29 | /**
30 | * set the debug level right before the step starts to run
31 | */
32 | public class SetStepDebugLevelExtensionPoint implements ExtensionPointInterface {
33 |
34 | @Override public void callExtensionPoint( LogChannelInterface logChannelInterface, Object o ) throws KettleException {
35 | if (!(o instanceof Trans )) {
36 | return;
37 | }
38 |
39 | Trans trans= (Trans) o;
40 |
41 | Map stepLevelMap = trans.getTransMeta().getAttributesMap().get( Defaults.DEBUG_GROUP );
42 |
43 | if (stepLevelMap!=null) {
44 |
45 | logChannelInterface.logDetailed( "Set debug level information on transformation : " + trans.getTransMeta().getName() );
46 |
47 | List stepnames = new ArrayList<>( );
48 | for ( String key : stepLevelMap.keySet() ) {
49 |
50 | int index = key.indexOf( " : " );
51 | if ( index > 0 ) {
52 | String stepname = key.substring( 0, index );
53 | if ( !stepnames.contains( stepname ) ) {
54 | stepnames.add( stepname );
55 | }
56 | }
57 | }
58 |
59 | for ( String stepname : stepnames ) {
60 |
61 | logChannelInterface.logDetailed( "Handling debug level for step : "+stepname );
62 |
63 | try {
64 |
65 | final StepDebugLevel debugLevel = DebugLevelUtil.getStepDebugLevel( stepLevelMap, stepname );
66 | if ( debugLevel != null ) {
67 |
68 | logChannelInterface.logDetailed("Found debug level info for step "+stepname);
69 |
70 | List baseSteps = trans.findBaseSteps( stepname );
71 |
72 | if (debugLevel.getStartRow()<0 && debugLevel.getEndRow()<0 && debugLevel.getCondition().isEmpty()) {
73 |
74 | logChannelInterface.logDetailed("Set logging level for step "+stepname+" to "+debugLevel.getLogLevel().getDescription());
75 |
76 | // Just a general log level on the step
77 | //
78 | String logLevelCode = stepLevelMap.get( stepname );
79 | for ( StepInterface stepInterface : baseSteps ) {
80 | if ( stepInterface instanceof BaseStep ) {
81 | BaseStep baseStep = (BaseStep) stepInterface;
82 | LogLevel logLevel = debugLevel.getLogLevel();
83 | baseStep.setLogLevel( logLevel );
84 | logChannelInterface.logDetailed( "SET LOGGING LEVEL " + logLevel.getDescription() + " ON STEP COPY " + baseStep.getStepname() + "." + baseStep.getCopy() );
85 | }
86 | }
87 | } else {
88 |
89 | // We need to look at every row
90 | //
91 | for ( StepInterface stepInterface : baseSteps ) {
92 |
93 | final LogLevel baseLogLevel = stepInterface.getLogChannel().getLogLevel();
94 | final AtomicLong rowCounter = new AtomicLong( 0L );
95 |
96 | stepInterface.addRowListener( new RowAdapter() {
97 |
98 | @Override public void rowReadEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
99 |
100 | rowCounter.incrementAndGet();
101 | boolean enabled = false;
102 |
103 | Condition condition = debugLevel.getCondition();
104 |
105 | if (debugLevel.getStartRow()>0 && rowCounter.get()>=debugLevel.getStartRow() && debugLevel.getEndRow()>=0 && debugLevel.getEndRow()>=rowCounter.get()) {
106 | // If we have a start and an end, we want to stay between start and end
107 | enabled = true;
108 | } else if (debugLevel.getStartRow()<=0 && debugLevel.getEndRow()>=0 && rowCounter.get()<=debugLevel.getEndRow()) {
109 | // If don't have a start row, just and end...
110 | enabled = true;
111 | } else if (debugLevel.getEndRow()<=0 && debugLevel.getStartRow()>=0 && rowCounter.get()>=debugLevel.getStartRow()) {
112 | enabled = true;
113 | }
114 |
115 | if ( (debugLevel.getStartRow()<=0 && debugLevel.getEndRow()<=0 || enabled) && !condition.isEmpty()) {
116 | enabled = condition.evaluate( rowMeta, row );
117 | }
118 |
119 | if (enabled) {
120 | stepInterface.getLogChannel().setLogLevel( debugLevel.getLogLevel() );
121 | }
122 | }
123 |
124 | @Override public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
125 |
126 | // Set the log level back to the original value.
127 | //
128 | stepInterface.getLogChannel().setLogLevel( baseLogLevel );
129 | }
130 | } );
131 |
132 | }
133 | }
134 | }
135 | } catch ( Exception e ) {
136 | logChannelInterface.logError( "Unable to handle specific debug level for step : " + stepname, e );
137 | }
138 | }
139 |
140 | }
141 |
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/util/DebugLevelUtil.java:
--------------------------------------------------------------------------------
1 | package org.kettle.util;
2 |
3 | import org.apache.commons.lang.StringUtils;
4 | import org.kettle.JobEntryDebugLevel;
5 | import org.kettle.StepDebugLevel;
6 | import org.pentaho.di.core.Condition;
7 | import org.pentaho.di.core.Const;
8 | import org.pentaho.di.core.exception.KettleValueException;
9 | import org.pentaho.di.core.exception.KettleXMLException;
10 | import org.pentaho.di.core.logging.LogLevel;
11 |
12 | import java.io.UnsupportedEncodingException;
13 | import java.util.Base64;
14 | import java.util.Map;
15 | import java.util.concurrent.TimeUnit;
16 |
17 | public class DebugLevelUtil {
18 |
19 | public static void storeStepDebugLevel( Map debugGroupAttributesMap, String stepName, StepDebugLevel debugLevel ) throws KettleValueException, UnsupportedEncodingException {
20 | debugGroupAttributesMap.put(stepName + " : " +Defaults.STEP_ATTR_LOGLEVEL, debugLevel.getLogLevel().getCode());
21 | debugGroupAttributesMap.put(stepName + " : " +Defaults.STEP_ATTR_START_ROW, Integer.toString(debugLevel.getStartRow()));
22 | debugGroupAttributesMap.put(stepName + " : " +Defaults.STEP_ATTR_END_ROW, Integer.toString(debugLevel.getEndRow()));
23 |
24 | String conditionXmlString = Base64.getEncoder().encodeToString( debugLevel.getCondition().getXML().getBytes( "UTF-8" ) );
25 | debugGroupAttributesMap.put(stepName + " : " +Defaults.STEP_ATTR_CONDITION, conditionXmlString);
26 | }
27 |
28 | public static StepDebugLevel getStepDebugLevel( Map debugGroupAttributesMap, String stepName ) throws UnsupportedEncodingException, KettleXMLException {
29 |
30 |
31 | String logLevelCode = debugGroupAttributesMap.get(stepName+ " : " + Defaults.STEP_ATTR_LOGLEVEL );
32 | String startRowString = debugGroupAttributesMap.get(stepName+ " : " + Defaults.STEP_ATTR_START_ROW );
33 | String endRowString = debugGroupAttributesMap.get(stepName+ " : " + Defaults.STEP_ATTR_END_ROW );
34 | String conditionString = debugGroupAttributesMap.get(stepName+ " : " + Defaults.STEP_ATTR_CONDITION );
35 |
36 | if ( StringUtils.isEmpty(logLevelCode)) {
37 | // Nothing to load
38 | //
39 | return null;
40 | }
41 |
42 | StepDebugLevel debugLevel = new StepDebugLevel();
43 | debugLevel.setLogLevel( LogLevel.getLogLevelForCode( logLevelCode ) );
44 | debugLevel.setStartRow( Const.toInt(startRowString, -1) );
45 | debugLevel.setEndRow( Const.toInt(endRowString, -1) );
46 |
47 | if (StringUtils.isNotEmpty( conditionString )) {
48 | String conditionXml = new String( Base64.getDecoder().decode( conditionString ), "UTF-8" );
49 | debugLevel.setCondition( new Condition( conditionXml ) );
50 | }
51 | return debugLevel;
52 | }
53 |
54 |
55 | public static void clearDebugLevel( Map debugGroupAttributesMap, String stepName) {
56 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.STEP_ATTR_LOGLEVEL );
57 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.STEP_ATTR_START_ROW );
58 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.STEP_ATTR_END_ROW );
59 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.STEP_ATTR_CONDITION );
60 |
61 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.JOBENTRY_ATTR_LOGLEVEL);
62 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.JOBENTRY_ATTR_LOG_RESULT);
63 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.JOBENTRY_ATTR_LOG_VARIABLES);
64 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.JOBENTRY_ATTR_LOG_RESULT_ROWS);
65 | debugGroupAttributesMap.remove(stepName+ " : " + Defaults.JOBENTRY_ATTR_LOG_RESULT_FILES);
66 | }
67 |
68 | public static void storeJobEntryDebugLevel( Map debugGroupAttributesMap, String entryName, JobEntryDebugLevel debugLevel ) throws KettleValueException, UnsupportedEncodingException {
69 | debugGroupAttributesMap.put(entryName + " : " +Defaults.JOBENTRY_ATTR_LOGLEVEL, debugLevel.getLogLevel().getCode());
70 | debugGroupAttributesMap.put(entryName + " : " +Defaults.JOBENTRY_ATTR_LOG_RESULT, debugLevel.isLoggingResult() ? "Y" : "N");
71 | debugGroupAttributesMap.put(entryName + " : " +Defaults.JOBENTRY_ATTR_LOG_VARIABLES, debugLevel.isLoggingVariables() ? "Y" : "N");
72 | debugGroupAttributesMap.put(entryName + " : " +Defaults.JOBENTRY_ATTR_LOG_RESULT_ROWS, debugLevel.isLoggingResultRows() ? "Y" : "N");
73 | debugGroupAttributesMap.put(entryName + " : " +Defaults.JOBENTRY_ATTR_LOG_RESULT_FILES, debugLevel.isLoggingResultFiles() ? "Y" : "N");
74 | }
75 |
76 | public static JobEntryDebugLevel getJobEntryDebugLevel( Map debugGroupAttributesMap, String entryName ) throws UnsupportedEncodingException, KettleXMLException {
77 |
78 | String logLevelCode = debugGroupAttributesMap.get(entryName+ " : " + Defaults.JOBENTRY_ATTR_LOGLEVEL);
79 | boolean loggingResult = "Y".equalsIgnoreCase( debugGroupAttributesMap.get(entryName+ " : " + Defaults.JOBENTRY_ATTR_LOG_RESULT) );
80 | boolean loggingVariables = "Y".equalsIgnoreCase( debugGroupAttributesMap.get(entryName+ " : " + Defaults.JOBENTRY_ATTR_LOG_VARIABLES) );
81 | boolean loggingResultRows = "Y".equalsIgnoreCase( debugGroupAttributesMap.get(entryName+ " : " + Defaults.JOBENTRY_ATTR_LOG_RESULT_ROWS) );
82 | boolean loggingResultFiles = "Y".equalsIgnoreCase( debugGroupAttributesMap.get(entryName+ " : " + Defaults.JOBENTRY_ATTR_LOG_RESULT_FILES) );
83 |
84 | if ( StringUtils.isEmpty(logLevelCode)) {
85 | // Nothing to load
86 | //
87 | return null;
88 | }
89 |
90 | JobEntryDebugLevel debugLevel = new JobEntryDebugLevel();
91 | debugLevel.setLogLevel( LogLevel.getLogLevelForCode( logLevelCode ) );
92 | debugLevel.setLoggingResult( loggingResult );
93 | debugLevel.setLoggingVariables( loggingVariables );
94 | debugLevel.setLoggingResultRows( loggingResultRows );
95 | debugLevel.setLoggingResultFiles( loggingResultFiles );
96 |
97 | return debugLevel;
98 | }
99 |
100 | public static String getDurationHMS(double seconds) {
101 | int day = (int) TimeUnit.SECONDS.toDays((long)seconds);
102 | long hours = TimeUnit.SECONDS.toHours((long)seconds) - (day *24);
103 | long minute = TimeUnit.SECONDS.toMinutes((long)seconds) - (TimeUnit.SECONDS.toHours((long)seconds)* 60);
104 | long second = TimeUnit.SECONDS.toSeconds((long)seconds) - (TimeUnit.SECONDS.toMinutes((long)seconds) *60);
105 | long ms = (long)((seconds - ((long)seconds))*1000);
106 |
107 | StringBuilder hms = new StringBuilder();
108 | if (day>0) {
109 | hms.append( day + "d " );
110 | }
111 | if (day>0 || hours>0) {
112 | hms.append(hours + "h ");
113 | }
114 | if (day>0 || hours>0 || minute>0) {
115 | hms.append(String.format( "%2d", minute ) + "' ");
116 | }
117 | hms.append(String.format( "%2d", second ) + ".");
118 | hms.append(String.format("%03d", ms)+"\"");
119 |
120 | return hms.toString();
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/DebugPluginsHelper.java:
--------------------------------------------------------------------------------
1 | /*! ******************************************************************************
2 | *
3 | * Pentaho Data Integration
4 | *
5 | * Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
6 | *
7 | *******************************************************************************
8 | *
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with
11 | * the License. You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | *
21 | ******************************************************************************/
22 |
23 | package org.kettle;
24 |
25 | import org.kettle.dialog.JobEntryDebugLevelDialog;
26 | import org.kettle.dialog.StepDebugLevelDialog;
27 | import org.kettle.util.DebugLevelUtil;
28 | import org.kettle.util.Defaults;
29 | import org.kettle.xp.util.ZoomLevel;
30 | import org.pentaho.di.core.gui.SpoonFactory;
31 | import org.pentaho.di.core.row.RowMeta;
32 | import org.pentaho.di.core.row.RowMetaInterface;
33 | import org.pentaho.di.job.JobMeta;
34 | import org.pentaho.di.job.entry.JobEntryCopy;
35 | import org.pentaho.di.trans.TransMeta;
36 | import org.pentaho.di.trans.step.StepMeta;
37 | import org.pentaho.di.ui.core.dialog.ErrorDialog;
38 | import org.pentaho.di.ui.spoon.ISpoonMenuController;
39 | import org.pentaho.di.ui.spoon.Spoon;
40 | import org.pentaho.di.ui.spoon.job.JobGraph;
41 | import org.pentaho.di.ui.spoon.trans.TransGraph;
42 | import org.pentaho.ui.xul.dom.Document;
43 | import org.pentaho.ui.xul.impl.AbstractXulEventHandler;
44 |
45 | import java.util.HashMap;
46 | import java.util.Map;
47 |
48 | public class DebugPluginsHelper extends AbstractXulEventHandler implements ISpoonMenuController {
49 | protected static Class> PKG = DebugPluginsHelper.class; // for i18n
50 |
51 | private static DebugPluginsHelper instance = null;
52 |
53 | private DebugPluginsHelper() {
54 | }
55 |
56 | public static DebugPluginsHelper getInstance() {
57 | if ( instance == null ) {
58 | instance = new DebugPluginsHelper();
59 | Spoon spoon = ( (Spoon) SpoonFactory.getInstance() );
60 | spoon.addSpoonMenuController( instance );
61 | }
62 | return instance;
63 | }
64 |
65 | public String getName() {
66 | return "debugHelper";
67 | }
68 |
69 | public void updateMenu( Document doc ) {
70 | // Nothing so far.
71 | }
72 |
73 | public void lastZoomLevel() {
74 |
75 | Spoon spoon = ( (Spoon) SpoonFactory.getInstance() );
76 | TransGraph transGraph = spoon.getActiveTransGraph();
77 | if (transGraph!=null) {
78 | ZoomLevel.changeTransGraphZoomLevel();
79 | }
80 | JobGraph jobGraph = spoon.getActiveJobGraph();
81 | if (jobGraph!=null) {
82 | ZoomLevel.changeJobGraphZoomLevel();
83 | }
84 | }
85 |
86 | public void setStepLoggingLevel() {
87 | setClearStepLogLevel(true);
88 | }
89 |
90 | public void clearStepLoggingLevel() {
91 | setClearStepLogLevel( false );
92 | }
93 |
94 | private void setClearStepLogLevel( boolean set) {
95 | Spoon spoon = ( (Spoon) SpoonFactory.getInstance() );
96 | try {
97 | TransGraph transGraph = spoon.getActiveTransGraph();
98 | TransMeta transMeta = spoon.getActiveTransformation();
99 | StepMeta stepMeta = transGraph.getCurrentStep();
100 | if ( transGraph == null || transMeta == null || stepMeta == null ) {
101 | return;
102 | }
103 |
104 | Map> attributesMap = transMeta.getAttributesMap();
105 | Map debugGroupAttributesMap = attributesMap.get( Defaults.DEBUG_GROUP );
106 |
107 | if ( debugGroupAttributesMap == null ) {
108 | debugGroupAttributesMap = new HashMap<>();
109 | attributesMap.put( Defaults.DEBUG_GROUP, debugGroupAttributesMap );
110 | }
111 |
112 | if ( !set ) {
113 | DebugLevelUtil.clearDebugLevel( debugGroupAttributesMap, stepMeta.getName());
114 | transMeta.setChanged();
115 | spoon.refreshGraph();
116 | return;
117 | }
118 |
119 | StepDebugLevel debugLevel = DebugLevelUtil.getStepDebugLevel( debugGroupAttributesMap, stepMeta.getName() );
120 | if ( debugLevel==null ) {
121 | debugLevel = new StepDebugLevel();
122 | }
123 |
124 | RowMetaInterface inputRowMeta = transMeta.getPrevStepFields( stepMeta );
125 | StepDebugLevelDialog dialog = new StepDebugLevelDialog( spoon.getShell(), debugLevel, inputRowMeta );
126 | if (dialog.open()) {
127 | DebugLevelUtil.storeStepDebugLevel(debugGroupAttributesMap, stepMeta.getName(), debugLevel);
128 | }
129 |
130 | transMeta.setChanged();
131 | spoon.refreshGraph();
132 | } catch(Exception e) {
133 | new ErrorDialog( spoon.getShell(), "Error", "Unexpected error", e );
134 | }
135 | }
136 |
137 |
138 | public void clearAllTransLogging() {
139 | Spoon spoon = ( (Spoon) SpoonFactory.getInstance() );
140 | TransGraph transGraph = spoon.getActiveTransGraph();
141 | TransMeta transMeta = spoon.getActiveTransformation();
142 | StepMeta stepMeta = transGraph.getCurrentStep();
143 | if ( transGraph == null || transMeta == null || stepMeta == null ) {
144 | return;
145 | }
146 | Map> attributesMap = transMeta.getAttributesMap();
147 | attributesMap.remove( Defaults.DEBUG_GROUP );
148 | transMeta.setChanged();
149 | spoon.refreshGraph();
150 | }
151 |
152 | public void setJobEntryLoggingLevel() {
153 | setClearJobEntryLogLevel(true);
154 | }
155 |
156 | public void clearJobEntryLoggingLevel() {
157 | setClearJobEntryLogLevel( false );
158 | }
159 |
160 | private void setClearJobEntryLogLevel( boolean set) {
161 | Spoon spoon = ( (Spoon) SpoonFactory.getInstance() );
162 | try {
163 | JobGraph jobGraph = spoon.getActiveJobGraph();
164 | JobMeta jobMeta = spoon.getActiveJob();
165 | JobEntryCopy jobEntryCopy = jobGraph.getJobEntry();
166 | if ( jobGraph == null || jobMeta == null || jobEntryCopy == null ) {
167 |
168 | return;
169 | }
170 |
171 | Map> attributesMap = jobMeta.getAttributesMap();
172 | Map debugGroupAttributesMap = attributesMap.get( Defaults.DEBUG_GROUP );
173 | if ( debugGroupAttributesMap == null ) {
174 | debugGroupAttributesMap = new HashMap<>();
175 | attributesMap.put( Defaults.DEBUG_GROUP, debugGroupAttributesMap );
176 | }
177 |
178 | if ( !set ) {
179 | DebugLevelUtil.clearDebugLevel( debugGroupAttributesMap, jobEntryCopy.toString());
180 | jobMeta.setChanged();
181 | spoon.refreshGraph();
182 | return;
183 | }
184 |
185 | JobEntryDebugLevel debugLevel = DebugLevelUtil.getJobEntryDebugLevel( debugGroupAttributesMap, jobEntryCopy.toString() );
186 | if ( debugLevel==null ) {
187 | debugLevel = new JobEntryDebugLevel();
188 | }
189 |
190 | JobEntryDebugLevelDialog dialog = new JobEntryDebugLevelDialog( spoon.getShell(), debugLevel);
191 | if (dialog.open()) {
192 | DebugLevelUtil.storeJobEntryDebugLevel(debugGroupAttributesMap, jobEntryCopy.toString(), debugLevel);
193 | }
194 |
195 | jobMeta.setChanged();
196 | spoon.refreshGraph();
197 | } catch(Exception e) {
198 | new ErrorDialog( spoon.getShell(), "Error", "Unexpected error", e );
199 | }
200 | }
201 |
202 | public void clearAllJobLogging() {
203 | Spoon spoon = ( (Spoon) SpoonFactory.getInstance() );
204 | JobGraph jobGraph = spoon.getActiveJobGraph();
205 | JobMeta jobMeta = spoon.getActiveJob();
206 | JobEntryCopy jobEntry = jobGraph.getJobEntry();
207 | if ( jobGraph == null || jobMeta == null || jobEntry == null ) {
208 | return;
209 | }
210 | Map> attributesMap = jobMeta.getAttributesMap();
211 | attributesMap.remove( Defaults.DEBUG_GROUP );
212 | jobMeta.setChanged();
213 | spoon.refreshGraph();
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/src/main/java/bee.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/dialog/StepDebugLevelDialog.java:
--------------------------------------------------------------------------------
1 | package org.kettle.dialog;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.events.SelectionAdapter;
5 | import org.eclipse.swt.events.SelectionEvent;
6 | import org.eclipse.swt.events.ShellAdapter;
7 | import org.eclipse.swt.events.ShellEvent;
8 | import org.eclipse.swt.layout.FormAttachment;
9 | import org.eclipse.swt.layout.FormData;
10 | import org.eclipse.swt.layout.FormLayout;
11 | import org.eclipse.swt.widgets.Button;
12 | import org.eclipse.swt.widgets.Combo;
13 | import org.eclipse.swt.widgets.Control;
14 | import org.eclipse.swt.widgets.Dialog;
15 | import org.eclipse.swt.widgets.Display;
16 | import org.eclipse.swt.widgets.Label;
17 | import org.eclipse.swt.widgets.Shell;
18 | import org.eclipse.swt.widgets.Text;
19 | import org.kettle.StepDebugLevel;
20 | import org.pentaho.di.core.Const;
21 | import org.pentaho.di.core.logging.LogLevel;
22 | import org.pentaho.di.core.row.RowMetaInterface;
23 | import org.pentaho.di.i18n.BaseMessages;
24 | import org.pentaho.di.ui.core.PropsUI;
25 | import org.pentaho.di.ui.core.gui.GUIResource;
26 | import org.pentaho.di.ui.core.gui.WindowProperty;
27 | import org.pentaho.di.ui.core.widget.ConditionEditor;
28 | import org.pentaho.di.ui.trans.step.BaseStepDialog;
29 |
30 | public class StepDebugLevelDialog extends Dialog {
31 | private static Class> PKG = StepDebugLevelDialog.class; // for i18n purposes, needed by Translator2!!
32 |
33 | private StepDebugLevel input;
34 | private StepDebugLevel debugLevel;
35 | private RowMetaInterface inputRowMeta;
36 |
37 | private Shell shell;
38 |
39 | // Connection properties
40 | //
41 | private Combo wLogLevel;
42 | private Text wStartRow;
43 | private Text wEndRow;
44 | private ConditionEditor wCondition;
45 |
46 | private Control lastControl;
47 |
48 | private PropsUI props;
49 |
50 | private int middle;
51 | private int margin;
52 |
53 | private boolean ok;
54 |
55 | public StepDebugLevelDialog( Shell par, StepDebugLevel debugLevel, RowMetaInterface inputRowMeta) {
56 | super( par, SWT.NONE );
57 | this.input = debugLevel;
58 | this.inputRowMeta = inputRowMeta;
59 | props = PropsUI.getInstance();
60 | ok = false;
61 |
62 | this.debugLevel = input.clone();
63 |
64 | }
65 |
66 | public boolean open() {
67 | Shell parent = getParent();
68 | shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN );
69 | props.setLook( shell );
70 | shell.setImage( GUIResource.getInstance().getImageSlave() );
71 |
72 | middle = props.getMiddlePct();
73 | margin = Const.MARGIN + 2;
74 |
75 | FormLayout formLayout = new FormLayout();
76 | formLayout.marginWidth = Const.FORM_MARGIN;
77 | formLayout.marginHeight = Const.FORM_MARGIN;
78 |
79 | shell.setText( "Step debug Level" );
80 | shell.setLayout( formLayout );
81 |
82 | // The name
83 | Label wlName = new Label( shell, SWT.RIGHT );
84 | props.setLook( wlName );
85 | wlName.setText( "Log level to set " );
86 | FormData fdlName = new FormData();
87 | fdlName.top = new FormAttachment( 0, margin );
88 | fdlName.left = new FormAttachment( 0, 0 ); // First one in the left top corner
89 | fdlName.right = new FormAttachment( middle, -margin );
90 | wlName.setLayoutData( fdlName );
91 | wLogLevel = new Combo( shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
92 | wLogLevel.setItems( LogLevel.getLogLevelDescriptions());
93 | props.setLook( wLogLevel );
94 | FormData fdName = new FormData();
95 | fdName.top = new FormAttachment( wlName, 0, SWT.CENTER );
96 | fdName.left = new FormAttachment( middle, 0 ); // To the right of the label
97 | fdName.right = new FormAttachment( 100, 0 );
98 | wLogLevel.setLayoutData( fdName );
99 | lastControl = wLogLevel;
100 |
101 | // Start row option
102 | Label wlStartRow = new Label( shell, SWT.RIGHT );
103 | props.setLook( wlStartRow );
104 | wlStartRow.setText( "Start row ");
105 | FormData fdlStartRow = new FormData();
106 | fdlStartRow.top = new FormAttachment( lastControl, margin );
107 | fdlStartRow.left = new FormAttachment( 0, 0 ); // First one in the left top corner
108 | fdlStartRow.right = new FormAttachment( middle, -margin );
109 | wlStartRow.setLayoutData( fdlStartRow );
110 | wStartRow = new Text( shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
111 | props.setLook( wStartRow );
112 | FormData fdStartRow = new FormData();
113 | fdStartRow.top = new FormAttachment( wlStartRow, 0, SWT.CENTER );
114 | fdStartRow.left = new FormAttachment( middle, 0 ); // To the right of the label
115 | fdStartRow.right = new FormAttachment( 100, 0 );
116 | wStartRow.setLayoutData( fdStartRow );
117 | lastControl = wStartRow;
118 |
119 | // End row
120 | Label wlEndRow = new Label( shell, SWT.RIGHT );
121 | props.setLook( wlEndRow );
122 | wlEndRow.setText( "End row " );
123 | FormData fdlEndRow = new FormData();
124 | fdlEndRow.top = new FormAttachment( lastControl, margin );
125 | fdlEndRow.left = new FormAttachment( 0, 0 ); // First one in the left top corner
126 | fdlEndRow.right = new FormAttachment( middle, -margin );
127 | wlEndRow.setLayoutData( fdlEndRow );
128 | wEndRow = new Text( shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
129 | props.setLook( wEndRow );
130 | FormData fdEndRow = new FormData();
131 | fdEndRow.top = new FormAttachment( wlEndRow, 0, SWT.CENTER );
132 | fdEndRow.left = new FormAttachment( middle, 0 ); // To the right of the label
133 | fdEndRow.right = new FormAttachment( 100, 0 );
134 | wEndRow.setLayoutData( fdEndRow );
135 | lastControl = wEndRow;
136 |
137 | // Buttons
138 | Button wOK = new Button( shell, SWT.PUSH );
139 | wOK.setText( BaseMessages.getString( PKG, "System.Button.OK" ) );
140 | wOK.addListener( SWT.Selection, e -> ok() );
141 |
142 | Button wCancel = new Button( shell, SWT.PUSH );
143 | wCancel.setText( BaseMessages.getString( PKG, "System.Button.Cancel" ) );
144 | wCancel.addListener( SWT.Selection, e -> cancel() );
145 |
146 | Button[] buttons = new Button[] { wOK, wCancel };
147 | BaseStepDialog.positionBottomButtons( shell, buttons, margin, null );
148 |
149 | SelectionAdapter selAdapter = new SelectionAdapter() {
150 | public void widgetDefaultSelected( SelectionEvent e ) {
151 | ok();
152 | }
153 | };
154 |
155 | wLogLevel.addSelectionListener( selAdapter );
156 | wStartRow.addSelectionListener( selAdapter );
157 | wEndRow.addSelectionListener( selAdapter );
158 |
159 | // Condition
160 | Label wlCondition = new Label( shell, SWT.RIGHT);
161 | wlCondition.setText( "Condition : " );
162 | props.setLook( wlCondition );
163 | FormData fdlCondition = new FormData();
164 | fdlCondition.top = new FormAttachment( lastControl, margin );
165 | fdlCondition.left = new FormAttachment( 0, 0 );
166 | fdlCondition.right = new FormAttachment( middle, -margin );
167 | wlCondition.setLayoutData( fdlCondition );
168 | wCondition = new ConditionEditor( shell, SWT.NONE, debugLevel.getCondition(), inputRowMeta);
169 | props.setLook( wCondition );
170 | FormData fdCondition = new FormData();
171 | fdCondition.top = new FormAttachment( lastControl, margin );
172 | fdCondition.left = new FormAttachment( middle, 0 );
173 | fdCondition.right = new FormAttachment( 100, 0 );
174 | fdCondition.bottom= new FormAttachment( wOK, 0 );
175 | wCondition.setLayoutData( fdCondition );
176 | lastControl = wCondition;
177 |
178 | // Detect X or ALT-F4 or something that kills this window...
179 | shell.addShellListener( new ShellAdapter() {
180 | public void shellClosed( ShellEvent e ) {
181 | cancel();
182 | }
183 | } );
184 |
185 | getData();
186 |
187 | BaseStepDialog.setSize( shell );
188 |
189 | shell.open();
190 | Display display = parent.getDisplay();
191 | while ( !shell.isDisposed() ) {
192 | if ( !display.readAndDispatch() ) {
193 | display.sleep();
194 | }
195 | }
196 | return ok;
197 | }
198 |
199 | public void dispose() {
200 | props.setScreen( new WindowProperty( shell ) );
201 | shell.dispose();
202 | }
203 |
204 | public void getData() {
205 | wLogLevel.setText( debugLevel.getLogLevel().getDescription() );
206 | wStartRow.setText( debugLevel.getStartRow() < 0 ? "" : Integer.toString( debugLevel.getStartRow() ) );
207 | wEndRow.setText( debugLevel.getEndRow() < 0 ? "" : Integer.toString( debugLevel.getEndRow() ) );
208 |
209 | wLogLevel.setFocus();
210 | }
211 |
212 | private void cancel() {
213 | ok = false;
214 | dispose();
215 | }
216 |
217 | public void ok() {
218 | getInfo( input );
219 | ok = true;
220 | dispose();
221 | }
222 |
223 | // Get dialog info in securityService
224 | private void getInfo( StepDebugLevel level ) {
225 | int index = Const.indexOfString( wLogLevel.getText(), LogLevel.getLogLevelDescriptions() );
226 | level.setLogLevel( LogLevel.values()[index] );
227 | level.setStartRow( Const.toInt( wStartRow.getText(), -1) );
228 | level.setEndRow( Const.toInt( wEndRow.getText(), -1) );
229 | level.setCondition( debugLevel.getCondition() );
230 | }
231 |
232 | }
233 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/xp/ModifyJobEntryLogLevelExtensionPoint.java:
--------------------------------------------------------------------------------
1 | package org.kettle.xp;
2 |
3 | import org.kettle.JobEntryDebugLevel;
4 | import org.kettle.util.DebugLevelUtil;
5 | import org.kettle.util.Defaults;
6 | import org.pentaho.di.core.Result;
7 | import org.pentaho.di.core.ResultFile;
8 | import org.pentaho.di.core.RowMetaAndData;
9 | import org.pentaho.di.core.exception.KettleException;
10 | import org.pentaho.di.core.extension.ExtensionPoint;
11 | import org.pentaho.di.core.extension.ExtensionPointInterface;
12 | import org.pentaho.di.core.logging.LogChannelInterface;
13 | import org.pentaho.di.core.logging.LogLevel;
14 | import org.pentaho.di.core.logging.LoggingObjectInterface;
15 | import org.pentaho.di.core.variables.VariableSpace;
16 | import org.pentaho.di.core.variables.Variables;
17 | import org.pentaho.di.job.Job;
18 | import org.pentaho.di.job.JobEntryListener;
19 | import org.pentaho.di.job.JobExecutionExtension;
20 | import org.pentaho.di.job.JobMeta;
21 | import org.pentaho.di.job.entry.JobEntryCopy;
22 | import org.pentaho.di.job.entry.JobEntryInterface;
23 | import org.pentaho.di.trans.Trans;
24 |
25 | import java.util.HashSet;
26 | import java.util.Map;
27 | import java.util.Set;
28 |
29 | @ExtensionPoint(
30 | id = "ModifyJobEntryLogLevelExtensionPoint",
31 | extensionPointId = "JobStart",
32 | description = "Modify the logging level of an individual job entry if needed" )
33 | public class ModifyJobEntryLogLevelExtensionPoint implements ExtensionPointInterface {
34 |
35 | public static final String STRING_REFERENCE_VARIABLE_SPACE = "REFERENCE_VARIABLE_SPACE";
36 |
37 |
38 | @Override public void callExtensionPoint( LogChannelInterface jobLog, Object object ) throws KettleException {
39 |
40 | if ( !( object instanceof Job ) ) {
41 | return;
42 | }
43 |
44 | Job job = (Job) object;
45 |
46 | Job rootJob = job;
47 | Trans rootTrans = null;
48 | while (rootJob!=null || rootTrans!=null) {
49 |
50 | if (rootJob!=null) {
51 | if (rootJob.getParentJob()==null && rootJob.getParentTrans()==null) {
52 | break;
53 | }
54 | rootJob = rootJob.getParentJob();
55 | rootTrans = rootJob.getParentTrans();
56 | } else {
57 | if (rootTrans.getParentJob()==null && rootTrans.getParentTrans()==null) {
58 | break;
59 | }
60 | rootJob = rootTrans.getParentJob();
61 | rootTrans = rootTrans.getParentTrans();
62 | }
63 | }
64 | Map rootDataMap;
65 | if (rootJob!=null) {
66 | rootDataMap = rootJob.getExtensionDataMap();
67 | } else {
68 | rootDataMap = rootTrans.getExtensionDataMap();
69 | }
70 |
71 | // Look for a reference variable space in the root job.
72 | // If non exists, add it. Only do this at the start of the root job, afterwards, never again.
73 | //
74 | final VariableSpace referenceSpace;
75 | synchronized ( rootDataMap ) {
76 | VariableSpace space = (VariableSpace) rootDataMap.get( STRING_REFERENCE_VARIABLE_SPACE );
77 | if (space==null) {
78 | space = new Variables();
79 | space.initializeVariablesFrom( job.getJobMeta() );
80 | rootDataMap.put(STRING_REFERENCE_VARIABLE_SPACE, space);
81 | }
82 | referenceSpace = space;
83 | }
84 |
85 | // Find the debug info in the job metadata
86 | //
87 | JobMeta jobMeta = job.getJobMeta();
88 |
89 | Map entryLevelMap = jobMeta.getAttributesMap().get( Defaults.DEBUG_GROUP );
90 | if ( entryLevelMap == null ) {
91 | return;
92 | }
93 |
94 | jobLog.logDetailed( "Set debug level information on job : " + jobMeta.getName() );
95 |
96 | final Set entries = new HashSet<>();
97 | for ( String key : entryLevelMap.keySet() ) {
98 |
99 | int index = key.indexOf( " : " );
100 | if ( index > 0 ) {
101 | String entryName = key.substring( 0, index );
102 | if ( !entries.contains( entryName ) ) {
103 | entries.add( entryName );
104 | }
105 | }
106 | }
107 |
108 | if ( entries.isEmpty() ) {
109 | return;
110 | }
111 |
112 | try {
113 |
114 | final LogLevel jobLogLevel = job.getLogLevel();
115 | final Set variablesToIgnore = Defaults.VARIABLES_TO_IGNORE;
116 |
117 | jobLog.logDetailed( "Found debug level info for job entries : " + entries.toString() );
118 |
119 | job.addJobEntryListener( new JobEntryListener() {
120 | @Override public void beforeExecution( Job job, JobEntryCopy jobEntryCopy, JobEntryInterface jobEntryInterface ) {
121 |
122 | LogChannelInterface log = jobEntryInterface.getLogChannel();
123 |
124 | try {
125 | // Is this a job entry with debugging set on it?
126 | //
127 | if ( entries.contains( jobEntryCopy.toString() ) ) {
128 | final JobEntryDebugLevel debugLevel = DebugLevelUtil.getJobEntryDebugLevel( entryLevelMap, jobEntryCopy.toString() );
129 | if ( debugLevel != null ) {
130 | // Set the debug level for this one...
131 | //
132 | log.setLogLevel( debugLevel.getLogLevel() );
133 | job.setLogLevel( debugLevel.getLogLevel() );
134 | }
135 | }
136 | } catch ( Exception e ) {
137 | log.logError( "Error setting logging level on entry" );
138 | }
139 | }
140 |
141 | @Override public void afterExecution( Job job, JobEntryCopy jobEntryCopy, JobEntryInterface jobEntryInterface, Result result ) {
142 | LogChannelInterface log = jobEntryInterface.getLogChannel();
143 |
144 | try {
145 | // Is this a job entry with debugging set on it?
146 | //
147 | if ( entries.contains( jobEntryCopy.toString() ) ) {
148 | final JobEntryDebugLevel debugLevel = DebugLevelUtil.getJobEntryDebugLevel( entryLevelMap, jobEntryCopy.toString() );
149 | if ( debugLevel != null ) {
150 | // Set the debug level for this one...
151 | //
152 | log.setLogLevel( jobLogLevel );
153 | job.setLogLevel( jobLogLevel );
154 |
155 | // Set the debug level back to normal...
156 | //
157 |
158 | if ( debugLevel.isLoggingResult() ) {
159 | log.logMinimal( "JOB ENTRY RESULT: " );
160 | log.logMinimal( " - result=" + result.getResult() );
161 | log.logMinimal( " - stopped=" + result.isStopped() );
162 | log.logMinimal( " - linesRead=" + result.getNrLinesRead() );
163 | log.logMinimal( " - linesWritten=" + result.getNrLinesWritten() );
164 | log.logMinimal( " - linesInput=" + result.getNrLinesInput() );
165 | log.logMinimal( " - linesOutput=" + result.getNrLinesOutput() );
166 | log.logMinimal( " - linesRejected=" + result.getNrLinesRejected() );
167 | log.logMinimal( " - result row count=" + result.getRows().size() );
168 | log.logMinimal( " - result files count=" + result.getResultFilesList().size() );
169 | }
170 | if ( debugLevel.isLoggingResultRows() ) {
171 | log.logMinimal( "JOB ENTRY RESULT ROWS: " );
172 | for ( RowMetaAndData rmad : result.getRows() ) {
173 | log.logMinimal( " - " + rmad.toString() );
174 | }
175 | }
176 | if ( debugLevel.isLoggingResultFiles() ) {
177 | log.logMinimal( "JOB ENTRY RESULT FILES: " );
178 | for ( ResultFile resultFile : result.getResultFilesList() ) {
179 | log.logMinimal( " - " + resultFile.getFile().toString() + " from " + resultFile.getOrigin() + " : " + resultFile.getComment() + " / " + resultFile.getTypeCode() );
180 | }
181 | }
182 | if ( debugLevel.isLoggingVariables() ) {
183 | if ( jobEntryInterface instanceof VariableSpace ) {
184 | log.logMinimal( "JOB ENTRY NOTEABLE VARIABLES: " );
185 |
186 | VariableSpace space = (VariableSpace) jobEntryInterface;
187 | // See the variables set differently from the parent job
188 | for ( String var : space.listVariables() ) {
189 | if ( !variablesToIgnore.contains( var ) ) {
190 | String value = space.getVariable( var );
191 | String refValue = referenceSpace.getVariable( var );
192 |
193 | if ( refValue == null || !refValue.equals( value ) ) {
194 | // Something different!
195 | //
196 | log.logMinimal( " - " + var + "=" + value );
197 | }
198 | }
199 | }
200 | }
201 | }
202 | }
203 | }
204 | } catch ( Exception e ) {
205 | log.logError( "Error re-setting logging level on entry" );
206 | }
207 | }
208 | } );
209 | } catch ( Exception e ) {
210 | jobLog.logError( "Unable to handle specific debug level for job", e );
211 | }
212 | }
213 | }
214 |
215 |
--------------------------------------------------------------------------------
/src/main/java/org/kettle/dialog/JobEntryDebugLevelDialog.java:
--------------------------------------------------------------------------------
1 | package org.kettle.dialog;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.events.SelectionAdapter;
5 | import org.eclipse.swt.events.SelectionEvent;
6 | import org.eclipse.swt.events.ShellAdapter;
7 | import org.eclipse.swt.events.ShellEvent;
8 | import org.eclipse.swt.layout.FormAttachment;
9 | import org.eclipse.swt.layout.FormData;
10 | import org.eclipse.swt.layout.FormLayout;
11 | import org.eclipse.swt.widgets.Button;
12 | import org.eclipse.swt.widgets.Combo;
13 | import org.eclipse.swt.widgets.Control;
14 | import org.eclipse.swt.widgets.Dialog;
15 | import org.eclipse.swt.widgets.Display;
16 | import org.eclipse.swt.widgets.Label;
17 | import org.eclipse.swt.widgets.Shell;
18 | import org.kettle.JobEntryDebugLevel;
19 | import org.pentaho.di.core.Const;
20 | import org.pentaho.di.core.logging.LogLevel;
21 | import org.pentaho.di.i18n.BaseMessages;
22 | import org.pentaho.di.ui.core.PropsUI;
23 | import org.pentaho.di.ui.core.gui.GUIResource;
24 | import org.pentaho.di.ui.core.gui.WindowProperty;
25 | import org.pentaho.di.ui.trans.step.BaseStepDialog;
26 |
27 | public class JobEntryDebugLevelDialog extends Dialog {
28 | private static Class> PKG = JobEntryDebugLevelDialog.class; // for i18n purposes, needed by Translator2!!
29 |
30 | private JobEntryDebugLevel input;
31 | private JobEntryDebugLevel debugLevel;
32 |
33 | private Shell shell;
34 |
35 | // Connection properties
36 | //
37 | private Combo wLogLevel;
38 | private Button wLoggingResult;
39 | private Button wLoggingVariables;
40 | private Button wLoggingRows;
41 | private Button wLoggingFiles;
42 |
43 | private Control lastControl;
44 |
45 | private PropsUI props;
46 |
47 | private int middle;
48 | private int margin;
49 |
50 | private boolean ok;
51 |
52 | public JobEntryDebugLevelDialog( Shell par, JobEntryDebugLevel debugLevel) {
53 | super( par, SWT.NONE );
54 | this.input = debugLevel;
55 | props = PropsUI.getInstance();
56 | ok = false;
57 |
58 | this.debugLevel = input.clone();
59 | }
60 |
61 | public boolean open() {
62 | Shell parent = getParent();
63 | shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN );
64 | props.setLook( shell );
65 | shell.setImage( GUIResource.getInstance().getImageSlave() );
66 |
67 | middle = props.getMiddlePct();
68 | margin = Const.MARGIN + 2;
69 |
70 | FormLayout formLayout = new FormLayout();
71 | formLayout.marginWidth = Const.FORM_MARGIN;
72 | formLayout.marginHeight = Const.FORM_MARGIN;
73 |
74 | shell.setText( "Job entry debug Level" );
75 | shell.setLayout( formLayout );
76 |
77 | // The name
78 | Label wlName = new Label( shell, SWT.RIGHT );
79 | props.setLook( wlName );
80 | wlName.setText( "Log level " );
81 | FormData fdlName = new FormData();
82 | fdlName.top = new FormAttachment( 0, margin );
83 | fdlName.left = new FormAttachment( 0, 0 ); // First one in the left top corner
84 | fdlName.right = new FormAttachment( middle, -margin );
85 | wlName.setLayoutData( fdlName );
86 | wLogLevel = new Combo( shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
87 | wLogLevel.setItems( LogLevel.getLogLevelDescriptions());
88 | props.setLook( wLogLevel );
89 | FormData fdName = new FormData();
90 | fdName.top = new FormAttachment( wlName, 0, SWT.CENTER );
91 | fdName.left = new FormAttachment( middle, 0 ); // To the right of the label
92 | fdName.right = new FormAttachment( 100, 0 );
93 | wLogLevel.setLayoutData( fdName );
94 | lastControl = wLogLevel;
95 |
96 | // Log result details?
97 | Label wlLoggingResult = new Label( shell, SWT.RIGHT );
98 | props.setLook( wlLoggingResult );
99 | wlLoggingResult.setText( "Log result?");
100 | FormData fdlLoggingResult = new FormData();
101 | fdlLoggingResult.top = new FormAttachment( lastControl, margin );
102 | fdlLoggingResult.left = new FormAttachment( 0, 0 ); // First one in the left top corner
103 | fdlLoggingResult.right = new FormAttachment( middle, -margin );
104 | wlLoggingResult.setLayoutData( fdlLoggingResult );
105 | wLoggingResult = new Button( shell, SWT.CHECK | SWT.LEFT );
106 | props.setLook( wLoggingResult );
107 | FormData fdLoggingResult = new FormData();
108 | fdLoggingResult.top = new FormAttachment( wlLoggingResult, 0, SWT.CENTER );
109 | fdLoggingResult.left = new FormAttachment( middle, 0 ); // To the right of the label
110 | fdLoggingResult.right = new FormAttachment( 100, 0 );
111 | wLoggingResult.setLayoutData( fdLoggingResult );
112 | lastControl = wLoggingResult;
113 |
114 | // Log result details?
115 | Label wlLoggingVariables = new Label( shell, SWT.RIGHT );
116 | props.setLook( wlLoggingVariables );
117 | wlLoggingVariables.setText( "Log variables?");
118 | FormData fdlLoggingVariables = new FormData();
119 | fdlLoggingVariables.top = new FormAttachment( lastControl, margin );
120 | fdlLoggingVariables.left = new FormAttachment( 0, 0 ); // First one in the left top corner
121 | fdlLoggingVariables.right = new FormAttachment( middle, -margin );
122 | wlLoggingVariables.setLayoutData( fdlLoggingVariables );
123 | wLoggingVariables = new Button( shell, SWT.CHECK | SWT.LEFT );
124 | props.setLook( wLoggingVariables );
125 | FormData fdLoggingVariables = new FormData();
126 | fdLoggingVariables.top = new FormAttachment( wlLoggingVariables, 0, SWT.CENTER );
127 | fdLoggingVariables.left = new FormAttachment( middle, 0 ); // To the right of the label
128 | fdLoggingVariables.right = new FormAttachment( 100, 0 );
129 | wLoggingVariables.setLayoutData( fdLoggingVariables );
130 | lastControl = wLoggingVariables;
131 |
132 | // Log result details?
133 | Label wlLoggingRows = new Label( shell, SWT.RIGHT );
134 | props.setLook( wlLoggingRows );
135 | wlLoggingRows.setText( "Log result rows?");
136 | FormData fdlLoggingRows = new FormData();
137 | fdlLoggingRows.top = new FormAttachment( lastControl, margin );
138 | fdlLoggingRows.left = new FormAttachment( 0, 0 ); // First one in the left top corner
139 | fdlLoggingRows.right = new FormAttachment( middle, -margin );
140 | wlLoggingRows.setLayoutData( fdlLoggingRows );
141 | wLoggingRows = new Button( shell, SWT.CHECK | SWT.LEFT );
142 | props.setLook( wLoggingRows );
143 | FormData fdLoggingRows = new FormData();
144 | fdLoggingRows.top = new FormAttachment( wlLoggingRows, 0, SWT.CENTER );
145 | fdLoggingRows.left = new FormAttachment( middle, 0 ); // To the right of the label
146 | fdLoggingRows.right = new FormAttachment( 100, 0 );
147 | wLoggingRows.setLayoutData( fdLoggingRows );
148 | lastControl = wLoggingRows;
149 |
150 | // Log result details?
151 | Label wlLoggingFiles = new Label( shell, SWT.RIGHT );
152 | props.setLook( wlLoggingFiles );
153 | wlLoggingFiles.setText( "Log result files?");
154 | FormData fdlLoggingFiles = new FormData();
155 | fdlLoggingFiles.top = new FormAttachment( lastControl, margin );
156 | fdlLoggingFiles.left = new FormAttachment( 0, 0 ); // First one in the left top corner
157 | fdlLoggingFiles.right = new FormAttachment( middle, -margin );
158 | wlLoggingFiles.setLayoutData( fdlLoggingFiles );
159 | wLoggingFiles = new Button( shell, SWT.CHECK | SWT.LEFT );
160 | props.setLook( wLoggingFiles );
161 | FormData fdLoggingFiles = new FormData();
162 | fdLoggingFiles.top = new FormAttachment( wlLoggingFiles, 0, SWT.CENTER );
163 | fdLoggingFiles.left = new FormAttachment( middle, 0 ); // To the right of the label
164 | fdLoggingFiles.right = new FormAttachment( 100, 0 );
165 | wLoggingFiles.setLayoutData( fdLoggingFiles );
166 | lastControl = wLoggingFiles;
167 |
168 | // Buttons
169 | Button wOK = new Button( shell, SWT.PUSH );
170 | wOK.setText( BaseMessages.getString( PKG, "System.Button.OK" ) );
171 | wOK.addListener( SWT.Selection, e -> ok() );
172 |
173 | Button wCancel = new Button( shell, SWT.PUSH );
174 | wCancel.setText( BaseMessages.getString( PKG, "System.Button.Cancel" ) );
175 | wCancel.addListener( SWT.Selection, e -> cancel() );
176 |
177 | Button[] buttons = new Button[] { wOK, wCancel };
178 | BaseStepDialog.positionBottomButtons( shell, buttons, margin*2, lastControl );
179 |
180 | SelectionAdapter selAdapter = new SelectionAdapter() {
181 | public void widgetDefaultSelected( SelectionEvent e ) {
182 | ok();
183 | }
184 | };
185 |
186 | wLogLevel.addSelectionListener( selAdapter );
187 |
188 | // Detect X or ALT-F4 or something that kills this window...
189 | shell.addShellListener( new ShellAdapter() {
190 | public void shellClosed( ShellEvent e ) {
191 | cancel();
192 | }
193 | } );
194 |
195 | getData();
196 |
197 | BaseStepDialog.setSize( shell );
198 |
199 | shell.open();
200 | Display display = parent.getDisplay();
201 | while ( !shell.isDisposed() ) {
202 | if ( !display.readAndDispatch() ) {
203 | display.sleep();
204 | }
205 | }
206 | return ok;
207 | }
208 |
209 | public void dispose() {
210 | props.setScreen( new WindowProperty( shell ) );
211 | shell.dispose();
212 | }
213 |
214 | public void getData() {
215 | wLogLevel.setText( debugLevel.getLogLevel().getDescription() );
216 | wLoggingResult.setSelection( debugLevel.isLoggingResult() );
217 | wLoggingVariables.setSelection( debugLevel.isLoggingVariables() );
218 | wLoggingRows.setSelection( debugLevel.isLoggingResultRows() );
219 | wLoggingFiles.setSelection( debugLevel.isLoggingResultFiles() );
220 |
221 | wLogLevel.setFocus();
222 | }
223 |
224 | private void cancel() {
225 | ok = false;
226 | dispose();
227 | }
228 |
229 | public void ok() {
230 | getInfo( input );
231 | ok = true;
232 | dispose();
233 | }
234 |
235 | // Get dialog info in securityService
236 | private void getInfo( JobEntryDebugLevel level ) {
237 | int index = Const.indexOfString( wLogLevel.getText(), LogLevel.getLogLevelDescriptions() );
238 | level.setLogLevel( LogLevel.values()[index] );
239 | level.setLoggingResult( wLoggingResult.getSelection() );
240 | level.setLoggingVariables( wLoggingVariables.getSelection() );
241 | level.setLoggingResultRows( wLoggingRows.getSelection() );
242 | level.setLoggingResultFiles( wLoggingFiles.getSelection() );
243 | }
244 |
245 | }
246 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/kettle-debug-plugin.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------