This closes #197
diff --git a/docs/customizations.md b/docs/customizations.md
index 77599a1..f1d4809 100644
--- a/docs/customizations.md
+++ b/docs/customizations.md
@@ -13,7 +13,7 @@
 
 * Composer - Custom Config Widgets: special widgets to use for config keys can be specified in a registered type's
   definition as a map tag, for example for the demo widget `suggestion-dropout` included we might have 
-      '{ ui-composer-hints: { config-widgets: [ { 
+      `{ ui-composer-hints: { config-widgets: [ { 
          key: start.timeout, suggestion-values: [ 30s, 2m, 5m, 30m, 2h, { value: forever, description: 'No timeout' ],
          widget: suggestion-dropdown, label-collapsed: fail after, label-expanded: Fail if not successful within } ] } }`
   (as shown in the accompanying `vanillia-with-custom-widget.bom`);
diff --git a/ui-modules/app-inspector/app/components/stream/stream.directive.js b/ui-modules/app-inspector/app/components/stream/stream.directive.js
index 8db9b86..2196885 100644
--- a/ui-modules/app-inspector/app/components/stream/stream.directive.js
+++ b/ui-modules/app-inspector/app/components/stream/stream.directive.js
@@ -43,19 +43,56 @@
         $scope.autoUpdate = $scope.autoUpdate !== false;
         $scope.tail = $scope.tail !== false;
 
-        let pre = $element.find('pre');
+        // Content filtering features
+        $scope.filteredStream = [];
+        $scope.streamProcessedUpTo = 0;
+        $scope.otherLogLines = 0;
+        $scope.errorLogLines = 0;
+        $scope.debugLogLines = 0;
+        $scope.traceLogLines = 0;
+        $scope.warningLogLines = 0;
+        $scope.isDisplayOther = $scope.isDisplayOther !== false;
+        $scope.isDisplayError = $scope.isDisplayError !== false;
+        $scope.isDisplayDebug = $scope.isDisplayDebug !== false;
+        $scope.isDisplayTrace = $scope.isDisplayTrace !== false;
+        $scope.isDisplayWarning = $scope.isDisplayWarning !== false;
+        $scope.isFilterContent = isFilterContent;
+        $scope.isDisplayFormattedItem = isDisplayFormattedItem;
+        $scope.getFormattedItemLogLevel = getFormattedItemLogLevel;
+
+        // CLI XML features
+        $scope.cliXml = false;
+        $scope.cliXmlIdentified = false;
+        $scope.toggleCliXml = toggleCliXml;
+        $scope.isCliXmlSupported = isCliXmlSupported;
+        $scope.cliXmlVerificationRequired = isWinRmStream(); // CLI XML verification is required only when stream is WinRM
+
+        let autoScrollableElement = Array.from($element.find('pre')).filter(item => item.classList.contains('auto-scrollable'));
         let refreshFunction;
 
