This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 43ebf9ff88 issue #7304 : Added Pipeline/Workflow Log option to fail 
the parent pipeline/workflow if the logging fails (#7361)
43ebf9ff88 is described below

commit 43ebf9ff886c2a52138ec6a48c2e7d8420ac379a
Author: Matt Casters <[email protected]>
AuthorDate: Mon Jun 29 15:23:58 2026 +0200

    issue #7304 : Added Pipeline/Workflow Log option to fail the parent 
pipeline/workflow if the logging fails (#7361)
---
 integration-tests/logging/001-abort-logging.hpl    | 101 +++++++
 integration-tests/logging/001-failing-pipeline.hpl |  76 ++++++
 integration-tests/logging/002-abort-logging.hpl    | 101 +++++++
 integration-tests/logging/002-failing-workflow.hwf |  74 ++++++
 integration-tests/logging/dev-env-config.json      |   9 +
 integration-tests/logging/hop-config.json          | 290 +++++++++++++++++++++
 .../logging/main-001-fail-pipeline-log.hwf         | 127 +++++++++
 .../logging/main-002-fail-workflow-log.hwf         | 123 +++++++++
 .../metadata/pipeline-log/fail-pipeline-log.json   |  17 ++
 .../metadata/pipeline-run-configuration/local.json |  17 ++
 .../metadata/workflow-log/fail-workflow-log.json   |  15 ++
 .../metadata/workflow-run-configuration/local.json |   9 +
 integration-tests/logging/project-config.json      |  13 +
 .../hop/reflection/pipeline/meta/PipelineLog.java  |   7 +-
 .../pipeline/meta/PipelineLogEditor.java           |  25 ++
 .../pipeline/xp/PipelineStartLoggingXp.java        | 117 ++++++---
 .../hop/reflection/workflow/meta/WorkflowLog.java  |   7 +-
 .../workflow/meta/WorkflowLogEditor.java           |  25 ++
 .../workflow/xp/WorkflowStartLoggingXp.java        |  95 +++++--
 .../meta/messages/messages_en_US.properties        |   1 +
 .../meta/messages/messages_en_US.properties        |   1 +
 21 files changed, 1194 insertions(+), 56 deletions(-)

diff --git a/integration-tests/logging/001-abort-logging.hpl 
b/integration-tests/logging/001-abort-logging.hpl
new file mode 100644
index 0000000000..8480a2e7f0
--- /dev/null
+++ b/integration-tests/logging/001-abort-logging.hpl
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<pipeline>
+  <info>
+    <name>001-abort-logging</name>
+    <name_sync_with_filename>Y</name_sync_with_filename>
+    <description/>
+    <extended_description/>
+    <pipeline_version/>
+    <pipeline_type>Normal</pipeline_type>
+    <parameters>
+    </parameters>
+    <capture_transform_performance>N</capture_transform_performance>
+    
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+    
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+    <created_user>-</created_user>
+    <created_date>2026/06/27 23:45:00.000</created_date>
+    <modified_user>-</modified_user>
+    <modified_date>2026/06/27 23:45:00.000</modified_date>
+  </info>
+  <notepads>
+  </notepads>
+  <order>
+    <hop>
+      <from>Generate rows</from>
+      <to>Abort</to>
+      <enabled>Y</enabled>
+    </hop>
+  </order>
+  <transform>
+    <name>Generate rows</name>
+    <type>RowGenerator</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <fields>
+      <field>
+        <length>-1</length>
+        <name>TEST</name>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <type>String</type>
+      </field>
+    </fields>
+    <interval_in_ms>5000</interval_in_ms>
+    <last_time_field>FiveSecondsAgo</last_time_field>
+    <limit>1</limit>
+    <never_ending>N</never_ending>
+    <row_time_field>now</row_time_field>
+    <attributes/>
+    <GUI>
+      <xloc>100</xloc>
+      <yloc>100</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>300</xloc>
+      <yloc>100</yloc>
+    </GUI>
+  </transform>
+  <transform_error_handling>
+  </transform_error_handling>
+  <attributes/>
+</pipeline>
diff --git a/integration-tests/logging/001-failing-pipeline.hpl 
b/integration-tests/logging/001-failing-pipeline.hpl
new file mode 100644
index 0000000000..66cddad83c
--- /dev/null
+++ b/integration-tests/logging/001-failing-pipeline.hpl
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<pipeline>
+  <info>
+    <name>001-failing-pipeline</name>
+    <name_sync_with_filename>Y</name_sync_with_filename>
+    <description/>
+    <extended_description/>
+    <pipeline_version/>
+    <pipeline_type>Normal</pipeline_type>
+    <parameters>
+    </parameters>
+    <capture_transform_performance>N</capture_transform_performance>
+    
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+    
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+    <created_user>-</created_user>
+    <created_date>2026/06/27 23:45:00.000</created_date>
+    <modified_user>-</modified_user>
+    <modified_date>2026/06/27 23:45:00.000</modified_date>
+  </info>
+  <notepads>
+  </notepads>
+  <order>
+  </order>
+  <transform>
+    <name>Generate rows</name>
+    <type>RowGenerator</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <fields>
+      <field>
+        <length>-1</length>
+        <name>TEST</name>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <type>String</type>
+      </field>
+    </fields>
+    <interval_in_ms>5000</interval_in_ms>
+    <last_time_field>FiveSecondsAgo</last_time_field>
+    <limit>1</limit>
+    <never_ending>N</never_ending>
+    <row_time_field>now</row_time_field>
+    <attributes/>
+    <GUI>
+      <xloc>100</xloc>
+      <yloc>100</yloc>
+    </GUI>
+  </transform>
+  <transform_error_handling>
+  </transform_error_handling>
+  <attributes/>
+</pipeline>
diff --git a/integration-tests/logging/002-abort-logging.hpl 
b/integration-tests/logging/002-abort-logging.hpl
new file mode 100644
index 0000000000..34a03046a8
--- /dev/null
+++ b/integration-tests/logging/002-abort-logging.hpl
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<pipeline>
+  <info>
+    <name>002-abort-logging</name>
+    <name_sync_with_filename>Y</name_sync_with_filename>
+    <description/>
+    <extended_description/>
+    <pipeline_version/>
+    <pipeline_type>Normal</pipeline_type>
+    <parameters>
+    </parameters>
+    <capture_transform_performance>N</capture_transform_performance>
+    
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+    
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+    <created_user>-</created_user>
+    <created_date>2026/06/27 23:45:00.000</created_date>
+    <modified_user>-</modified_user>
+    <modified_date>2026/06/27 23:45:00.000</modified_date>
+  </info>
+  <notepads>
+  </notepads>
+  <order>
+    <hop>
+      <from>Generate rows</from>
+      <to>Abort</to>
+      <enabled>Y</enabled>
+    </hop>
+  </order>
+  <transform>
+    <name>Generate rows</name>
+    <type>RowGenerator</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <fields>
+      <field>
+        <length>-1</length>
+        <name>TEST</name>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <type>String</type>
+      </field>
+    </fields>
+    <interval_in_ms>5000</interval_in_ms>
+    <last_time_field>FiveSecondsAgo</last_time_field>
+    <limit>1</limit>
+    <never_ending>N</never_ending>
+    <row_time_field>now</row_time_field>
+    <attributes/>
+    <GUI>
+      <xloc>100</xloc>
+      <yloc>100</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>300</xloc>
+      <yloc>100</yloc>
+    </GUI>
+  </transform>
+  <transform_error_handling>
+  </transform_error_handling>
+  <attributes/>
+</pipeline>
diff --git a/integration-tests/logging/002-failing-workflow.hwf 
b/integration-tests/logging/002-failing-workflow.hwf
new file mode 100644
index 0000000000..bc855bbc50
--- /dev/null
+++ b/integration-tests/logging/002-failing-workflow.hwf
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<workflow>
+  <name>002-failing-workflow</name>
+  <name_sync_with_filename>Y</name_sync_with_filename>
+  <description/>
+  <extended_description/>
+  <workflow_version/>
+  <created_user>-</created_user>
+  <created_date>2026/06/27 23:45:00.000</created_date>
+  <modified_user>-</modified_user>
+  <modified_date>2026/06/27 23:45:00.000</modified_date>
+  <parameters>
+  </parameters>
+  <actions>
+    <action>
+      <name>Start</name>
+      <description/>
+      <type>SPECIAL</type>
+      <attributes/>
+      <DayOfMonth>1</DayOfMonth>
+      <hour>12</hour>
+      <intervalMinutes>60</intervalMinutes>
+      <intervalSeconds>0</intervalSeconds>
+      <minutes>0</minutes>
+      <repeat>N</repeat>
+      <schedulerType>0</schedulerType>
+      <weekDay>1</weekDay>
+      <parallel>N</parallel>
+      <xloc>50</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>Success</name>
+      <description/>
+      <type>SUCCESS</type>
+      <attributes/>
+      <parallel>N</parallel>
+      <xloc>250</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+  </actions>
+  <hops>
+    <hop>
+      <from>Start</from>
+      <to>Success</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>Y</unconditional>
+    </hop>
+  </hops>
+  <notepads>
+  </notepads>
+  <attributes/>
+</workflow>
diff --git a/integration-tests/logging/dev-env-config.json 
b/integration-tests/logging/dev-env-config.json
new file mode 100644
index 0000000000..a1ca51bc29
--- /dev/null
+++ b/integration-tests/logging/dev-env-config.json
@@ -0,0 +1,9 @@
+{
+  "variables": [
+    {
+      "name": "SAMPLE",
+      "value": "sampleValue",
+      "description": "A sample variable value"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/integration-tests/logging/hop-config.json 
b/integration-tests/logging/hop-config.json
new file mode 100644
index 0000000000..d9e1e6562e
--- /dev/null
+++ b/integration-tests/logging/hop-config.json
@@ -0,0 +1,290 @@
+{
+  "variables": [
+    {
+      "name": "HOP_LENIENT_STRING_TO_NUMBER_CONVERSION",
+      "value": "N",
+      "description": "System wide flag to allow lenient string to number 
conversion for backward compatibility. If this setting is set to \"Y\", an 
string starting with digits will be converted successfully into a number. 
(example: 192.168.1.1 will be converted into 192 or 192.168 or 192168 depending 
on the decimal and grouping symbol). The default (N) will be to throw an error 
if non-numeric symbols are found in the string."
+    },
+    {
+      "name": "HOP_COMPATIBILITY_DB_IGNORE_TIMEZONE",
+      "value": "N",
+      "description": "System wide flag to ignore timezone while writing 
date/timestamp value to the database."
+    },
+    {
+      "name": "HOP_LOG_SIZE_LIMIT",
+      "value": "0",
+      "description": "The log size limit for all pipelines and workflows that 
don't have the \"log size limit\" property set in their respective properties."
+    },
+    {
+      "name": "HOP_EMPTY_STRING_DIFFERS_FROM_NULL",
+      "value": "N",
+      "description": "NULL vs Empty String. If this setting is set to Y, an 
empty string and null are different. Otherwise they are not."
+    },
+    {
+      "name": "HOP_MAX_LOG_SIZE_IN_LINES",
+      "value": "0",
+      "description": "The maximum number of log lines that are kept internally 
by Hop. Set to 0 to keep all rows (default)"
+    },
+    {
+      "name": "HOP_MAX_LOG_TIMEOUT_IN_MINUTES",
+      "value": "1440",
+      "description": "The maximum age (in minutes) of a log line while being 
kept internally by Hop. Set to 0 to keep all rows indefinitely (default)"
+    },
+    {
+      "name": "HOP_MAX_WORKFLOW_TRACKER_SIZE",
+      "value": "5000",
+      "description": "The maximum number of workflow trackers kept in memory"
+    },
+    {
+      "name": "HOP_MAX_ACTIONS_LOGGED",
+      "value": "5000",
+      "description": "The maximum number of action results kept in memory for 
logging purposes."
+    },
+    {
+      "name": "HOP_MAX_LOGGING_REGISTRY_SIZE",
+      "value": "10000",
+      "description": "The maximum number of logging registry entries kept in 
memory for logging purposes."
+    },
+    {
+      "name": "HOP_LOG_TAB_REFRESH_DELAY",
+      "value": "1000",
+      "description": "The hop log tab refresh delay."
+    },
+    {
+      "name": "HOP_LOG_TAB_REFRESH_PERIOD",
+      "value": "1000",
+      "description": "The hop log tab refresh period."
+    },
+    {
+      "name": "HOP_PLUGIN_CLASSES",
+      "value": null,
+      "description": "A comma delimited list of classes to scan for plugin 
annotations"
+    },
+    {
+      "name": "HOP_PLUGIN_PACKAGES",
+      "value": null,
+      "description": "A comma delimited list of packages to scan for plugin 
annotations (warning: slow!!)"
+    },
+    {
+      "name": "HOP_TRANSFORM_PERFORMANCE_SNAPSHOT_LIMIT",
+      "value": "0",
+      "description": "The maximum number of transform performance snapshots to 
keep in memory. Set to 0 to keep all snapshots indefinitely (default)"
+    },
+    {
+      "name": "HOP_ROWSET_GET_TIMEOUT",
+      "value": "50",
+      "description": "The name of the variable that optionally contains an 
alternative rowset get timeout (in ms). This only makes a difference for 
extremely short lived pipelines."
+    },
+    {
+      "name": "HOP_ROWSET_PUT_TIMEOUT",
+      "value": "50",
+      "description": "The name of the variable that optionally contains an 
alternative rowset put timeout (in ms). This only makes a difference for 
extremely short lived pipelines."
+    },
+    {
+      "name": "HOP_CORE_TRANSFORMS_FILE",
+      "value": null,
+      "description": "The name of the project variable that will contain the 
alternative location of the hop-transforms.xml file. You can use this to 
customize the list of available internal transforms outside of the codebase."
+    },
+    {
+      "name": "HOP_CORE_WORKFLOW_ACTIONS_FILE",
+      "value": null,
+      "description": "The name of the project variable that will contain the 
alternative location of the hop-workflow-actions.xml file."
+    },
+    {
+      "name": "HOP_SERVER_OBJECT_TIMEOUT_MINUTES",
+      "value": "1440",
+      "description": "This project variable will set a time-out after which 
waiting, completed or stopped pipelines and workflows will be automatically 
cleaned up. The default value is 1440 (one day)."
+    },
+    {
+      "name": "HOP_PIPELINE_PAN_JVM_EXIT_CODE",
+      "value": null,
+      "description": "Set this variable to an integer that will be returned as 
the Pan JVM exit code."
+    },
+    {
+      "name": "HOP_DISABLE_CONSOLE_LOGGING",
+      "value": "N",
+      "description": "Set this variable to Y to disable standard Hop logging 
to the console. (stdout)"
+    },
+    {
+      "name": "HOP_REDIRECT_STDERR",
+      "value": "N",
+      "description": "Set this variable to Y to redirect stderr to Hop 
logging."
+    },
+    {
+      "name": "HOP_REDIRECT_STDOUT",
+      "value": "N",
+      "description": "Set this variable to Y to redirect stdout to Hop 
logging."
+    },
+    {
+      "name": "HOP_DEFAULT_NUMBER_FORMAT",
+      "value": null,
+      "description": "The name of the variable containing an alternative 
default number format"
+    },
+    {
+      "name": "HOP_DEFAULT_BIGNUMBER_FORMAT",
+      "value": null,
+      "description": "The name of the variable containing an alternative 
default bignumber format"
+    },
+    {
+      "name": "HOP_DEFAULT_INTEGER_FORMAT",
+      "value": null,
+      "description": "The name of the variable containing an alternative 
default integer format"
+    },
+    {
+      "name": "HOP_DEFAULT_DATE_FORMAT",
+      "value": null,
+      "description": "The name of the variable containing an alternative 
default date format"
+    },
+    {
+      "name": "HOP_DEFAULT_TIMESTAMP_FORMAT",
+      "value": null,
+      "description": "The name of the variable containing an alternative 
default timestamp format"
+    },
+    {
+      "name": "HOP_DEFAULT_SERVLET_ENCODING",
+      "value": null,
+      "description": "Defines the default encoding for servlets, leave it 
empty to use Java default encoding"
+    },
+    {
+      "name": "HOP_FAIL_ON_LOGGING_ERROR",
+      "value": "N",
+      "description": "Set this variable to Y when you want the 
workflow/pipeline fail with an error when the related logging process (e.g. to 
a database) fails."
+    },
+    {
+      "name": "HOP_AGGREGATION_MIN_NULL_IS_VALUED",
+      "value": "N",
+      "description": "Set this variable to Y to set the minimum to NULL if 
NULL is within an aggregate. Otherwise by default NULL is ignored by the MIN 
aggregate and MIN is set to the minimum value that is not NULL. See also the 
variable HOP_AGGREGATION_ALL_NULLS_ARE_ZERO."
+    },
+    {
+      "name": "HOP_AGGREGATION_ALL_NULLS_ARE_ZERO",
+      "value": "N",
+      "description": "Set this variable to Y to return 0 when all values 
within an aggregate are NULL. Otherwise by default a NULL is returned when all 
values are NULL."
+    },
+    {
+      "name": "HOP_COMPATIBILITY_TEXT_FILE_OUTPUT_APPEND_NO_HEADER",
+      "value": "N",
+      "description": "Set this variable to Y for backward compatibility for 
the Text File Output transform. Setting this to Ywill add no header row at all 
when the append option is enabled, regardless if the file is existing or not."
+    },
+    {
+      "name": "HOP_PASSWORD_ENCODER_PLUGIN",
+      "value": "Hop",
+      "description": "Specifies the password encoder plugin to use by ID (Hop 
is the default)."
+    },
+    {
+      "name": "HOP_SYSTEM_HOSTNAME",
+      "value": null,
+      "description": "You can use this variable to speed up hostname lookup. 
Hostname lookup is performed by Hop so that it is capable of logging the server 
on which a workflow or pipeline is executed."
+    },
+    {
+      "name": "HOP_SERVER_JETTY_ACCEPTORS",
+      "value": null,
+      "description": "A variable to configure jetty option: acceptors for 
Carte"
+    },
+    {
+      "name": "HOP_SERVER_JETTY_ACCEPT_QUEUE_SIZE",
+      "value": null,
+      "description": "A variable to configure jetty option: acceptQueueSize 
for Carte"
+    },
+    {
+      "name": "HOP_SERVER_JETTY_RES_MAX_IDLE_TIME",
+      "value": null,
+      "description": "A variable to configure jetty option: 
lowResourcesMaxIdleTime for Carte"
+    },
+    {
+      "name": 
"HOP_COMPATIBILITY_MERGE_ROWS_USE_REFERENCE_STREAM_WHEN_IDENTICAL",
+      "value": "N",
+      "description": "Set this variable to Y for backward compatibility for 
the Merge Rows (diff) transform. Setting this to Y will use the data from the 
reference stream (instead of the comparison stream) in case the compared rows 
are identical."
+    },
+    {
+      "name": "HOP_SPLIT_FIELDS_REMOVE_ENCLOSURE",
+      "value": "false",
+      "description": "Set this variable to false to preserve enclosure symbol 
after splitting the string in the Split fields transform. Changing it to true 
will remove first and last enclosure symbol from the resulting string chunks."
+    },
+    {
+      "name": "HOP_ALLOW_EMPTY_FIELD_NAMES_AND_TYPES",
+      "value": "false",
+      "description": "Set this variable to TRUE to allow your pipeline to pass 
'null' fields and/or empty types."
+    },
+    {
+      "name": "HOP_GLOBAL_LOG_VARIABLES_CLEAR_ON_EXPORT",
+      "value": "false",
+      "description": "Set this variable to false to preserve global log 
variables defined in pipeline / workflow Properties -> Log panel. Changing it 
to true will clear it when export pipeline / workflow."
+    },
+    {
+      "name": "HOP_FILE_OUTPUT_MAX_STREAM_COUNT",
+      "value": "1024",
+      "description": "This project variable is used by the Text File Output 
transform. It defines the max number of simultaneously open files within the 
transform. The transform will close/reopen files as necessary to insure the max 
is not exceeded"
+    },
+    {
+      "name": "HOP_FILE_OUTPUT_MAX_STREAM_LIFE",
+      "value": "0",
+      "description": "This project variable is used by the Text File Output 
transform. It defines the max number of milliseconds between flushes of files 
opened by the transform."
+    },
+    {
+      "name": "HOP_USE_NATIVE_FILE_DIALOG",
+      "value": "N",
+      "description": "Set this value to Y if you want to use the system file 
open/save dialog when browsing files"
+    },
+    {
+      "name": "HOP_AUTO_CREATE_CONFIG",
+      "value": "Y",
+      "description": "Set this value to N if you don't want to automatically 
create a hop configuration file (hop-config.json) when it's missing"
+    }
+  ],
+  "LocaleDefault": "en_BE",
+  "guiProperties": {
+    "FontFixedSize": "13",
+    "MaxUndo": "100",
+    "DarkMode": "Y",
+    "FontNoteSize": "13",
+    "ShowOSLook": "Y",
+    "FontFixedStyle": "0",
+    "FontNoteName": ".AppleSystemUIFont",
+    "FontFixedName": "Monospaced",
+    "FontGraphStyle": "0",
+    "FontDefaultSize": "13",
+    "GraphColorR": "255",
+    "FontGraphSize": "13",
+    "IconSize": "32",
+    "BackgroundColorB": "255",
+    "FontNoteStyle": "0",
+    "FontGraphName": ".AppleSystemUIFont",
+    "FontDefaultName": ".AppleSystemUIFont",
+    "GraphColorG": "255",
+    "UseGlobalFileBookmarks": "Y",
+    "FontDefaultStyle": "0",
+    "GraphColorB": "255",
+    "BackgroundColorR": "255",
+    "BackgroundColorG": "255",
+    "WorkflowDialogStyle": "RESIZE,MAX,MIN",
+    "LineWidth": "1",
+    "ContextDialogShowCategories": "Y"
+  },
+  "projectsConfig": {
+    "enabled": true,
+    "projectMandatory": true,
+    "environmentMandatory": false,
+    "defaultProject": "default",
+    "defaultEnvironment": null,
+    "standardParentProject": "default",
+    "standardProjectsFolder": null,
+    "projectConfigurations": [
+      {
+        "projectName": "default",
+        "projectHome": "${HOP_CONFIG_FOLDER}",
+        "configFilename": "project-config.json"
+      }
+    ],
+    "lifecycleEnvironments": [
+      {
+        "name": "dev",
+        "purpose": "Testing",
+        "projectName": "default",
+        "configurationFiles": [
+          "${PROJECT_HOME}/dev-env-config.json"
+        ]
+      }
+    ],
+    "projectLifecycles": []
+  }
+}
\ No newline at end of file
diff --git a/integration-tests/logging/main-001-fail-pipeline-log.hwf 
b/integration-tests/logging/main-001-fail-pipeline-log.hwf
new file mode 100644
index 0000000000..b954805030
--- /dev/null
+++ b/integration-tests/logging/main-001-fail-pipeline-log.hwf
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<workflow>
+  <name>main-001-fail-pipeline-log</name>
+  <name_sync_with_filename>Y</name_sync_with_filename>
+  <description/>
+  <extended_description/>
+  <workflow_version/>
+  <created_user>-</created_user>
+  <created_date>2026/06/27 23:45:00.000</created_date>
+  <modified_user>-</modified_user>
+  <modified_date>2026/06/27 23:45:00.000</modified_date>
+  <parameters>
+  </parameters>
+  <actions>
+    <action>
+      <name>Start</name>
+      <description/>
+      <type>SPECIAL</type>
+      <attributes/>
+      <DayOfMonth>1</DayOfMonth>
+      <hour>12</hour>
+      <intervalMinutes>60</intervalMinutes>
+      <intervalSeconds>0</intervalSeconds>
+      <minutes>0</minutes>
+      <repeat>N</repeat>
+      <schedulerType>0</schedulerType>
+      <weekDay>1</weekDay>
+      <parallel>N</parallel>
+      <xloc>50</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>001-failing-pipeline.hpl</name>
+      <description/>
+      <type>PIPELINE</type>
+      <attributes/>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <clear_files>N</clear_files>
+      <clear_rows>N</clear_rows>
+      <create_parent_folder>N</create_parent_folder>
+      <exec_per_row>N</exec_per_row>
+      <filename>${PROJECT_HOME}/001-failing-pipeline.hpl</filename>
+      <logext/>
+      <logfile/>
+      <loglevel>Basic</loglevel>
+      <parameters>
+        <pass_all_parameters>Y</pass_all_parameters>
+      </parameters>
+      <params_from_previous>N</params_from_previous>
+      <run_configuration>local</run_configuration>
+      <set_append_logfile>N</set_append_logfile>
+      <set_logfile>N</set_logfile>
+      <wait_until_finished>Y</wait_until_finished>
+      <parallel>N</parallel>
+      <xloc>250</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>Success</name>
+      <description/>
+      <type>SUCCESS</type>
+      <attributes/>
+      <parallel>N</parallel>
+      <xloc>450</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>Abort workflow</name>
+      <description/>
+      <type>ABORT</type>
+      <attributes/>
+      <always_log_rows>N</always_log_rows>
+      <parallel>N</parallel>
+      <xloc>250</xloc>
+      <yloc>250</yloc>
+      <attributes_hac/>
+    </action>
+  </actions>
+  <hops>
+    <hop>
+      <from>Start</from>
+      <to>001-failing-pipeline.hpl</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>Y</unconditional>
+    </hop>
+    <hop>
+      <from>001-failing-pipeline.hpl</from>
+      <to>Success</to>
+      <enabled>Y</enabled>
+      <evaluation>N</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>001-failing-pipeline.hpl</from>
+      <to>Abort workflow</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+  </hops>
+  <notepads>
+  </notepads>
+  <attributes/>
+</workflow>
diff --git a/integration-tests/logging/main-002-fail-workflow-log.hwf 
b/integration-tests/logging/main-002-fail-workflow-log.hwf
new file mode 100644
index 0000000000..0abc8d3cdd
--- /dev/null
+++ b/integration-tests/logging/main-002-fail-workflow-log.hwf
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<workflow>
+  <name>main-002-fail-workflow-log</name>
+  <name_sync_with_filename>Y</name_sync_with_filename>
+  <description/>
+  <extended_description/>
+  <workflow_version/>
+  <created_user>-</created_user>
+  <created_date>2026/06/27 23:45:00.000</created_date>
+  <modified_user>-</modified_user>
+  <modified_date>2026/06/27 23:45:00.000</modified_date>
+  <parameters>
+  </parameters>
+  <actions>
+    <action>
+      <name>Start</name>
+      <description/>
+      <type>SPECIAL</type>
+      <attributes/>
+      <DayOfMonth>1</DayOfMonth>
+      <hour>12</hour>
+      <intervalMinutes>60</intervalMinutes>
+      <intervalSeconds>0</intervalSeconds>
+      <minutes>0</minutes>
+      <repeat>N</repeat>
+      <schedulerType>0</schedulerType>
+      <weekDay>1</weekDay>
+      <parallel>N</parallel>
+      <xloc>50</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>002-failing-workflow.hwf</name>
+      <description/>
+      <type>WORKFLOW</type>
+      <attributes/>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <create_parent_folder>N</create_parent_folder>
+      <exec_per_row>N</exec_per_row>
+      <filename>${PROJECT_HOME}/002-failing-workflow.hwf</filename>
+      <loglevel>Basic</loglevel>
+      <parameters>
+        <pass_all_parameters>Y</pass_all_parameters>
+      </parameters>
+      <params_from_previous>N</params_from_previous>
+      <run_configuration>local</run_configuration>
+      <set_append_logfile>N</set_append_logfile>
+      <set_logfile>N</set_logfile>
+      <wait_until_finished>Y</wait_until_finished>
+      <parallel>N</parallel>
+      <xloc>250</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>Success</name>
+      <description/>
+      <type>SUCCESS</type>
+      <attributes/>
+      <parallel>N</parallel>
+      <xloc>450</xloc>
+      <yloc>100</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>Abort workflow</name>
+      <description/>
+      <type>ABORT</type>
+      <attributes/>
+      <always_log_rows>N</always_log_rows>
+      <parallel>N</parallel>
+      <xloc>250</xloc>
+      <yloc>250</yloc>
+      <attributes_hac/>
+    </action>
+  </actions>
+  <hops>
+    <hop>
+      <from>Start</from>
+      <to>002-failing-workflow.hwf</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>Y</unconditional>
+    </hop>
+    <hop>
+      <from>002-failing-workflow.hwf</from>
+      <to>Success</to>
+      <enabled>Y</enabled>
+      <evaluation>N</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>002-failing-workflow.hwf</from>
+      <to>Abort workflow</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+  </hops>
+  <notepads>
+  </notepads>
+  <attributes/>
+</workflow>
diff --git 
a/integration-tests/logging/metadata/pipeline-log/fail-pipeline-log.json 
b/integration-tests/logging/metadata/pipeline-log/fail-pipeline-log.json
new file mode 100644
index 0000000000..fb882be675
--- /dev/null
+++ b/integration-tests/logging/metadata/pipeline-log/fail-pipeline-log.json
@@ -0,0 +1,17 @@
+{
+  "name": "fail-pipeline-log",
+  "enabled": true,
+  "loggingParentsOnly": false,
+  "pipelineFilename": "${PROJECT_HOME}/001-abort-logging.hpl",
+  "executingAtStart": true,
+  "executingPeriodically": false,
+  "intervalInSeconds": "30",
+  "executingAtEnd": true,
+  "logLevel": "BASIC",
+  "pipelinesToLog": [
+    {
+      "pipelineToLogFilename": "${PROJECT_HOME}/001-failing-pipeline.hpl"
+    }
+  ],
+  "failParentOnLoggingFailure": true
+}
diff --git 
a/integration-tests/logging/metadata/pipeline-run-configuration/local.json 
b/integration-tests/logging/metadata/pipeline-run-configuration/local.json
new file mode 100644
index 0000000000..63794efcaf
--- /dev/null
+++ b/integration-tests/logging/metadata/pipeline-run-configuration/local.json
@@ -0,0 +1,17 @@
+{
+  "engineRunConfiguration": {
+    "Local": {
+      "feedback_size": "50000",
+      "sample_size": "100",
+      "sample_type_in_gui": "Last",
+      "rowset_size": "10000",
+      "safe_mode": false,
+      "show_feedback": false,
+      "topo_sort": false,
+      "gather_metrics": false
+    }
+  },
+  "configurationVariables": [],
+  "name": "local",
+  "description": "Runs your pipelines locally with the standard local Hop 
pipeline engine"
+}
\ No newline at end of file
diff --git 
a/integration-tests/logging/metadata/workflow-log/fail-workflow-log.json 
b/integration-tests/logging/metadata/workflow-log/fail-workflow-log.json
new file mode 100644
index 0000000000..63ea76eb32
--- /dev/null
+++ b/integration-tests/logging/metadata/workflow-log/fail-workflow-log.json
@@ -0,0 +1,15 @@
+{
+  "name": "fail-workflow-log",
+  "enabled": true,
+  "loggingParentsOnly": false,
+  "pipelineFilename": "${PROJECT_HOME}/002-abort-logging.hpl",
+  "executingAtStart": true,
+  "executingPeriodically": false,
+  "intervalInSeconds": "30",
+  "executingAtEnd": true,
+  "logLevel": "BASIC",
+  "workflowToLog": [
+    "${PROJECT_HOME}/002-failing-workflow.hwf"
+  ],
+  "failParentOnLoggingFailure": true
+}
diff --git 
a/integration-tests/logging/metadata/workflow-run-configuration/local.json 
b/integration-tests/logging/metadata/workflow-run-configuration/local.json
new file mode 100644
index 0000000000..e37a93039a
--- /dev/null
+++ b/integration-tests/logging/metadata/workflow-run-configuration/local.json
@@ -0,0 +1,9 @@
+{
+  "engineRunConfiguration": {
+    "Local": {
+      "safe_mode": false
+    }
+  },
+  "name": "local",
+  "description": "Runs your workflows locally with the standard local Hop 
workflow engine"
+}
\ No newline at end of file
diff --git a/integration-tests/logging/project-config.json 
b/integration-tests/logging/project-config.json
new file mode 100644
index 0000000000..6a91171e1c
--- /dev/null
+++ b/integration-tests/logging/project-config.json
@@ -0,0 +1,13 @@
+{
+  "metadataBaseFolder" : "${PROJECT_HOME}/metadata",
+  "unitTestsBasePath" : "${PROJECT_HOME}",
+  "dataSetsCsvFolder" : "${PROJECT_HOME}/datasets",
+  "enforcingExecutionInHome" : true,
+  "config" : {
+    "variables" : [ {
+      "name" : "HOP_LICENSE_HEADER_FILE",
+      "value" : "${PROJECT_HOME}/../asf-header.txt",
+      "description" : "This will automatically serialize the ASF license 
header into pipelines and workflows in the integration test projects"
+    } ]
+  }
+}
\ No newline at end of file
diff --git 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLog.java
 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLog.java
index 98f743f950..24bdae5f7a 100644
--- 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLog.java
+++ 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLog.java
@@ -44,6 +44,7 @@ public class PipelineLog extends HopMetadataBase implements 
IHopMetadata {
 
   @HopMetadataProperty private boolean enabled;
   @HopMetadataProperty private boolean loggingParentsOnly;
+  @HopMetadataProperty private boolean failParentOnLoggingFailure;
 
   @HopMetadataProperty(hopMetadataPropertyType = 
HopMetadataPropertyType.PIPELINE_FILE)
   private String pipelineFilename;
@@ -62,6 +63,7 @@ public class PipelineLog extends HopMetadataBase implements 
IHopMetadata {
   public PipelineLog() {
     enabled = true;
     loggingParentsOnly = false;
+    failParentOnLoggingFailure = false;
     executingAtStart = true;
     executingPeriodically = false;
     intervalInSeconds = "30";
@@ -73,6 +75,7 @@ public class PipelineLog extends HopMetadataBase implements 
IHopMetadata {
   public PipelineLog(String name) {
     super(name);
     pipelinesToLog = new ArrayList<>();
+    failParentOnLoggingFailure = false;
   }
 
   public PipelineLog(
@@ -84,7 +87,8 @@ public class PipelineLog extends HopMetadataBase implements 
IHopMetadata {
       boolean executingPeriodically,
       String intervalInSeconds,
       boolean executingAtEnd,
-      List<PipelineToLogLocation> pipelinesToLog) {
+      List<PipelineToLogLocation> pipelinesToLog,
+      boolean failParentOnLoggingFailure) {
     super(name);
     this.enabled = enabled;
     this.loggingParentsOnly = loggingParentsOnly;
@@ -94,5 +98,6 @@ public class PipelineLog extends HopMetadataBase implements 
IHopMetadata {
     this.intervalInSeconds = intervalInSeconds;
     this.executingAtEnd = executingAtEnd;
     this.pipelinesToLog = pipelinesToLog;
+    this.failParentOnLoggingFailure = failParentOnLoggingFailure;
   }
 }
diff --git 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLogEditor.java
 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLogEditor.java
index 37e15b2d70..37de386fa0 100644
--- 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLogEditor.java
+++ 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/meta/PipelineLogEditor.java
@@ -63,6 +63,7 @@ public class PipelineLogEditor extends 
MetadataEditor<PipelineLog> {
   private Text wName;
   private Button wEnabled;
   private Button wLoggingParentsOnly;
+  private Button wFailParentOnLoggingFailure;
   private TextVar wFilename;
   private Combo wLogLevel;
   private Button wAtStart;
@@ -157,6 +158,27 @@ public class PipelineLogEditor extends 
MetadataEditor<PipelineLog> {
     wLoggingParentsOnly.setLayoutData(fdLoggingParentsOnly);
     lastControl = wlLoggingParentsOnly;
 
+    // FailParentOnLoggingFailure?
+    //
+    Label wlFailParentOnLoggingFailure = new Label(parent, SWT.RIGHT);
+    PropsUi.setLook(wlFailParentOnLoggingFailure);
+    wlFailParentOnLoggingFailure.setText(
+        BaseMessages.getString(PKG, 
"PipelineLoggingEditor.FailParentOnLoggingFailure.Label"));
+    FormData fdlFailParentOnLoggingFailure = new FormData();
+    fdlFailParentOnLoggingFailure.left = new FormAttachment(0, 0);
+    fdlFailParentOnLoggingFailure.right = new FormAttachment(middle, 0);
+    fdlFailParentOnLoggingFailure.top = new FormAttachment(lastControl, 2 * 
margin);
+    wlFailParentOnLoggingFailure.setLayoutData(fdlFailParentOnLoggingFailure);
+    wFailParentOnLoggingFailure = new Button(parent, SWT.CHECK | SWT.LEFT);
+    PropsUi.setLook(wFailParentOnLoggingFailure);
+    FormData fdFailParentOnLoggingFailure = new FormData();
+    fdFailParentOnLoggingFailure.left = new FormAttachment(middle, margin);
+    fdFailParentOnLoggingFailure.right = new FormAttachment(100, 0);
+    fdFailParentOnLoggingFailure.top =
+        new FormAttachment(wlFailParentOnLoggingFailure, 0, SWT.CENTER);
+    wFailParentOnLoggingFailure.setLayoutData(fdFailParentOnLoggingFailure);
+    lastControl = wlFailParentOnLoggingFailure;
+
     Label wlFilename = new Label(parent, SWT.RIGHT);
     PropsUi.setLook(wlFilename);
     wlFilename.setText(BaseMessages.getString(PKG, 
"PipelineLoggingEditor.Filename.Label"));
@@ -334,6 +356,7 @@ public class PipelineLogEditor extends 
MetadataEditor<PipelineLog> {
     wName.addListener(SWT.Modify, modifyListener);
     wEnabled.addListener(SWT.Selection, modifyListener);
     wLoggingParentsOnly.addListener(SWT.Selection, modifyListener);
+    wFailParentOnLoggingFailure.addListener(SWT.Selection, modifyListener);
     wFilename.addListener(SWT.Modify, modifyListener);
     wLogLevel.addListener(SWT.Modify, modifyListener);
     wAtStart.addListener(SWT.Selection, modifyListener);
@@ -446,6 +469,7 @@ public class PipelineLogEditor extends 
MetadataEditor<PipelineLog> {
     wName.setText(Const.NVL(pl.getName(), ""));
     wEnabled.setSelection(pl.isEnabled());
     wLoggingParentsOnly.setSelection(pl.isLoggingParentsOnly());
+    
wFailParentOnLoggingFailure.setSelection(pl.isFailParentOnLoggingFailure());
     wFilename.setText(Const.NVL(pl.getPipelineFilename(), ""));
     wLogLevel.setText(pl.getLogLevel().getDescription());
     wAtStart.setSelection(pl.isExecutingAtStart());
@@ -467,6 +491,7 @@ public class PipelineLogEditor extends 
MetadataEditor<PipelineLog> {
     pl.setName(wName.getText());
     pl.setEnabled(wEnabled.getSelection());
     pl.setLoggingParentsOnly(wLoggingParentsOnly.getSelection());
+    
pl.setFailParentOnLoggingFailure(wFailParentOnLoggingFailure.getSelection());
     pl.setPipelineFilename(wFilename.getText());
     pl.setLogLevel(LogLevel.lookupDescription(wLogLevel.getText()));
     pl.setExecutingAtStart(wAtStart.getSelection());
diff --git 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/xp/PipelineStartLoggingXp.java
 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/xp/PipelineStartLoggingXp.java
index ff9c0a1e45..66ea83a8fa 100644
--- 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/xp/PipelineStartLoggingXp.java
+++ 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/pipeline/xp/PipelineStartLoggingXp.java
@@ -111,18 +111,28 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
         return;
       }
     } catch (Exception e) {
-      pipeline.stopAll();
-      throw new HopException(
-          "Error handling Pipeline Log metadata object '"
-              + pipelineLog.getName()
-              + "' at the start of pipeline: "
-              + pipeline,
-          e);
+      if (pipelineLog.isFailParentOnLoggingFailure()) {
+        pipeline.stopAll();
+        throw new HopException(
+            "Error handling Pipeline Log metadata object '"
+                + pipelineLog.getName()
+                + "' at the start of pipeline: "
+                + e.getMessage(),
+            e);
+      } else {
+        log.logError(
+            "Error handling Pipeline Log metadata object '"
+                + pipelineLog.getName()
+                + "' at the start of pipeline: "
+                + e.getMessage(),
+            e);
+        return;
+      }
     }
 
     // check if we need to log everything or specific pipelines only.
     if (pipelineLog.getPipelinesToLog().isEmpty()) {
-      logPipeline(pipelineLog, pipeline, loggingPipelineFilename, variables);
+      logPipeline(log, pipelineLog, pipeline, loggingPipelineFilename, 
variables);
     } else {
       for (PipelineToLogLocation pipelineToLogLocation : 
pipelineLog.getPipelinesToLog()) {
 
@@ -134,7 +144,7 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
                       
variables.resolve(pipelineToLogLocation.getPipelineToLogFilename()))
                   .getPublicURIString();
           if (pipelineUri.equals(pipelineToLogUri)) {
-            logPipeline(pipelineLog, pipeline, loggingPipelineFilename, 
variables);
+            logPipeline(log, pipelineLog, pipeline, loggingPipelineFilename, 
variables);
           }
         }
       }
@@ -142,6 +152,7 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
   }
 
   private void logPipeline(
+      ILogChannel log,
       PipelineLog pipelineLog,
       IPipelineEngine<PipelineMeta> pipeline,
       String loggingPipelineFilename,
@@ -157,9 +168,23 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
       if (pipelineLog.isExecutingAtEnd()) {
         pipeline.addExecutionFinishedListener(
             engine -> {
-              executeLoggingPipeline(
-                  pipelineLog, "end", loggingPipelineFilename, pipeline, 
variables);
-              ExecutorUtil.cleanup(timer);
+              try {
+                executeLoggingPipeline(
+                    pipelineLog, "end", loggingPipelineFilename, pipeline, 
variables);
+              } catch (HopException e) {
+                if (pipelineLog.isFailParentOnLoggingFailure()) {
+                  throw e;
+                } else {
+                  log.logError(
+                      "Error handling Pipeline Log metadata object '"
+                          + pipelineLog.getName()
+                          + "' at the end of pipeline: "
+                          + e.getMessage(),
+                      e);
+                }
+              } finally {
+                ExecutorUtil.cleanup(timer);
+              }
             });
         pipeline.addExecutionStoppedListener(
             engine -> {
@@ -167,13 +192,23 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
                 executeLoggingPipeline(
                     pipelineLog, "stop", loggingPipelineFilename, pipeline, 
variables);
               } catch (Exception e) {
-                throw new HopRuntimeException(
-                    "Unable to do interval logging for Pipeline Log object '"
-                        + pipelineLog.getName()
-                        + "'",
-                    e);
+                if (pipelineLog.isFailParentOnLoggingFailure()) {
+                  throw new HopRuntimeException(
+                      "Unable to do stop logging for Pipeline Log object '"
+                          + pipelineLog.getName()
+                          + "'",
+                      e);
+                } else {
+                  log.logError(
+                      "Unable to do stop logging for Pipeline Log object '"
+                          + pipelineLog.getName()
+                          + "': "
+                          + e.getMessage(),
+                      e);
+                }
+              } finally {
+                ExecutorUtil.cleanup(timer);
               }
-              ExecutorUtil.cleanup(timer);
             });
       }
 
@@ -189,11 +224,20 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
                     executeLoggingPipeline(
                         pipelineLog, "interval", loggingPipelineFilename, 
pipeline, variables);
                   } catch (Exception e) {
-                    throw new HopRuntimeException(
-                        "Unable to do interval logging for Pipeline Log object 
'"
-                            + pipelineLog.getName()
-                            + "'",
-                        e);
+                    if (pipelineLog.isFailParentOnLoggingFailure()) {
+                      throw new HopRuntimeException(
+                          "Unable to do interval logging for Pipeline Log 
object '"
+                              + pipelineLog.getName()
+                              + "'",
+                          e);
+                    } else {
+                      log.logError(
+                          "Unable to do interval logging for Pipeline Log 
object '"
+                              + pipelineLog.getName()
+                              + "': "
+                              + e.getMessage(),
+                          e);
+                    }
                   }
                 }
               };
@@ -201,13 +245,22 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
         }
       }
     } catch (Exception e) {
-      pipeline.stopAll();
-      throw new HopException(
-          "Error handling Pipeline Log metadata object '"
-              + pipelineLog.getName()
-              + "' at the start of pipeline: "
-              + pipeline,
-          e);
+      if (pipelineLog.isFailParentOnLoggingFailure()) {
+        pipeline.stopAll();
+        throw new HopException(
+            "Error handling Pipeline Log metadata object '"
+                + pipelineLog.getName()
+                + "' at the start of pipeline: "
+                + e.getMessage(),
+            e);
+      } else {
+        log.logError(
+            "Error handling Pipeline Log metadata object '"
+                + pipelineLog.getName()
+                + "' at the start of pipeline: "
+                + e.getMessage(),
+            e);
+      }
     }
   }
 
@@ -248,6 +301,10 @@ public class PipelineStartLoggingXp implements 
IExtensionPoint<Pipeline> {
     //
     loggingPipeline.startThreads();
     loggingPipeline.waitUntilFinished();
+
+    if (loggingPipeline.getErrors() > 0) {
+      throw new HopException("Errors occurred during logging pipeline 
execution.");
+    }
   }
 
   private boolean logLocationExists(
diff --git 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLog.java
 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLog.java
index 14c348a793..7dff56fc1e 100644
--- 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLog.java
+++ 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLog.java
@@ -44,6 +44,7 @@ public class WorkflowLog extends HopMetadataBase implements 
IHopMetadata {
 
   @HopMetadataProperty private boolean enabled;
   @HopMetadataProperty private boolean loggingParentsOnly;
+  @HopMetadataProperty private boolean failParentOnLoggingFailure;
 
   @HopMetadataProperty(hopMetadataPropertyType = 
HopMetadataPropertyType.PIPELINE_FILE)
   private String pipelineFilename;
@@ -62,6 +63,7 @@ public class WorkflowLog extends HopMetadataBase implements 
IHopMetadata {
   public WorkflowLog() {
     enabled = true;
     loggingParentsOnly = false;
+    failParentOnLoggingFailure = false;
     executingAtStart = true;
     executingPeriodically = false;
     intervalInSeconds = "30";
@@ -73,6 +75,7 @@ public class WorkflowLog extends HopMetadataBase implements 
IHopMetadata {
   public WorkflowLog(String name) {
     super(name);
     workflowToLog = new ArrayList<>();
+    failParentOnLoggingFailure = false;
   }
 
   public WorkflowLog(
@@ -84,7 +87,8 @@ public class WorkflowLog extends HopMetadataBase implements 
IHopMetadata {
       boolean executingPeriodically,
       String intervalInSeconds,
       boolean executingAtEnd,
-      List<String> workflowToLog) {
+      List<String> workflowToLog,
+      boolean failParentOnLoggingFailure) {
     super(name);
     this.enabled = enabled;
     this.loggingParentsOnly = loggingParentsOnly;
@@ -94,5 +98,6 @@ public class WorkflowLog extends HopMetadataBase implements 
IHopMetadata {
     this.intervalInSeconds = intervalInSeconds;
     this.executingAtEnd = executingAtEnd;
     this.workflowToLog = workflowToLog;
+    this.failParentOnLoggingFailure = failParentOnLoggingFailure;
   }
 }
diff --git 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLogEditor.java
 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLogEditor.java
index 2baa101923..505981b399 100644
--- 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLogEditor.java
+++ 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/meta/WorkflowLogEditor.java
@@ -63,6 +63,7 @@ public class WorkflowLogEditor extends 
MetadataEditor<WorkflowLog> {
   private Text wName;
   private Button wEnabled;
   private Button wLoggingParentsOnly;
+  private Button wFailParentOnLoggingFailure;
   private TextVar wFilename;
   private Combo wLogLevel;
   private Button wAtStart;
@@ -157,6 +158,27 @@ public class WorkflowLogEditor extends 
MetadataEditor<WorkflowLog> {
     wLoggingParentsOnly.setLayoutData(fdLoggingParentsOnly);
     lastControl = wlLoggingParentsOnly;
 
+    // FailParentOnLoggingFailure?
+    //
+    Label wlFailParentOnLoggingFailure = new Label(parent, SWT.RIGHT);
+    PropsUi.setLook(wlFailParentOnLoggingFailure);
+    wlFailParentOnLoggingFailure.setText(
+        BaseMessages.getString(PKG, 
"WorkflowLoggingEditor.FailParentOnLoggingFailure.Label"));
+    FormData fdlFailParentOnLoggingFailure = new FormData();
+    fdlFailParentOnLoggingFailure.left = new FormAttachment(0, 0);
+    fdlFailParentOnLoggingFailure.right = new FormAttachment(middle, 0);
+    fdlFailParentOnLoggingFailure.top = new FormAttachment(lastControl, 
margin);
+    wlFailParentOnLoggingFailure.setLayoutData(fdlFailParentOnLoggingFailure);
+    wFailParentOnLoggingFailure = new Button(parent, SWT.CHECK | SWT.LEFT);
+    PropsUi.setLook(wFailParentOnLoggingFailure);
+    FormData fdFailParentOnLoggingFailure = new FormData();
+    fdFailParentOnLoggingFailure.left = new FormAttachment(middle, margin);
+    fdFailParentOnLoggingFailure.right = new FormAttachment(100, 0);
+    fdFailParentOnLoggingFailure.top =
+        new FormAttachment(wlFailParentOnLoggingFailure, 0, SWT.CENTER);
+    wFailParentOnLoggingFailure.setLayoutData(fdFailParentOnLoggingFailure);
+    lastControl = wlFailParentOnLoggingFailure;
+
     // The filename and some buttons to the right
     //
     Label wlFilename = new Label(parent, SWT.RIGHT);
@@ -336,6 +358,7 @@ public class WorkflowLogEditor extends 
MetadataEditor<WorkflowLog> {
     wName.addListener(SWT.Modify, modifyListener);
     wEnabled.addListener(SWT.Selection, modifyListener);
     wLoggingParentsOnly.addListener(SWT.Selection, modifyListener);
+    wFailParentOnLoggingFailure.addListener(SWT.Selection, modifyListener);
     wFilename.addListener(SWT.Modify, modifyListener);
     wLogLevel.addListener(SWT.Modify, modifyListener);
     wAtStart.addListener(SWT.Selection, modifyListener);
@@ -448,6 +471,7 @@ public class WorkflowLogEditor extends 
MetadataEditor<WorkflowLog> {
     wName.setText(Const.NVL(wl.getName(), ""));
     wEnabled.setSelection(wl.isEnabled());
     wLoggingParentsOnly.setSelection(wl.isLoggingParentsOnly());
+    
wFailParentOnLoggingFailure.setSelection(wl.isFailParentOnLoggingFailure());
     wFilename.setText(Const.NVL(wl.getPipelineFilename(), ""));
     wLogLevel.setText(wl.getLogLevel().getDescription());
     wAtStart.setSelection(wl.isExecutingAtStart());
@@ -469,6 +493,7 @@ public class WorkflowLogEditor extends 
MetadataEditor<WorkflowLog> {
     pl.setName(wName.getText());
     pl.setEnabled(wEnabled.getSelection());
     pl.setLoggingParentsOnly(wLoggingParentsOnly.getSelection());
+    
pl.setFailParentOnLoggingFailure(wFailParentOnLoggingFailure.getSelection());
     pl.setPipelineFilename(wFilename.getText());
     pl.setLogLevel(LogLevel.lookupDescription(wLogLevel.getText()));
     pl.setExecutingAtStart(wAtStart.getSelection());
diff --git 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/xp/WorkflowStartLoggingXp.java
 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/xp/WorkflowStartLoggingXp.java
index 507bae6349..43fa2e25f8 100644
--- 
a/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/xp/WorkflowStartLoggingXp.java
+++ 
b/plugins/misc/reflection/src/main/java/org/apache/hop/reflection/workflow/xp/WorkflowStartLoggingXp.java
@@ -96,30 +96,41 @@ public class WorkflowStartLoggingXp implements 
IExtensionPoint<IWorkflowEngine<W
         return;
       }
     } catch (Exception e) {
-      workflow.stopExecution();
-      throw new HopException(
-          "Error handling Workflow Log metadata object '"
-              + workflowLog.getName()
-              + "' at the start of pipeline: "
-              + workflow,
-          e);
+      if (workflowLog.isFailParentOnLoggingFailure()) {
+        workflow.stopExecution();
+        throw new HopException(
+            "Error handling Workflow Log metadata object '"
+                + workflowLog.getName()
+                + "' at the start of workflow: "
+                + e.getMessage(),
+            e);
+      } else {
+        log.logError(
+            "Error handling Workflow Log metadata object '"
+                + workflowLog.getName()
+                + "' at the start of workflow: "
+                + e.getMessage(),
+            e);
+        return;
+      }
     }
 
     if (workflowLog.getWorkflowToLog().isEmpty()) {
-      logWorkflow(workflowLog, workflow, variables, loggingPipelineFilename);
+      logWorkflow(log, workflowLog, workflow, variables, 
loggingPipelineFilename);
     } else {
       for (String workflowToLog : workflowLog.getWorkflowToLog()) {
         String workflowUri = 
HopVfs.getFileObject(workflow.getFilename()).getPublicURIString();
         String workflowToLogUri =
             
HopVfs.getFileObject(variables.resolve(workflowToLog)).getPublicURIString();
         if (workflowUri.equals(workflowToLogUri)) {
-          logWorkflow(workflowLog, workflow, variables, 
loggingPipelineFilename);
+          logWorkflow(log, workflowLog, workflow, variables, 
loggingPipelineFilename);
         }
       }
     }
   }
 
   private void logWorkflow(
+      ILogChannel log,
       WorkflowLog workflowLog,
       IWorkflowEngine<WorkflowMeta> workflow,
       IVariables variables,
@@ -135,9 +146,23 @@ public class WorkflowStartLoggingXp implements 
IExtensionPoint<IWorkflowEngine<W
       if (workflowLog.isExecutingAtEnd()) {
         workflow.addExecutionFinishedListener(
             engine -> {
-              executeLoggingPipeline(
-                  workflowLog, "end", loggingPipelineFilename, workflow, 
variables);
-              ExecutorUtil.cleanup(timer);
+              try {
+                executeLoggingPipeline(
+                    workflowLog, "end", loggingPipelineFilename, workflow, 
variables);
+              } catch (HopException e) {
+                if (workflowLog.isFailParentOnLoggingFailure()) {
+                  throw e;
+                } else {
+                  log.logError(
+                      "Error handling Workflow Log metadata object '"
+                          + workflowLog.getName()
+                          + "' at the end of workflow: "
+                          + e.getMessage(),
+                      e);
+                }
+              } finally {
+                ExecutorUtil.cleanup(timer);
+              }
             });
       }
 
@@ -153,11 +178,20 @@ public class WorkflowStartLoggingXp implements 
IExtensionPoint<IWorkflowEngine<W
                     executeLoggingPipeline(
                         workflowLog, "interval", loggingPipelineFilename, 
workflow, variables);
                   } catch (Exception e) {
-                    throw new HopRuntimeException(
-                        "Unable to do interval logging for Workflow Log object 
'"
-                            + workflowLog.getName()
-                            + "'",
-                        e);
+                    if (workflowLog.isFailParentOnLoggingFailure()) {
+                      throw new HopRuntimeException(
+                          "Unable to do interval logging for Workflow Log 
object '"
+                              + workflowLog.getName()
+                              + "'",
+                          e);
+                    } else {
+                      log.logError(
+                          "Unable to do interval logging for Workflow Log 
object '"
+                              + workflowLog.getName()
+                              + "': "
+                              + e.getMessage(),
+                          e);
+                    }
                   }
                 }
               };
@@ -165,13 +199,22 @@ public class WorkflowStartLoggingXp implements 
IExtensionPoint<IWorkflowEngine<W
         }
       }
     } catch (Exception e) {
-      workflow.stopExecution();
-      throw new HopException(
-          "Error handling Workflow Log metadata object '"
-              + workflowLog.getName()
-              + "' at the start of pipeline: "
-              + workflow,
-          e);
+      if (workflowLog.isFailParentOnLoggingFailure()) {
+        workflow.stopExecution();
+        throw new HopException(
+            "Error handling Workflow Log metadata object '"
+                + workflowLog.getName()
+                + "' at the start of workflow: "
+                + e.getMessage(),
+            e);
+      } else {
+        log.logError(
+            "Error handling Workflow Log metadata object '"
+                + workflowLog.getName()
+                + "' at the start of workflow: "
+                + e.getMessage(),
+            e);
+      }
     }
   }
 
@@ -211,5 +254,9 @@ public class WorkflowStartLoggingXp implements 
IExtensionPoint<IWorkflowEngine<W
     //
     loggingPipeline.startThreads();
     loggingPipeline.waitUntilFinished();
+
+    if (loggingPipeline.getErrors() > 0) {
+      throw new HopException("Errors occurred during logging pipeline 
execution.");
+    }
   }
 }
diff --git 
a/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/pipeline/meta/messages/messages_en_US.properties
 
b/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/pipeline/meta/messages/messages_en_US.properties
index 9da71fef93..efd23ffa90 100644
--- 
a/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/pipeline/meta/messages/messages_en_US.properties
+++ 
b/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/pipeline/meta/messages/messages_en_US.properties
@@ -27,5 +27,6 @@ PipelineLoggingEditor.Name.Label=Name
 PipelineLoggingEditor.Periodic.Label=Execute periodically during execution
 PipelineLoggingEditor.Sources.Label=Capture output of the following pipelines
 PipelineLoggingEditor.SourcesTable.Column.Pipeline=Pipeline
+PipelineLoggingEditor.FailParentOnLoggingFailure.Label=Fail pipeline if 
logging fails
 PipelineLog.name=Pipeline Log
 PipelineLog.description=This metadata object type allows you to log activity 
of a pipeline with another pipeline
\ No newline at end of file
diff --git 
a/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/workflow/meta/messages/messages_en_US.properties
 
b/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/workflow/meta/messages/messages_en_US.properties
index 18aac50d37..027b033e38 100644
--- 
a/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/workflow/meta/messages/messages_en_US.properties
+++ 
b/plugins/misc/reflection/src/main/resources/org/apache/hop/reflection/workflow/meta/messages/messages_en_US.properties
@@ -27,5 +27,6 @@ WorkflowLoggingEditor.Name.Label=Name
 WorkflowLoggingEditor.Periodic.Label=Execute periodically during execution
 WorkflowLoggingEditor.Sources.Label=Capture output of the following workflows
 WorkflowLoggingEditor.SourcesTable.Column.Pipeline=Workflow
+WorkflowLoggingEditor.FailParentOnLoggingFailure.Label=Fail workflow if 
logging fails
 WorkflowLog.name=Workflow Log
 WorkflowLog.description=This metadata object type allows you to log activity 
of a workflow with a pipeline
\ No newline at end of file

Reply via email to