We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Sigma analyzer creates saved search and story even with 0 results
The Sigma analyzer will create a story and saved search even if there are no results from the analyzer.

Fix: Only create saved search and story if there was any events tagged.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `timesketch/lib/analyzers/sigma_tagger.py`
Content:
```
1 """Index analyzer plugin for sigma."""
2 from __future__ import unicode_literals
3 
4 import logging
5 import time
6 import elasticsearch
7 
8 from flask import current_app
9 
10 from timesketch.lib.analyzers import utils
11 
12 from timesketch.lib.analyzers import interface
13 from timesketch.lib.analyzers import manager
14 import timesketch.lib.sigma_util as ts_sigma_lib
15 
16 
17 logger = logging.getLogger('timesketch.analyzers.sigma_tagger')
18 
19 
20 class SigmaPlugin(interface.BaseAnalyzer):
21     """Analyzer for Sigma."""
22 
23     NAME = 'sigma'
24     DISPLAY_NAME = 'Sigma'
25     DESCRIPTION = 'Run pre-defined Sigma rules and tag matching events'
26 
27     def run_sigma_rule(self, query, rule_name, tag_list = None):
28         """Runs a sigma rule and applies the appropriate tags.
29 
30         Args:
31             query: elastic search query for events to tag.
32             rule_name: rule_name to apply to matching events.
33             tag_list: a list of additional tags to be added to the event(s)
34 
35         Returns:
36             int: number of events tagged.
37         """
38         return_fields = []
39         tagged_events_counter = 0
40         events = self.event_stream(
41             query_string=query, return_fields=return_fields)
42         for event in events:
43             ts_sigma_rules = event.source.get('ts_sigma_rule', [])
44             ts_sigma_rules.append(rule_name)
45             event.add_attributes({'ts_sigma_rule': list(set(ts_sigma_rules))})
46             ts_ttp = event.source.get('ts_ttp', [])
47             for tag in tag_list:
48                 # special handling for sigma tags that TS considers TTPS
49                 # https://car.mitre.org and https://attack.mitre.org
50                 if tag.startswith(('attack.', 'car.')):
51                     ts_ttp.append(tag)
52                     tag_list.remove(tag)
53             event.add_tags(tag_list)
54             if len(ts_ttp) > 0:
55                 event.add_attributes({'ts_ttp': list(set(ts_ttp))})
56             event.commit()
57             tagged_events_counter += 1
58         return tagged_events_counter
59 
60     def run(self):
61         """Entry point for the analyzer.
62 
63         Returns:
64             String with summary of the analyzer result.
65         """
66 
67         tags_applied = {}
68         sigma_rule_counter = 0
69         sigma_rules = ts_sigma_lib.get_all_sigma_rules()
70         if sigma_rules is None:
71             logger.error('No  Sigma rules found. Check SIGMA_RULES_FOLDERS')
72         problem_strings = []
73         output_strings = []
74 
75         for rule in sigma_rules:
76             tags_applied[rule.get('file_name')] = 0
77             try:
78                 sigma_rule_counter += 1
79                 tagged_events_counter = self.run_sigma_rule(
80                     rule.get('es_query'), rule.get('file_name'),
81                     tag_list=rule.get('tags'))
82                 tags_applied[rule.get('file_name')] += tagged_events_counter
83                 if sigma_rule_counter % 10 == 0:
84                     logger.debug('Rule {0:d}/{1:d}'.format(
85                         sigma_rule_counter, len(sigma_rules)))
86             except elasticsearch.TransportError as e:
87                 logger.error(
88                     'Timeout executing search for {0:s}: '
89                     '{1!s} waiting for 10 seconds'.format(
90                         rule.get('file_name'), e), exc_info=True)
91                 # this is caused by too many ES queries in short time range
92                 # TODO: https://github.com/google/timesketch/issues/1782
93                 sleep_time = current_app.config.get(
94                     'SIGMA_TAG_DELAY', 15)
95                 time.sleep(sleep_time)
96                 tagged_events_counter = self.run_sigma_rule(
97                     rule.get('es_query'), rule.get('file_name'),
98                     tag_list=rule.get('tags'))
99                 tags_applied[rule.get('file_name')] += tagged_events_counter
100             # Wide exception handling since there are multiple exceptions that
101             # can be raised by the underlying sigma library.
102             except: # pylint: disable=bare-except
103                 logger.error(
104                     'Problem with rule in file {0:s}: '.format(
105                         rule.get('file_name')), exc_info=True)
106                 problem_strings.append('* {0:s}'.format(
107                     rule.get('file_name')))
108                 continue
109 
110         total_tagged_events = sum(tags_applied.values())
111         output_strings.append('Applied {0:d} tags'.format(total_tagged_events))
112 
113         if sigma_rule_counter > 0:
114             self.add_sigma_match_view(sigma_rule_counter)
115 
116         if len(problem_strings) > 0:
117             output_strings.append('Problematic rules:')
118             output_strings.extend(problem_strings)
119 
120         return '\n'.join(output_strings)
121 
122     def add_sigma_match_view(self, sigma_rule_counter):
123         """Adds a view with the top 20 matching rules.
124 
125         Args:
126             sigma_rule_counter number of matching rules
127 
128         """
129         view = self.sketch.add_view(
130             view_name='Sigma Rule matches', analyzer_name=self.NAME,
131             query_string='tag:"sigma*"')
132         agg_params = {
133             'field': 'tag',
134             'limit': 20,
135             'index': [self.timeline_id],
136         }
137         agg_obj = self.sketch.add_aggregation(
138             name='Top 20 Sigma tags', agg_name='field_bucket',
139             agg_params=agg_params, view_id=view.id, chart_type='hbarchart',
140             description='Created by the Sigma analyzer')
141 
142         story = self.sketch.add_story('Sigma Rule hits')
143         story.add_text(
144             utils.SIGMA_STORY_HEADER, skip_if_exists=True)
145 
146         story.add_text(
147             '## Sigma Analyzer.\n\nThe Sigma '
148             'analyzer takes Events and matches them with Sigma rules.'
149             'In this timeline the analyzer discovered {0:d} '
150             'Sigma tags.\n\nThis is a summary of '
151             'it\'s findings.'.format(sigma_rule_counter))
152         story.add_text(
153             'The top 20 most commonly discovered tags were:')
154         story.add_aggregation(agg_obj)
155         story.add_text(
156             'And an overview of all the discovered search terms:')
157         story.add_view(view)
158 
159 
160 class RulesSigmaPlugin(SigmaPlugin):
161     """Sigma plugin to run rules."""
162 
163     NAME = 'sigma'
164 
165 manager.AnalysisManager.register_analyzer(RulesSigmaPlugin)
166
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/timesketch/lib/analyzers/sigma_tagger.py b/timesketch/lib/analyzers/sigma_tagger.py
--- a/timesketch/lib/analyzers/sigma_tagger.py
+++ b/timesketch/lib/analyzers/sigma_tagger.py
@@ -110,7 +110,7 @@
         total_tagged_events = sum(tags_applied.values())
         output_strings.append('Applied {0:d} tags'.format(total_tagged_events))
 
-        if sigma_rule_counter > 0:
+        if total_tagged_events > 0:
             self.add_sigma_match_view(sigma_rule_counter)
 
         if len(problem_strings) > 0:

{"golden_diff": "diff --git a/timesketch/lib/analyzers/sigma_tagger.py b/timesketch/lib/analyzers/sigma_tagger.py\n--- a/timesketch/lib/analyzers/sigma_tagger.py\n+++ b/timesketch/lib/analyzers/sigma_tagger.py\n@@ -110,7 +110,7 @@\n         total_tagged_events = sum(tags_applied.values())\n         output_strings.append('Applied {0:d} tags'.format(total_tagged_events))\n \n-        if sigma_rule_counter > 0:\n+        if total_tagged_events > 0:\n             self.add_sigma_match_view(sigma_rule_counter)\n \n         if len(problem_strings) > 0:\n", "issue": "Sigma analyzer creates saved search and story even with 0 results\nThe Sigma analyzer will create a story and saved search even if there are no results from the analyzer.\r\n\r\nFix: Only create saved search and story if there was any events tagged.\n", "before_files": [{"content": "\"\"\"Index analyzer plugin for sigma.\"\"\"\nfrom __future__ import unicode_literals\n\nimport logging\nimport time\nimport elasticsearch\n\nfrom flask import current_app\n\nfrom timesketch.lib.analyzers import utils\n\nfrom timesketch.lib.analyzers import interface\nfrom timesketch.lib.analyzers import manager\nimport timesketch.lib.sigma_util as ts_sigma_lib\n\n\nlogger = logging.getLogger('timesketch.analyzers.sigma_tagger')\n\n\nclass SigmaPlugin(interface.BaseAnalyzer):\n    \"\"\"Analyzer for Sigma.\"\"\"\n\n    NAME = 'sigma'\n    DISPLAY_NAME = 'Sigma'\n    DESCRIPTION = 'Run pre-defined Sigma rules and tag matching events'\n\n    def run_sigma_rule(self, query, rule_name, tag_list = None):\n        \"\"\"Runs a sigma rule and applies the appropriate tags.\n\n        Args:\n            query: elastic search query for events to tag.\n            rule_name: rule_name to apply to matching events.\n            tag_list: a list of additional tags to be added to the event(s)\n\n        Returns:\n            int: number of events tagged.\n        \"\"\"\n        return_fields = []\n        tagged_events_counter = 0\n        events = self.event_stream(\n            query_string=query, return_fields=return_fields)\n        for event in events:\n            ts_sigma_rules = event.source.get('ts_sigma_rule', [])\n            ts_sigma_rules.append(rule_name)\n            event.add_attributes({'ts_sigma_rule': list(set(ts_sigma_rules))})\n            ts_ttp = event.source.get('ts_ttp', [])\n            for tag in tag_list:\n                # special handling for sigma tags that TS considers TTPS\n                # https://car.mitre.org and https://attack.mitre.org\n                if tag.startswith(('attack.', 'car.')):\n                    ts_ttp.append(tag)\n                    tag_list.remove(tag)\n            event.add_tags(tag_list)\n            if len(ts_ttp) > 0:\n                event.add_attributes({'ts_ttp': list(set(ts_ttp))})\n            event.commit()\n            tagged_events_counter += 1\n        return tagged_events_counter\n\n    def run(self):\n        \"\"\"Entry point for the analyzer.\n\n        Returns:\n            String with summary of the analyzer result.\n        \"\"\"\n\n        tags_applied = {}\n        sigma_rule_counter = 0\n        sigma_rules = ts_sigma_lib.get_all_sigma_rules()\n        if sigma_rules is None:\n            logger.error('No  Sigma rules found. Check SIGMA_RULES_FOLDERS')\n        problem_strings = []\n        output_strings = []\n\n        for rule in sigma_rules:\n            tags_applied[rule.get('file_name')] = 0\n            try:\n                sigma_rule_counter += 1\n                tagged_events_counter = self.run_sigma_rule(\n                    rule.get('es_query'), rule.get('file_name'),\n                    tag_list=rule.get('tags'))\n                tags_applied[rule.get('file_name')] += tagged_events_counter\n                if sigma_rule_counter % 10 == 0:\n                    logger.debug('Rule {0:d}/{1:d}'.format(\n                        sigma_rule_counter, len(sigma_rules)))\n            except elasticsearch.TransportError as e:\n                logger.error(\n                    'Timeout executing search for {0:s}: '\n                    '{1!s} waiting for 10 seconds'.format(\n                        rule.get('file_name'), e), exc_info=True)\n                # this is caused by too many ES queries in short time range\n                # TODO: https://github.com/google/timesketch/issues/1782\n                sleep_time = current_app.config.get(\n                    'SIGMA_TAG_DELAY', 15)\n                time.sleep(sleep_time)\n                tagged_events_counter = self.run_sigma_rule(\n                    rule.get('es_query'), rule.get('file_name'),\n                    tag_list=rule.get('tags'))\n                tags_applied[rule.get('file_name')] += tagged_events_counter\n            # Wide exception handling since there are multiple exceptions that\n            # can be raised by the underlying sigma library.\n            except: # pylint: disable=bare-except\n                logger.error(\n                    'Problem with rule in file {0:s}: '.format(\n                        rule.get('file_name')), exc_info=True)\n                problem_strings.append('* {0:s}'.format(\n                    rule.get('file_name')))\n                continue\n\n        total_tagged_events = sum(tags_applied.values())\n        output_strings.append('Applied {0:d} tags'.format(total_tagged_events))\n\n        if sigma_rule_counter > 0:\n            self.add_sigma_match_view(sigma_rule_counter)\n\n        if len(problem_strings) > 0:\n            output_strings.append('Problematic rules:')\n            output_strings.extend(problem_strings)\n\n        return '\\n'.join(output_strings)\n\n    def add_sigma_match_view(self, sigma_rule_counter):\n        \"\"\"Adds a view with the top 20 matching rules.\n\n        Args:\n            sigma_rule_counter number of matching rules\n\n        \"\"\"\n        view = self.sketch.add_view(\n            view_name='Sigma Rule matches', analyzer_name=self.NAME,\n            query_string='tag:\"sigma*\"')\n        agg_params = {\n            'field': 'tag',\n            'limit': 20,\n            'index': [self.timeline_id],\n        }\n        agg_obj = self.sketch.add_aggregation(\n            name='Top 20 Sigma tags', agg_name='field_bucket',\n            agg_params=agg_params, view_id=view.id, chart_type='hbarchart',\n            description='Created by the Sigma analyzer')\n\n        story = self.sketch.add_story('Sigma Rule hits')\n        story.add_text(\n            utils.SIGMA_STORY_HEADER, skip_if_exists=True)\n\n        story.add_text(\n            '## Sigma Analyzer.\\n\\nThe Sigma '\n            'analyzer takes Events and matches them with Sigma rules.'\n            'In this timeline the analyzer discovered {0:d} '\n            'Sigma tags.\\n\\nThis is a summary of '\n            'it\\'s findings.'.format(sigma_rule_counter))\n        story.add_text(\n            'The top 20 most commonly discovered tags were:')\n        story.add_aggregation(agg_obj)\n        story.add_text(\n            'And an overview of all the discovered search terms:')\n        story.add_view(view)\n\n\nclass RulesSigmaPlugin(SigmaPlugin):\n    \"\"\"Sigma plugin to run rules.\"\"\"\n\n    NAME = 'sigma'\n\nmanager.AnalysisManager.register_analyzer(RulesSigmaPlugin)\n", "path": "timesketch/lib/analyzers/sigma_tagger.py"}], "after_files": [{"content": "\"\"\"Index analyzer plugin for sigma.\"\"\"\nfrom __future__ import unicode_literals\n\nimport logging\nimport time\nimport elasticsearch\n\nfrom flask import current_app\n\nfrom timesketch.lib.analyzers import utils\n\nfrom timesketch.lib.analyzers import interface\nfrom timesketch.lib.analyzers import manager\nimport timesketch.lib.sigma_util as ts_sigma_lib\n\n\nlogger = logging.getLogger('timesketch.analyzers.sigma_tagger')\n\n\nclass SigmaPlugin(interface.BaseAnalyzer):\n    \"\"\"Analyzer for Sigma.\"\"\"\n\n    NAME = 'sigma'\n    DISPLAY_NAME = 'Sigma'\n    DESCRIPTION = 'Run pre-defined Sigma rules and tag matching events'\n\n    def run_sigma_rule(self, query, rule_name, tag_list = None):\n        \"\"\"Runs a sigma rule and applies the appropriate tags.\n\n        Args:\n            query: elastic search query for events to tag.\n            rule_name: rule_name to apply to matching events.\n            tag_list: a list of additional tags to be added to the event(s)\n\n        Returns:\n            int: number of events tagged.\n        \"\"\"\n        return_fields = []\n        tagged_events_counter = 0\n        events = self.event_stream(\n            query_string=query, return_fields=return_fields)\n        for event in events:\n            ts_sigma_rules = event.source.get('ts_sigma_rule', [])\n            ts_sigma_rules.append(rule_name)\n            event.add_attributes({'ts_sigma_rule': list(set(ts_sigma_rules))})\n            ts_ttp = event.source.get('ts_ttp', [])\n            for tag in tag_list:\n                # special handling for sigma tags that TS considers TTPS\n                # https://car.mitre.org and https://attack.mitre.org\n                if tag.startswith(('attack.', 'car.')):\n                    ts_ttp.append(tag)\n                    tag_list.remove(tag)\n            event.add_tags(tag_list)\n            if len(ts_ttp) > 0:\n                event.add_attributes({'ts_ttp': list(set(ts_ttp))})\n            event.commit()\n            tagged_events_counter += 1\n        return tagged_events_counter\n\n    def run(self):\n        \"\"\"Entry point for the analyzer.\n\n        Returns:\n            String with summary of the analyzer result.\n        \"\"\"\n\n        tags_applied = {}\n        sigma_rule_counter = 0\n        sigma_rules = ts_sigma_lib.get_all_sigma_rules()\n        if sigma_rules is None:\n            logger.error('No  Sigma rules found. Check SIGMA_RULES_FOLDERS')\n        problem_strings = []\n        output_strings = []\n\n        for rule in sigma_rules:\n            tags_applied[rule.get('file_name')] = 0\n            try:\n                sigma_rule_counter += 1\n                tagged_events_counter = self.run_sigma_rule(\n                    rule.get('es_query'), rule.get('file_name'),\n                    tag_list=rule.get('tags'))\n                tags_applied[rule.get('file_name')] += tagged_events_counter\n                if sigma_rule_counter % 10 == 0:\n                    logger.debug('Rule {0:d}/{1:d}'.format(\n                        sigma_rule_counter, len(sigma_rules)))\n            except elasticsearch.TransportError as e:\n                logger.error(\n                    'Timeout executing search for {0:s}: '\n                    '{1!s} waiting for 10 seconds'.format(\n                        rule.get('file_name'), e), exc_info=True)\n                # this is caused by too many ES queries in short time range\n                # TODO: https://github.com/google/timesketch/issues/1782\n                sleep_time = current_app.config.get(\n                    'SIGMA_TAG_DELAY', 15)\n                time.sleep(sleep_time)\n                tagged_events_counter = self.run_sigma_rule(\n                    rule.get('es_query'), rule.get('file_name'),\n                    tag_list=rule.get('tags'))\n                tags_applied[rule.get('file_name')] += tagged_events_counter\n            # Wide exception handling since there are multiple exceptions that\n            # can be raised by the underlying sigma library.\n            except: # pylint: disable=bare-except\n                logger.error(\n                    'Problem with rule in file {0:s}: '.format(\n                        rule.get('file_name')), exc_info=True)\n                problem_strings.append('* {0:s}'.format(\n                    rule.get('file_name')))\n                continue\n\n        total_tagged_events = sum(tags_applied.values())\n        output_strings.append('Applied {0:d} tags'.format(total_tagged_events))\n\n        if total_tagged_events > 0:\n            self.add_sigma_match_view(sigma_rule_counter)\n\n        if len(problem_strings) > 0:\n            output_strings.append('Problematic rules:')\n            output_strings.extend(problem_strings)\n\n        return '\\n'.join(output_strings)\n\n    def add_sigma_match_view(self, sigma_rule_counter):\n        \"\"\"Adds a view with the top 20 matching rules.\n\n        Args:\n            sigma_rule_counter number of matching rules\n\n        \"\"\"\n        view = self.sketch.add_view(\n            view_name='Sigma Rule matches', analyzer_name=self.NAME,\n            query_string='tag:\"sigma*\"')\n        agg_params = {\n            'field': 'tag',\n            'limit': 20,\n            'index': [self.timeline_id],\n        }\n        agg_obj = self.sketch.add_aggregation(\n            name='Top 20 Sigma tags', agg_name='field_bucket',\n            agg_params=agg_params, view_id=view.id, chart_type='hbarchart',\n            description='Created by the Sigma analyzer')\n\n        story = self.sketch.add_story('Sigma Rule hits')\n        story.add_text(\n            utils.SIGMA_STORY_HEADER, skip_if_exists=True)\n\n        story.add_text(\n            '## Sigma Analyzer.\\n\\nThe Sigma '\n            'analyzer takes Events and matches them with Sigma rules.'\n            'In this timeline the analyzer discovered {0:d} '\n            'Sigma tags.\\n\\nThis is a summary of '\n            'it\\'s findings.'.format(sigma_rule_counter))\n        story.add_text(\n            'The top 20 most commonly discovered tags were:')\n        story.add_aggregation(agg_obj)\n        story.add_text(\n            'And an overview of all the discovered search terms:')\n        story.add_view(view)\n\n\nclass RulesSigmaPlugin(SigmaPlugin):\n    \"\"\"Sigma plugin to run rules.\"\"\"\n\n    NAME = 'sigma'\n\nmanager.AnalysisManager.register_analyzer(RulesSigmaPlugin)\n", "path": "timesketch/lib/analyzers/sigma_tagger.py"}]}