-        pre.on('mousewheel', () => {
-            $scope.$apply(() => {
-                $scope.tail = pre[0].scrollTop + pre[0].offsetHeight >= pre[0].scrollHeight;
-            });
+        // Set up cancellation of auto-scrolling on scrolling up.
+        autoScrollableElement.forEach(item => {
+            if (item.addEventListener)
+            {
+                let wheelHandler = () => {
+                    $scope.$apply(() => {
+                        $scope.tail = (item.scrollTop + item.offsetHeight) >= item.scrollHeight;
+                    });
+                }
+                // IE9, Chrome, Safari, Opera
+                item.addEventListener("mousewheel", wheelHandler, false);
+                // Firefox
+                item.addEventListener("DOMMouseScroll", wheelHandler, false);
+            }
         });
 
+        // Watch the 'tail' and auto-scroll down if auto-scroll is enabled.
         $scope.$watch('tail', () => {
-            $scope.$applyAsync(() => {
-                pre[0].scrollTop = pre[0].scrollHeight;
-            });
+            if ($scope.tail) {
+                $scope.$applyAsync(() => {
+                    autoScrollableElement.forEach(item => item.scrollTop = item.scrollHeight);
+                });
+            }
         });
 
         $scope.$watch('autoUpdate', ()=> {
@@ -67,9 +104,28 @@
         });
         $scope.$on('$destroy', cancelUpdate);
 
+        /**
+         * Updates the stream data.
+         */
         function updateStream() {
             activityApi.activityStream($scope.activityId, $scope.streamType).then((response)=> {
+
+                // 1. Try to identify CLI XML output.
+                const CLI_XML_HEADER_SIZE = 100; // estimated headers size in WinRM that can contain indication of CLI XML output
+                if ($scope.cliXmlVerificationRequired && typeof response.data === 'string' && response.data.length >= CLI_XML_HEADER_SIZE) {
+                    let header = response.data.slice(0, CLI_XML_HEADER_SIZE);
+                    if (header.includes('#< CLIXML') || header.includes('xmlns="http://schemas.microsoft.com/powershell')) {
+                        $scope.cliXmlIdentified = true;
+                    }
+                    $scope.cliXmlVerificationRequired = false; // perform verification once, if conditions match
+                }
+
+                // 2. Update the stream data holder in this directive.
                 $scope.stream = response.data;
+
+                // 3. Filter the content where relevant and display it.
+                updateFilteredContent();
+
             }).catch((error)=> {
                 if (error.data) {
                     $scope.error = error.data.message;
@@ -77,18 +133,146 @@
             }).finally(() => {
                 if ($scope.tail) {
                     $scope.$applyAsync(() => {
-                        pre[0].scrollTop = pre[0].scrollHeight;
+                        autoScrollableElement.forEach(item => item.scrollTop = item.scrollHeight);
                     });
                 }
             })
         }
 
+        /**
+         * Cancels the auto-update of the streamed content.
+         */
         function cancelUpdate() {
             if (refreshFunction) {
                 $interval.cancel(refreshFunction);
             }
         }
 
+        /**
+         * @returns {boolean} True if CLI XML is supported, and false otherwise. CLI XML is expected in WinRM stream only.
+         */
+        function isCliXmlSupported() {
+            return isWinRmStream() && $scope.cliXmlIdentified === true;
+        }
+
+        /**
+         * @returns {boolean} True if stream type is WinRM, and false otherwise.
+         */
+        function isWinRmStream() {
+            return $scope.streamType === 'winrm';
+        }
+
+        /**
+         * Switches content format to CLI XML and back.
+         */
+        function toggleCliXml() {
+            $scope.cliXml = !$scope.cliXml;
+            updateFilteredContent();
+        }
+
+        /**
+         * @returns {boolean} True if logging filter should be displayed, and false otherwise.
+         */
+        function isFilterContent() {
+            return isCliXmlSupported() && $scope.cliXml !== true;
+        }
+
+        /**
+         * @returns {string} Returns class name of the formatted item log level.
+         */
+        function getFormattedItemLogLevel(formattedItem) {
+            if (formattedItem.isWarning) {
+                return 'log-warning';
+            } else  if (formattedItem.isError) {
+                return 'log-error';
+            } if (formattedItem.isDebug) {
+                return 'log-debug';
+            }
+            return 'log-trace';
+        }
+
+        /**
+         * @returns {boolean} True if formatted item should be displayed, and false otherwise.
+         */
+        function isDisplayFormattedItem(formattedItem) {
+            return formattedItem.isWarning && $scope.isDisplayWarning
+                || formattedItem.isDebug && $scope.isDisplayDebug
+                || formattedItem.isError && $scope.isDisplayError
+                || formattedItem.isTrace && $scope.isDisplayTrace
+                || formattedItem.isOther && $scope.isDisplayOther;
+        }
+
+        /**
+         * Formats CLI XML output and displays it in 'filtered-stream-content' field.
+         */
+        function formatCliXmlContent() {
+
+            // Slice at index of last closing tag ending wth the new line
+            let streamTags = $scope.stream.match(/<\/(.*?)>\n/g);
+            let lastClosingTagIndex  = $scope.stream.lastIndexOf(streamTags[streamTags.length-1]);
+            let newCliXmlData = $scope.stream.slice($scope.streamProcessedUpTo, lastClosingTagIndex);
+            if (!newCliXmlData) {
+                return;
+            }
+
+            $scope.streamProcessedUpTo += newCliXmlData.length;
+
+            newCliXmlData.split(/\n/g).forEach(item => {
+                let formattedItem = {
+                    id: ($scope.filteredStream.length), // ng-repeat requires unique items, array length fits the bill
+                    text: item,
+                    isOther: false,
+                    isError: false,
+                    isDebug: false,
+                    isTrace: false,
+                    isWarning: false
+                };
+
+                if (/<s s="warning">/i.test(item)) {
+                    $scope.warningLogLines++;
+                    formattedItem.isWarning = true;
+                } else if (/<s s="debug">/i.test(item)) {
+                    $scope.debugLogLines++;
+                    formattedItem.isDebug = true;
+                } else if (/<s s="verbose">/i.test(item)) {
+                    $scope.traceLogLines++;
+                    formattedItem.isTrace = true;
+                } else if (/<s s="error">/i.test(item)) {
+                    $scope.errorLogLines++;
+                    formattedItem.isError = true;
+                } else {
+                    $scope.otherLogLines++;
+                    formattedItem.isOther = true;
+                }
+
+                // Remove CLI XML string tags for know log levels
+                if (!formattedItem.isOther) {
+                    formattedItem.text = item.replace(/<s s="(.*?)">|\t/gi, '');
+                }
+
+                // Remove CLI XML markers, newlines and replace tabs with spaces
+                formattedItem.text = formattedItem.text.replace(/<\/s>|_x000[a-z0-9]_|\n/gi, '').replace(/\t/g,' ');
+
+                // Push update item and let ng-repeat update the content
+                $scope.filteredStream.push(formattedItem);
+            });
+        }
+
+        /**
+         * Filters stream content as per selected filters if filtering is enabled, e.g. display/hide warnings or errors.
+         */
+        function updateFilteredContent() {
+
+            if (!isFilterContent()) {
+                return;
+            }
+
+            // Format new CLI XML content
+            if (isCliXmlSupported()) {
+                formatCliXmlContent();
+            }
+        }
+
         updateStream();
     }
 }
diff --git a/ui-modules/app-inspector/app/components/stream/stream.less b/ui-modules/app-inspector/app/components/stream/stream.less
index 8f43f73..f505b92 100644
--- a/ui-modules/app-inspector/app/components/stream/stream.less
+++ b/ui-modules/app-inspector/app/components/stream/stream.less
@@ -19,22 +19,42 @@
 stream {
   display: block;
   position: relative;
+  @warning-log-color: @brand-warning;
+  @error-log-color: @brand-danger;
+  @debug-log-color: @brand-info;
+  @trace-log-color: @gray-lighter;
 
   pre {
     min-height: 4em;
     background: @gray;
     color:  @gray-lighter;
     .monospace();
-    padding: 0.8em;
-    padding-bottom: 1.2em;
+    padding: 0.8em 0.8em 1.2em;
+
+    .log-section {
+      all: revert;
+      margin: 0;
+      .monospace();
+      &.log-warning {
+        color: @warning-log-color;
+      }
+      &.log-error {
+        color: @error-log-color;
+      }
+      &.log-debug {
+        color: @debug-log-color;
+      }
+      &.log-trace {
+        color: @trace-log-color;
+      }
+    }
   }
 
   .log-actions {
     position: absolute;
     top: 0;
     right: 0;
-    padding: 1em;
-    padding-top: 0.75em;
+    padding: 0.75em 1em 1em;
   }
 
   .log-action {
@@ -49,25 +69,50 @@
     &:hover .fa  {
       color: lighten(desaturate(@base-color, 40%), 10%);
     }
-    &.active .fa {
-      color: @base-color
+    &.active {
+      .fa {
+        color: @base-color;
+      }
+      .fa-exclamation-triangle {
+        color: @error-log-color;
+      }
+      .fa-bolt {
+        color: @warning-log-color;
+      }
+      .fa-bug {
+        color: @debug-log-color;
+      }
+      .fa-bullhorn {
+        color: @trace-log-color;
+      }
+      .fa-question {
+        color: @trace-log-color;
+      }
     }
-    &.active:hover .fa {
-      color: desaturate(@base-color, 20%);
+    &.active:hover {
+      .fa {
+        color: desaturate(@base-color, 20%);
+      }
+      .fa-exclamation-triangle {
+        color: desaturate(@error-log-color, 20%);
+      }
+      .fa-bolt {
+        color: desaturate(@warning-log-color, 20%);
+      }
+      .fa-bug {
+        color: desaturate(@debug-log-color, 20%);
+      }
+      .fa-bullhorn {
+        color: desaturate(@trace-log-color, 20%);
+      }
+      .fa-question {
+        color: desaturate(@trace-log-color, 20%);
+      }
     }
   }
   
   .fa-arrow-circle-o-down {
     margin-top: 1px;
   }
-
-  .log-autoupdate {
-    .fa {
-      transform: rotate(0);
-    }
-    &.active .fa {
-      transform: rotate(180deg) translate(0,1px);
-    }
-  }
 }
 
diff --git a/ui-modules/app-inspector/app/components/stream/stream.template.html b/ui-modules/app-inspector/app/components/stream/stream.template.html
index 0b2e1e1..0322874 100644
--- a/ui-modules/app-inspector/app/components/stream/stream.template.html
+++ b/ui-modules/app-inspector/app/components/stream/stream.template.html
@@ -19,14 +19,38 @@
 <loading-state error="error" ng-if="stream === undefined"></loading-state>
 
 <div ng-show="stream.length >= 0">
-  <pre ng-show="stream.length > 0">{{stream}}</pre>
+  <pre ng-show="stream.length > 0 && !isFilterContent()" class="auto-scrollable">{{stream}}</pre>
+  <pre ng-show="stream.length > 0 && isFilterContent()" class="auto-scrollable"><pre ng-repeat="item in filteredStream track by item.id" ng-show="isDisplayFormattedItem(item)" class="log-section" ng-class="getFormattedItemLogLevel(item)">{{item.text}}</pre><p ng-show="!isDisplayTrace && !isDisplayDebug && !isDisplayWarning && !isDisplayError && !isDisplayOther" class="text-center"><i>(select filter)</i></p></pre>
   <pre ng-show="stream.length == 0" class="text-center"><i>(no content)</i></pre>
-
   <div class="log-actions">
-    <span class="log-autoupdate log-action" ng-click="autoUpdate = !autoUpdate" ng-class="{'active': autoUpdate}" 
-            uib-tooltip="{{ autoUpdate ? 'Disable' : 'Enable' }} auto-update" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
-        <i class="fa fa-refresh"></i></span>
-    <span class="log-tail log-action" ng-click="tail = !tail" ng-class="{'active': tail}" 
+
+    <!-- Content filtering -->
+    <span class="log-action" ng-click="isDisplayOther = !isDisplayOther" ng-class="{'active': isDisplayOther}" ng-show="isFilterContent()"
+          uib-tooltip="{{ isDisplayOther ? 'Hide' : 'Show' }} other ({{otherLogLines}} lines)" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
+        <i class="fa fa-question"></i></span>
+    <span class="log-action" ng-click="isDisplayTrace = !isDisplayTrace" ng-class="{'active': isDisplayTrace}" ng-show="isFilterContent()"
+          uib-tooltip="{{ isDisplayTrace ? 'Hide' : 'Show' }} trace ({{traceLogLines}} lines)" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
+        <i class="fa fa-bullhorn"></i></span>
+    <span class="log-action" ng-click="isDisplayDebug = !isDisplayDebug" ng-class="{'active': isDisplayDebug}" ng-show="isFilterContent()"
+          uib-tooltip="{{ isDisplayDebug ? 'Hide' : 'Show' }} debug ({{debugLogLines}} lines)" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
+        <i class="fa fa-bug"></i></span>
+    <span class="log-action" ng-click="isDisplayWarning = !isDisplayWarning" ng-class="{'active': isDisplayWarning}" ng-show="isFilterContent()"
+          uib-tooltip="{{ isDisplayWarning ? 'Hide' : 'Show' }} warnings ({{warningLogLines}} lines)" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
+        <i class="fa fa-bolt"></i></span>
+    <span class="log-action" ng-click="isDisplayError = !isDisplayError" ng-class="{'active': isDisplayError}" ng-show="isFilterContent()"
+          uib-tooltip="{{ isDisplayError ? 'Hide' : 'Show' }} errors ({{errorLogLines}} lines)" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
+        <i class="fa fa-exclamation-triangle"></i></span>
+
+    <!-- CLI XML output mode -->
+    <span class="log-action" ng-click="toggleCliXml()" ng-class="{'active': cliXml}" ng-show="isCliXmlSupported()"
+          uib-tooltip="Display {{ cliXml ? 'formatted output' : 'CLI XML' }}" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
+        <i class="fa fa-code"></i></span>
+
+    <!-- Auto-update and auto-scroll -->
+    <span class="log-action" ng-click="autoUpdate = !autoUpdate" ng-class="{'active': autoUpdate}"
+          uib-tooltip="{{ autoUpdate ? 'Disable' : 'Enable' }} auto-update" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
+        <i class="fa fa-refresh" ng-class="autoUpdate ? 'fa-spin' : ''"></i></span>
+    <span class="log-tail log-action" ng-click="tail = !tail" ng-class="{'active': tail}"
             uib-tooltip="{{ tail ? 'Disable' : 'Enable' }} auto-scroll" tooltip-placement="top" tooltip-popup-delay="500" tooltip-append-to-body="true">
         <i class="fa fa-arrow-circle-o-down "></i></span>
   </div>
diff --git a/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js b/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js
index f089495..f8f7e2b 100644
--- a/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js
+++ b/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js
@@ -116,6 +116,14 @@
                 otherMap[name] = s;
             }
         }
+
+        // Do not display streams that are not initialized
+        for (let name in knownMap) {
+            if (knownMap[name] === null || knownMap[name] === undefined) {
+                delete knownMap[name];
+            }
+        }
+
         $scope.streamsById = Object.assign({}, knownMap, otherMap);
         return Object.keys($scope.streamsById);
     };