Skip to content

Commit 8f9a1c5

Browse files
author
Li Wu
authored
Release 6.5.2 (#303)
* Fix structlog dependency for app (#280) * zipfile fix (#284) * Fix bug 286 random token replacement (#287) * Fix bug 286 random token replacement * Change perdayvolume generator logic to get random token value replacement * Versioning scheme (#278) * [global] perDayVolume (#288) * exclude global from perDayVolume assignment * Address comment * Fix security vulnerability issue (#289) * Fix custom plugin stale docs (#290) * Server fix (#293) * Flag added * server fix for count and env clean * Fix bug 285 (#297) * Add syslogAddHeader config directive (#296) * Add syslog header to event in syslog mode * timezone setting bugfix #249 * Using multiprocess pool to address the OOM issue (#301) * Using multiprocess pool to address the OOM issue * Fix test case fail * Remove workerQueue unfinished tasks (#302) * Bumped version to 6.5.2
1 parent 0a9c727 commit 8f9a1c5

23 files changed

+296
-180
lines changed

docs/CONFIGURE.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,10 @@ specifically be supported by all plugins. Plugins that write to files like spool
382382
* Set event sourcetype in Splunk to <source> Defaults to 'eventgen' if none specified.
383383

384384
host = <host>
385-
* ONLY VALID WITH outputMode SPLUNKSTREAM
386-
* Set event host in Splunk to <host>. Defaults to 127.0.0.1 if none specified.
385+
* When outputMode is splunkstream, set event host in Splunk to <host>.
386+
* When outputMode is syslogout and syslogAddHeader is set to true, add initial header with hostname <host>,
387+
see syslogAddHeader for details.
388+
* Defaults to 127.0.0.1 if none specified.
387389

388390
host.token = <regular expression>
389391
* PCRE expression used to identify the host name (or partial name) for replacement.
@@ -420,6 +422,14 @@ specifically be supported by all plugins. Plugins that write to files like spool
420422
* Only supports UDP ports
421423
* Required
422424

425+
syslogAddHeader = true | false
426+
* Controls whether syslog messages should be prefixed with an RFC3164 compliant header
427+
including the host value defined for the sample.
428+
* Useful in situations where you want to output generated events to syslog and make it
429+
possible for the receiving syslog server to use the sample's defined host value instead of
430+
the hostname of the host that eventgen is running on.
431+
* Defaults to false
432+
423433
###### tcpout
424434
tcpDestinationHost = <host>
425435
* Defaults to 127.0.0.1

docs/CONTRIBUTE_CODE.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,26 @@ If you want to contribute code to eventgen, please read over the following guide
55

66
## Pull request guidelines
77

8-
98
If you want to contribute to an eventgen repo, please use a GitHub pull request. This is the fastest way for us to evaluate your code and to merge it into the code base. Please don’t file an issue with snippets of code. Doing so means that we need to manually merge the changes in and update any appropriate tests. That decreases the likelihood that your code is going to get included in a timely manner. Please use pull requests.
109

10+
11+
## Release versioning guidelines
12+
13+
Major Release — Increment the first digit by 1 if the new features break backwards compatibility/current features
14+
15+
Minor Release — Increment the middle digit by 1 if the new features don’t break any existing features and are compatible with the app in it’s current state
16+
17+
Patch Release — Increment the last digit by 1 if you’re publishing bug/patch fixes to your app
18+
1119
### Get started
1220

1321
If you’d like to work on a pull request and you’ve never submitted code before, follow these steps:
1422
1. fork eventgen to your github workspace
1523
2. If you want to fix bugs or make enhancement, please make sure there is a issue in eventgen project. Refer [this guide](FILE_ISSUES.md) to create a issue.
1624

17-
1825
After that, you’re ready to start working on code.
1926

27+
2028
### Working on the code
2129

2230
The process of submitting a pull request is fairly straightforward and generally follows the same pattern each time:
@@ -75,6 +83,7 @@ The message summary should be a one-sentence description of the change, and it m
7583

7684
**Note**: please squash you changes in one commit before firing the pull request. One commit in one PR keeps the git history clean.
7785

86+
7887
#### Step 3: Rebase onto upstream
7988

8089
Before you send the pull request, be sure to rebase onto the upstream source. This ensures your code is running on the latest available code. We prefer rebase instead of merge when upstream changes. Rebase keeps the git history clearer.
@@ -83,6 +92,7 @@ git fetch upstream
8392
git rebase upstream/master
8493
```
8594

95+
8696
#### Step 4: Run the tests
8797

8898
The is a place holder as well. We should write about
@@ -101,6 +111,7 @@ Next, push your changes to your clone:
101111
git push origin fix/issue123
102112
```
103113

114+
104115
#### Step 6: Submit the pull request
105116

106117
Before creating a pull request, here are some recommended **check points**.
@@ -118,7 +129,6 @@ Next, create a pull request from your branch to the eventgen develop branch.
118129
Mark @lephino , @arctan5x , @jmeixensperger , @li-wu , @GordonWang as the reviewers.
119130

120131

121-
122132
## Code style and formatting tools
123133

124134
Since Eventgen is written in python, we apply a coding style based on [PEP8](https://www.python.org/dev/peps/pep-0008/).

docs/Gemfile.lock

+20-20
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
GEM
22
remote: https://rubygems.org/
33
specs:
4-
activesupport (4.2.10)
4+
activesupport (4.2.11.1)
55
i18n (~> 0.7)
66
minitest (~> 5.1)
77
thread_safe (~> 0.3, >= 0.3.4)
88
tzinfo (~> 1.1)
9-
addressable (2.5.2)
9+
addressable (2.6.0)
1010
public_suffix (>= 2.0.2, < 4.0)
1111
coffee-script (2.4.1)
1212
coffee-script-source
@@ -16,7 +16,7 @@ GEM
1616
commonmarker (0.17.13)
1717
ruby-enum (~> 0.5)
1818
concurrent-ruby (1.1.5)
19-
dnsruby (1.61.2)
19+
dnsruby (1.61.3)
2020
addressable (~> 2.5)
2121
em-websocket (0.5.1)
2222
eventmachine (>= 0.12.9)
@@ -27,13 +27,13 @@ GEM
2727
execjs (2.7.0)
2828
faraday (0.15.4)
2929
multipart-post (>= 1.2, < 3)
30-
ffi (1.10.0)
30+
ffi (1.11.1)
3131
forwardable-extended (2.6.0)
32-
gemoji (3.0.0)
33-
github-pages (197)
34-
activesupport (= 4.2.10)
32+
gemoji (3.0.1)
33+
github-pages (198)
34+
activesupport (= 4.2.11.1)
3535
github-pages-health-check (= 1.16.1)
36-
jekyll (= 3.7.4)
36+
jekyll (= 3.8.5)
3737
jekyll-avatar (= 0.6.0)
3838
jekyll-coffeescript (= 1.1.1)
3939
jekyll-commonmark-ghpages (= 0.1.5)
@@ -81,13 +81,13 @@ GEM
8181
octokit (~> 4.0)
8282
public_suffix (~> 3.0)
8383
typhoeus (~> 1.3)
84-
html-pipeline (2.10.0)
84+
html-pipeline (2.12.0)
8585
activesupport (>= 2)
8686
nokogiri (>= 1.4)
8787
http_parser.rb (0.6.0)
8888
i18n (0.9.5)
8989
concurrent-ruby (~> 1.0)
90-
jekyll (3.7.4)
90+
jekyll (3.8.5)
9191
addressable (~> 2.4)
9292
colorator (~> 1.0)
9393
em-websocket (~> 0.5)
@@ -204,39 +204,39 @@ GEM
204204
jekyll-feed (~> 0.9)
205205
jekyll-seo-tag (~> 2.1)
206206
minitest (5.11.3)
207-
multipart-post (2.0.0)
208-
nokogiri (1.10.2)
207+
multipart-post (2.1.1)
208+
nokogiri (1.10.4)
209209
mini_portile2 (~> 2.4.0)
210210
octokit (4.14.0)
211211
sawyer (~> 0.8.0, >= 0.5.3)
212212
pathutil (0.16.2)
213213
forwardable-extended (~> 2.6)
214-
public_suffix (3.0.3)
214+
public_suffix (3.1.1)
215215
rb-fsevent (0.10.3)
216216
rb-inotify (0.10.0)
217217
ffi (~> 1.0)
218218
rouge (2.2.1)
219219
ruby-enum (0.7.2)
220220
i18n
221221
ruby_dep (1.5.0)
222-
rubyzip (1.2.2)
222+
rubyzip (1.2.3)
223223
safe_yaml (1.0.5)
224-
sass (3.7.3)
224+
sass (3.7.4)
225225
sass-listen (~> 4.0.0)
226226
sass-listen (4.0.0)
227227
rb-fsevent (~> 0.9, >= 0.9.4)
228228
rb-inotify (~> 0.9, >= 0.9.7)
229-
sawyer (0.8.1)
230-
addressable (>= 2.3.5, < 2.6)
231-
faraday (~> 0.8, < 1.0)
229+
sawyer (0.8.2)
230+
addressable (>= 2.3.5)
231+
faraday (> 0.8, < 2.0)
232232
terminal-table (1.8.0)
233233
unicode-display_width (~> 1.1, >= 1.1.1)
234234
thread_safe (0.3.6)
235235
typhoeus (1.3.1)
236236
ethon (>= 0.9.0)
237237
tzinfo (1.2.5)
238238
thread_safe (~> 0.1)
239-
unicode-display_width (1.5.0)
239+
unicode-display_width (1.6.0)
240240

241241
PLATFORMS
242242
ruby
@@ -245,4 +245,4 @@ DEPENDENCIES
245245
github-pages
246246

247247
BUNDLED WITH
248-
2.0.1
248+
2.0.2

docs/PLUGINS.md

+48-42
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,37 @@ Plugins inherit from a base plugin class and are placed in their appropriate dir
1616
Let's take a look at the simplest plugin available to us, the Devnull output plugin:
1717

1818
```python
19-
from __future__ import division
2019
from outputplugin import OutputPlugin
21-
import sys
20+
from logging_config import logger
21+
2222

2323
class DevNullOutputPlugin(OutputPlugin):
24+
name = 'devnull'
2425
MAXQUEUELENGTH = 1000
26+
useOutputQueue = True
2527

26-
def __init__(self, sample):
27-
OutputPlugin.__init__(self, sample)
28+
def __init__(self, sample, output_counter=None):
29+
OutputPlugin.__init__(self, sample, output_counter)
2830
self.firsttime = True
2931

3032
def flush(self, q):
33+
logger.info('flush data to devnull')
3134
if self.firsttime:
3235
self.f = open('/dev/null', 'w')
36+
self.firsttime = False
3337
buf = '\n'.join(x['_raw'].rstrip() for x in q)
3438
self.f.write(buf)
3539

40+
3641
def load():
3742
"""Returns an instance of the plugin"""
3843
return DevNullOutputPlugin
44+
3945
```
4046

41-
First, we import the OutputPlugin superclass. For output plugins, they define a constant MAXQUEUELENGTH to determine the maximum amount of items in queue before forcing a queue flush.
47+
First, we import the OutputPlugin superclass. For output plugins, they define a constant `MAXQUEUELENGTH` to determine the maximum amount of items in queue before forcing a queue flush.
48+
49+
`useOutputQueue` is set to `True` here to use the output queue which functions as a reduce step when you need to maintain a single thread or a limited number of threads outputting data
4250

4351
``__init__()`` is very simple. It calls its superclass init and sets one variable, firsttime. ``flush()`` is also very simple.
4452
If it's the first time, open the file /dev/null, otherwise, output the queue by writing it to the already open file.
@@ -56,34 +64,34 @@ class SplunkStreamOutputPlugin(OutputPlugin):
5664
intSettings = [ 'splunkPort' ]
5765
```
5866

59-
MAXQUEUELENGTH should look normal, but these other class variables need a little explanation.
67+
`MAXQUEUELENGTH` should look normal, but these other class variables need a little explanation.
6068

6169
### Configuration Validation
6270
Config validation is a modular system in Eventgen, and plugins must be allowed to specify additional configuration parameters that the main Eventgen will consider valid and store.
63-
*Note that eventgen.conf.spec generation is not yet automated, which means plugins must ship with the default distribution and eventgen.conf.spec must be maintained manually.*
71+
> Note that `eventgen.conf.spec` generation is not yet automated, which means plugins must ship with the default distribution and eventgen.conf.spec must be maintained manually.
6472
Eventually spec file generation will be automated as well.
6573

6674
The main configuration of Eventgen validates itself by a list of configuration parameters assigned by type, and each of the configuration parameters is validated by that type.
6775
The settings list is required:
6876

69-
* validSettings | Defines the list of valid settings for this plugin
77+
* validSettings: Defines the list of valid settings for this plugin
7078

7179
The following lists are optional and likely to be used by many plugins:
7280

73-
* intSettings | Will validate the settings as integers
74-
* floatSettings | Will validate the settings as floating point numbers
75-
* boolSettings | Will validate the settings as booleans
76-
* jsonSettings | Will validate the settings as a JSON string
77-
* defaultableSettings | Settings which can be specified in the [global] stanza and will pass down to individual stanzas
78-
* complexSettings | A dictionary of lists or function callbacks, containing a setting name with list of valid options or a callback function to validate the setting.
81+
* intSettings: Will validate the settings as integers
82+
* floatSettings: Will validate the settings as floating point numbers
83+
* boolSettings: Will validate the settings as booleans
84+
* jsonSettings: Will validate the settings as a JSON string
85+
* defaultableSettings: Settings which can be specified in the [global] stanza and will pass down to individual stanzas
86+
* complexSettings: A dictionary of lists or function callbacks, containing a setting name with list of valid options or a callback function to validate the setting.
7987

8088
## Methods required per plugin type
8189

8290
Each plugin type will define a different method required.
8391

8492
**Plugin Type** | **Method** | **Returns** | **Notes**
8593
--- | --- | --- | ---
86-
Rater | ``rate()`` | Integer count of events to generate | n/a
94+
Rater | ``rate()`` | Integer count of events to generate | N/A
8795
Generator | ``gen(count, earliest, latest) `` | Success (0) | Events get put into an output queue by calling the Sample's ``send()`` or ``bulksend()`` methods in the output object.
8896
Output | ``flush(q)`` | Success (0) | Gets a deque list q to operate upon and output as configured.
8997

@@ -92,48 +100,46 @@ Output | ``flush(q)`` | Success (0) | Gets a deque list q to operate upon and ou
92100
We reviewed a simple Output Plugin earlier, let's look at a simple Generator Plugin:
93101

94102
```python
95-
from __future__ import division
103+
import datetime
104+
from datetime import timedelta
105+
96106
from generatorplugin import GeneratorPlugin
97-
import os
98-
import logging
99-
import datetime, time
100-
import itertools
101-
from collections import deque
107+
from logging_config import logger
108+
102109

103110
class WindbagGenerator(GeneratorPlugin):
104111
def __init__(self, sample):
105112
GeneratorPlugin.__init__(self, sample)
106113

107-
# Logger already setup by config, just get an instance
108-
logger = logging.getLogger('eventgen')
109-
globals()['logger'] = logger
110-
111-
from eventgenconfig import Config
112-
globals()['c'] = Config()
113-
114-
def gen(self, count, earliest, latest):
115-
l = [ {'_raw': '2014-01-05 23:07:08 WINDBAG Event 1 of 100000'} for i in xrange(count) ]
116-
117-
self._out.bulksend(l)
114+
def gen(self, count, earliest, latest, samplename=None):
115+
if count < 0:
116+
logger.warning('Sample size not found for count=-1 and generator=windbag, defaulting to count=60')
117+
count = 60
118+
time_interval = timedelta.total_seconds((latest - earliest)) / count
119+
for i in xrange(count):
120+
current_time_object = earliest + datetime.timedelta(0, time_interval * (i + 1))
121+
msg = '{0} -0700 WINDBAG Event {1} of {2}'.format(current_time_object, (i + 1), count)
122+
self._out.send(msg)
118123
return 0
119124

125+
120126
def load():
121127
return WindbagGenerator
128+
122129
```
123130

124-
For this generator plugin, notice we inherit from GeneratorPlugin instead of OutputPlugin. This plugin is also quite simple.
125-
In its ``__init__()`` method, it calls the superclass ``__init__()`` and it sets up two global variables, c, which holds the config
126-
(and is a Singleton pattern which can be instantiated many times) and a copy of the logger which we'll use for logging in most plugins.
131+
For this generator plugin, notice we inherit from `GeneratorPlugin` instead of `OutputPlugin`. This plugin is also quite simple.
127132

128-
Secondly, it defines a gen() method, which generates ``count`` events between ``earliest`` and ``latest`` time. In this case, we ignore the timestamp and return just event text.
129-
Then we call bulksend. This plugin has several performance optimizations: using a list constructor instead of a loop and using bulksend instead of send.
133+
Secondly, it defines a `gen()` method, which generates ``count`` events between ``earliest`` and ``latest`` time. In this case, we ignore the timestamp and return just event text.
134+
Then we call `bulksend`. This plugin has several performance optimizations: using a list constructor instead of a loop and using bulksend instead of send.
130135
Let's see how this could be implemented in a slightly less performant but easier to understand way:
131136

132137
```python
133-
def gen(self, count, earliest, latest):
134-
for x in xrange(count):
135-
self._sample.send({ '_raw': '2014-01-05 23:07:08 WINDBAG Event 1 of 100000' })
136-
138+
def gen(self, count, earliest, latest, samplename=None):
139+
for i in xrange(count):
140+
current_time_object = earliest + datetime.timedelta(0, time_interval * (i + 1))
141+
msg = '{0} -0700 WINDBAG Event {1} of {2}'.format(current_time_object, (i + 1), count)
142+
self._out.send(msg)
137143
return 0
138144
```
139145

@@ -142,4 +148,4 @@ Here, we use ``send()`` instead of ``bulksend()`` and a loop to make it easier t
142148
# Shipping a Plugin
143149

144150
When you've developed a plugin that you want to use in your app, shipping it with your app is easy.
145-
Place any Eventgen plugin in your Splunk app's ``bin/`` directory and we'll search for and find any plugins referenced by a ``outputMode``, ``generator`` or ``rater`` config statement.
151+
Place any Eventgen plugin in your Splunk app's ``bin/`` directory and we'll search for and find any plugins referenced by a ``outputMode``, ``generator`` or ``rater`` config statement.

docs/REFERENCE.md

+3
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ syslogDestinationPort = <port>
139139
* Defaults to port 1514
140140
* Only supports UDP ports
141141
142+
syslogAddHeader = true | false
143+
* Defaults to false
144+
142145
tcpDestinationHost = <host>
143146
* Defaults to 127.0.0.1
144147

splunk_eventgen/eventgen_api_server/eventgen_controller_api.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def gather_response(response_number_target=0):
3535
if not response_number_target:
3636
response_number_target = int(self.redis_connector.message_connection.pubsub_numsub(self.redis_connector.servers_channel)[0][1])
3737
response_num = 0
38-
countdown = 1.5 / self.interval
38+
countdown = 60 / self.interval
3939
for i in range(0, int(countdown)):
4040
if response_num == response_number_target:
4141
break

0 commit comments

Comments
 (0)