Skip to content

Commit 5f001b4

Browse files
kiddinnberggren
authored andcommitted
Added dynamic form definition for the feature extraction analyzer. (#1055)
* Adding dynamic form definition for the feature extraction analyzer. * Making changes to dynamic forms * Removing UI bit flip * Minor linter * Adding a bit more assistance into the sketch object for the API client.
1 parent 48d204a commit 5f001b4

File tree

3 files changed

+114
-3
lines changed

3 files changed

+114
-3
lines changed

api_client/python/timesketch_api_client/sketch.py

+11
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,17 @@ def run_analyzer(
439439
resource_url = '{0:s}/sketches/{1:d}/analyzer/'.format(
440440
self.api.api_root, self.id)
441441

442+
# The analyzer_kwargs is expected to be a dict with the key
443+
# being the analyzer name, and the value being the key/value dict
444+
# with parameters for the analyzer.
445+
if analyzer_kwargs:
446+
if not isinstance(analyzer_kwargs, dict):
447+
return (
448+
'Unable to run analyzer, analyzer kwargs needs to be a '
449+
'dict')
450+
if analyzer_name not in analyzer_kwargs:
451+
analyzer_kwargs = {analyzer_name: analyzer_kwargs}
452+
442453
if timeline_name:
443454
sketch = self.lazyload_data()
444455
timelines = []

timesketch/lib/analyzers/feature_extraction.py

+100-3
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,129 @@
1111
from timesketch.lib.analyzers import manager
1212

1313

14+
RE_FLAGS = [
15+
're.ASCII',
16+
're.IGNORECASE',
17+
're.LOCALE',
18+
're.MULTILINE',
19+
're.DOTALL',
20+
're.VERBOSE',
21+
]
22+
23+
1424
class FeatureExtractionSketchPlugin(interface.BaseSketchAnalyzer):
1525
"""Sketch analyzer for FeatureExtraction."""
1626

1727
NAME = 'feature_extraction'
1828

1929
CONFIG_FILE = 'features.yaml'
2030

21-
def __init__(self, index_name, sketch_id):
31+
FORM_FIELDS = [
32+
{
33+
'name': 'query_string',
34+
'type': 'ts-dynamic-form-text-input',
35+
'label': 'The filter query to narrow down the result set',
36+
'placeholder': 'Query',
37+
'default_value': ''
38+
},
39+
{
40+
'name': 'query_dsl',
41+
'type': 'ts-dynamic-form-text-input',
42+
'label': 'The filter query DSL to narrow down the result',
43+
'placeholder': 'Query DSL',
44+
'default_value': ''
45+
},
46+
{
47+
'name': 'attribute',
48+
'type': 'ts-dynamic-form-text-input',
49+
'label': 'Name of the field to apply regular expression against',
50+
'placeholder': 'Field Name',
51+
'default_value': ''
52+
},
53+
{
54+
'name': 'store_as',
55+
'type': 'ts-dynamic-form-text-input',
56+
'label': 'Name of the field to store the extracted results in',
57+
'placeholder': 'Store results as field name',
58+
'default_value': ''
59+
},
60+
{
61+
'name': 're',
62+
'type': 'ts-dynamic-form-text-input',
63+
'label': 'The regular expression to extract data from field',
64+
'placeholder': 'Regular Expression',
65+
'default_value': ''
66+
},
67+
{
68+
'name': 're_flags',
69+
'type': 'ts-dynamic-form-multi-select-input',
70+
'label': 'List of flags to pass to the regular expression',
71+
'placeholder': 'Regular Expression flags',
72+
'default_value': [],
73+
'options': RE_FLAGS,
74+
'optional': True,
75+
},
76+
{
77+
'name': 'emojis',
78+
'type': 'ts-dynamic-form-multi-select-input',
79+
'label': 'List of emojis to add to events with matches',
80+
'placeholder': 'Emojis to add to events',
81+
'default_value': [],
82+
'options': [x.code for x in emojis.EMOJI_MAP.values()],
83+
'options-label': [
84+
'{0:s} - {1:s}'.format(
85+
x, y.help) for x, y in emojis.EMOJI_MAP.items()],
86+
'optional': True,
87+
},
88+
{
89+
'name': 'tags',
90+
'type': 'ts-dynamic-form-text-input',
91+
'label': 'Tag to add to events with matches',
92+
'placeholder': 'Tag to add to events',
93+
'default_value': '',
94+
'optional': True,
95+
},
96+
{
97+
'name': 'create_view',
98+
'type': 'ts-dynamic-form-boolean',
99+
'label': 'Should a view be created if there is a match',
100+
'placeholder': 'Create a view',
101+
'default_value': False,
102+
'optional': True,
103+
},
104+
{
105+
'name': 'aggregate',
106+
'type': 'ts-dynamic-form-boolean',
107+
'label': 'Should results be aggregated if there is a match',
108+
'placeholder': 'Aggregate results',
109+
'default_value': False,
110+
'optional': True,
111+
},
112+
]
113+
114+
115+
def __init__(self, index_name, sketch_id, config=None):
22116
"""Initialize The Sketch Analyzer.
23117
24118
Args:
25119
index_name: Elasticsearch index name
26120
sketch_id: Sketch ID
121+
config: Optional dict that contains the configuration for the
122+
analyzer. If not provided, the default YAML file will be
123+
loaded up.
27124
"""
28125
self.index_name = index_name
29126
super(FeatureExtractionSketchPlugin, self).__init__(
30127
index_name, sketch_id)
128+
self._config = config
31129

32130
def run(self):
33131
"""Entry point for the analyzer.
34132
35133
Returns:
36134
String with summary of the analyzer result.
37135
"""
38-
config = interface.get_yaml_config(self.CONFIG_FILE)
39-
136+
config = self._config or interface.get_yaml_config(self.CONFIG_FILE)
40137
if not config:
41138
return 'Unable to parse the config file.'
42139

timesketch/lib/analyzers/interface.py

+3
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,9 @@ class BaseIndexAnalyzer(object):
361361
# the indexer names.
362362
DEPENDENCIES = frozenset()
363363

364+
# Used as hints to the frontend UI in order to render input forms.
365+
FORM_FIELDS = []
366+
364367
def __init__(self, index_name):
365368
"""Initialize the analyzer object.
366369

0 commit comments

Comments
 (0)